From 57e44face84d02870e7451f6c2cd741dd4c4c2bf Mon Sep 17 00:00:00 2001 From: greeng00se Date: Sat, 4 Nov 2023 11:06:20 +0000 Subject: [PATCH] deploy: 58b995fb64a5a21cb89542c19f5dcd72f7cd8299 --- 2022-retrospective.html | 8 +- 404.html | 4 +- accidental-duplication.html | 14 +- ...1a526.3199c893.js => 0571a526.5b85696b.js} | 2 +- ...37dbc.83c072d2.js => 08e37dbc.1ff31367.js} | 2 +- ...3a907.8661cb3c.js => 0e33a907.d81edb95.js} | 2 +- ...b58de.2b9af44d.js => 101b58de.2fd700f0.js} | 2 +- ...6fad7.e7249cac.js => 1236fad7.24b71e81.js} | 2 +- ...1d98b.8c5715bc.js => 1251d98b.9baae304.js} | 2 +- ...df38c.c25a1b6d.js => 130df38c.d6d4e2d6.js} | 2 +- ...c1923.1aa6fe97.js => 14dc1923.1659bee8.js} | 2 +- ...4646a.eba2ca7c.js => 1664646a.965e02af.js} | 2 +- ...719ab.0a2e8f52.js => 16f719ab.b3631b89.js} | 2 +- ...1b1c4.511d5aa4.js => 1781b1c4.21e20787.js} | 2 +- ...ecffe.de94e202.js => 1e8ecffe.564d76f3.js} | 2 +- ...5d14a.da3635f1.js => 1f05d14a.f5451368.js} | 2 +- ...1820a.d2fe9ecf.js => 1f61820a.6e34d588.js} | 2 +- ...94bbb.58721559.js => 21294bbb.f9fbadbd.js} | 2 +- ...9bc70.6793a550.js => 24b9bc70.d6ffdb3f.js} | 2 +- ...c40bf.bd9e249d.js => 26dc40bf.116a2dcb.js} | 2 +- ...faff0.bab1919e.js => 2a8faff0.1aef9017.js} | 2 +- ...f5501.313f53d8.js => 2c9f5501.5b78b3b1.js} | 2 +- ...fa616.f584e7ce.js => 327fa616.43d3c065.js} | 2 +- ...ccfe9.2d5d0a9f.js => 372ccfe9.560e7db1.js} | 2 +- ...4d232.a5b347e4.js => 3dd4d232.025b37fc.js} | 2 +- ...ea930.c12b117e.js => 3f6ea930.73dad3b0.js} | 2 +- ...57a8d.205e0091.js => 42957a8d.f8fb5118.js} | 2 +- ...5017c.9559a624.js => 4485017c.34771f44.js} | 2 +- ...c20a0.1a72b6ca.js => 448c20a0.55a75d0f.js} | 2 +- ...a6d0d.64dcde7c.js => 454a6d0d.94706a96.js} | 2 +- ...af148.251b0554.js => 48faf148.1717462a.js} | 2 +- ...c8300.cdb79bf0.js => 4a1c8300.e8eaab32.js} | 2 +- ...9a3c9.c3ac845d.js => 4b79a3c9.8e3e62d0.js} | 2 +- ...3abad.3e067cc0.js => 4d43abad.97a6cc5b.js} | 2 +- ...06a5f.17a5eda6.js => 52106a5f.a24ae46f.js} | 2 +- ...ffa4f.2cf34794.js => 530ffa4f.89118ba6.js} | 2 +- ...817cb.65f6a412.js => 537817cb.910a967a.js} | 2 +- ...73bed.c534c8ad.js => 5a473bed.0629687d.js} | 2 +- ...7bdab.54ff7247.js => 5c07bdab.bae264e4.js} | 2 +- ...cff52.e443e998.js => 5d4cff52.fade9e47.js} | 2 +- ...2f31f.46a2fccb.js => 6552f31f.7b26502f.js} | 2 +- ...5e9ab.aea6d3a6.js => 6675e9ab.2eb5bc04.js} | 2 +- ...4f6a4.2c404bfc.js => 6b54f6a4.b0d83dc8.js} | 2 +- ...85a52.b5af1364.js => 6f385a52.e1859e1c.js} | 2 +- ...34889.15e53e1e.js => 70834889.29b52f30.js} | 2 +- ...9c7ff.9f77b884.js => 7159c7ff.97797bc2.js} | 2 +- ...57f57.cd507c93.js => 72657f57.6d0bc2e8.js} | 2 +- ...88d5c.50416e9c.js => 73688d5c.124e0ac3.js} | 2 +- ...97f4e.6cfb3091.js => 79a97f4e.d4ad7d18.js} | 2 +- assets/js/814f3328.2e60c17f.js | 1 - assets/js/814f3328.e1e03de9.js | 1 + ...fa7b9.c29a2b79.js => 829fa7b9.893198b6.js} | 2 +- ...0c147.b6a4b7a3.js => 8720c147.5c511468.js} | 2 +- ...4850b.b479905c.js => 8a24850b.059ab89a.js} | 2 +- ...7aeff.2359b403.js => 8a27aeff.557abf1c.js} | 2 +- ...2f007.9b356e06.js => 8ad2f007.05e7e42b.js} | 2 +- ...ecccc.aeeb3c76.js => 905ecccc.63be6be2.js} | 2 +- ...de856.9c969003.js => 92ade856.dd26f1be.js} | 2 +- ...ef07b.fcbe78e8.js => 92fef07b.753706d5.js} | 2 +- ...3eac8.90a09cb8.js => 9b43eac8.65478c34.js} | 2 +- ...d5ae7.fa0f41bc.js => 9bad5ae7.eedb04d6.js} | 2 +- ...fd2b0.80d4a2ec.js => 9d1fd2b0.dffb724e.js} | 2 +- ...e3982.6ece4d4c.js => 9e2e3982.247afb43.js} | 2 +- ...14f73.63484f4e.js => a3614f73.a53a0551.js} | 2 +- ...d28a9.aacad7b2.js => a59d28a9.ad347984.js} | 2 +- ...0d533.89036d73.js => a710d533.ad456f4c.js} | 2 +- ...ba70f.18be7e46.js => a8cba70f.b05901e8.js} | 2 +- ...feabc.8863a050.js => aacfeabc.33e0e3f7.js} | 2 +- ...fdf5d.9c827f3a.js => ac3fdf5d.a14ec008.js} | 2 +- ...b7b62.f8707eac.js => ad3b7b62.16148c2a.js} | 2 +- ...2353f.77430c26.js => ae82353f.0d3e2a97.js} | 2 +- assets/js/b2b675dd.09e8d7a6.js | 1 + assets/js/b2b675dd.adafc1ef.js | 1 - ...8756c.4aff2828.js => b2c8756c.af1e0a2c.js} | 2 +- ...bb6fd.301d7a2d.js => b2ebb6fd.4d905b58.js} | 2 +- ...adc00.633c89b0.js => b41adc00.70ad5b86.js} | 2 +- ...fb0cb.4afb0eea.js => b6ffb0cb.13ba99fe.js} | 2 +- ...e0b37.f928003e.js => bace0b37.8f6c96e7.js} | 2 +- ...21eab.15e3f1c0.js => bb221eab.fe82a60c.js} | 2 +- ...d7e52.3be218d1.js => bbdd7e52.dcdab03d.js} | 2 +- ...db8ee.65f63b9c.js => bd4db8ee.912a9bad.js} | 2 +- ...97a8d.ef83736d.js => be497a8d.330d47db.js} | 2 +- ...17b3f.e63c57c6.js => c1b17b3f.ba398bfc.js} | 2 +- assets/js/c573638f.0c33f138.js | 1 - assets/js/c573638f.208f0fb2.js | 1 + ...04683.2f21610f.js => c6d04683.c9a2f336.js} | 2 +- ...229c3.5653afa0.js => cb6229c3.5e557995.js} | 2 +- ...19f63.46c3d20e.js => cc519f63.a2f54eb7.js} | 2 +- ...8cda1.c2b122c5.js => cd68cda1.fb88bddb.js} | 2 +- ...46b76.69423224.js => cef46b76.6d320653.js} | 2 +- ...e30d7.489aca7d.js => d28e30d7.c8b5ab46.js} | 2 +- ...0f5d9.668ec20f.js => d350f5d9.ebc27a24.js} | 2 +- ...b232a.61c24a0e.js => d5bb232a.a8801f4d.js} | 2 +- ...e25b7.04063c18.js => d65e25b7.d8647075.js} | 2 +- ...55594.3de2f6cf.js => d7955594.5a25bd6d.js} | 2 +- ...75059.f37a361d.js => d8775059.db70e9eb.js} | 2 +- ...f1d93.268aa82a.js => daff1d93.59c68117.js} | 2 +- ...6613e.2f8f2d5c.js => db86613e.1dbc4bdd.js} | 2 +- ...6a1e3.52680b40.js => dca6a1e3.e9780e39.js} | 2 +- ...47deb.ff087a25.js => df147deb.fd934096.js} | 2 +- ...7013c.f3d89c0c.js => dfc7013c.5b4d3dab.js} | 2 +- ...35da7.7747f2b7.js => e1735da7.b8fd0ff5.js} | 2 +- ...06456.e625e406.js => e1a06456.58ffb480.js} | 2 +- ...26195.c1345a1c.js => e2326195.07314e50.js} | 2 +- ...6ed43.a7a88c94.js => e6a6ed43.9f35502e.js} | 2 +- ...abc5d.fcb4962f.js => e9eabc5d.60ab3c19.js} | 2 +- ...1d58f.886bd191.js => eff1d58f.9a2d582c.js} | 2 +- ...cb3e2.536ef825.js => f06cb3e2.0fe3406d.js} | 2 +- ...de701.7bd01fad.js => f25de701.ca61418d.js} | 2 +- ...09a7e.dfd38fb7.js => f8409a7e.33b7f04e.js} | 2 +- ...bdf62.b1ec672d.js => f87bdf62.d26f8bee.js} | 2 +- ...d0c52.7f1a329c.js => f90d0c52.52a08709.js} | 2 +- ...d3942.73543988.js => fa3d3942.7d5090c3.js} | 2 +- ...c6c5e.8132bff2.js => ff4c6c5e.05d35921.js} | 2 +- .../js/{main.eea870a2.js => main.6df83e8f.js} | 4 +- ...CENSE.txt => main.6df83e8f.js.LICENSE.txt} | 0 ...n.32d2bfa9.js => runtime~main.46df1ef9.js} | 2 +- atom.xml | 4161 +++++++---------- blackjack-retrospective.html | 16 +- blog.html | Bin 13294 -> 13296 bytes book-leadership-and-self-deception.html | 12 +- book-writer.html | 10 +- chess-retrospective.html | 14 +- cloudwatch.html | 8 +- composite.html | 12 +- custom-jdbc-template.html | 8 +- db-replication.html | 10 +- docs.html | 6 +- .../virtical-slice-architecture.html | 4 +- docs/book/getting-out-of-the-box.html | 4 +- docs/culture/postmortem.html | 4 +- docs/database/maximumPoolSize.html | 4 +- docs/database/query-execution.html | 4 +- docs/deploy/zero-downtime.html | 4 +- docs/design/package.html | 4 +- docs/etc/communication.html | 4 +- docs/etc/develop-with-spring.html | 4 +- docs/etc/experience-and-self-question.html | 4 +- docs/etc/healthful-growth.html | 4 +- docs/java/sequenced-collection.html | 4 +- docs/jpa/key.html | 4 +- docs/linux/shell.html | 4 +- docs/linux/swap.html | 4 +- docs/mac/java.html | 4 +- docs/monitoring/intro.html | 4 +- docs/network/load-balancing-algorithm.html | 4 +- docs/network/load-balancing.html | 4 +- docs/nginx/command.html | 4 +- docs/nginx/static-file.html | 4 +- docs/performance/throughput-latency.html | 4 +- docs/performance/throughput.html | 4 +- docs/performance/types.html | 4 +- docs/spring/essence.html | 4 +- docs/tags.html | 4 +- docs/tags/architecture.html | 4 +- docs/tags/book.html | 4 +- docs/tags/collection.html | 4 +- docs/tags/deploy.html | 4 +- docs/tags/etc.html | 4 +- docs/tags/java.html | 4 +- docs/tags/jpa.html | 4 +- docs/tags/latency.html | 4 +- docs/tags/load-balancing.html | 4 +- docs/tags/monitoring.html | 4 +- docs/tags/network.html | 4 +- docs/tags/nginx.html | 4 +- docs/tags/package.html | 4 +- docs/tags/performance.html | 4 +- docs/tags/postmortem.html | 4 +- docs/tags/sequenced.html | 4 +- docs/tags/spring.html | 4 +- docs/tags/test.html | 4 +- docs/tags/throughput.html | 4 +- docs/tags/zero-downtime.html | 4 +- docs/test/benefit.html | 4 +- docs/test/first.html | 4 +- docs/test/heuristics.html | 4 +- docs/test/stairstep.html | 4 +- docusaurus.html | 10 +- grasp.html | 12 +- index.html | 4 +- innodb-lock.html | 8 +- intellij-settings.html | 8 +- java-class-file.html | 12 +- java-spring-springboot.html | 12 +- jdbc-retrospective.html | 8 +- jenkins.html | 8 +- jsr-310.html | 8 +- kotlin-null.html | 10 +- ladder-retrospective.html | 16 +- level2-interview-retrospective.html | 8 +- log-async-exception.html | 12 +- mock-static-method.html | 10 +- mvc-retrospective.html | 10 +- mysql-lock.html | 12 +- order-retrospective.html | 10 +- page/10.html | 87 +- page/11.html | 177 +- page/12.html | 285 +- page/13.html | 260 +- page/14.html | 512 +- page/15.html | 113 +- page/16.html | 96 +- page/17.html | 217 +- page/18.html | 122 +- page/19.html | 412 +- page/2.html | 116 +- page/20.html | 95 +- page/21.html | 84 +- page/22.html | 271 +- page/23.html | 79 +- page/24.html | 142 +- page/25.html | 113 +- page/26.html | 14 +- page/27.html | 115 +- page/28.html | 142 +- page/29.html | 79 +- page/3.html | 157 +- page/30.html | 271 +- page/31.html | 84 +- page/32.html | 95 +- page/33.html | 412 +- page/34.html | 122 +- page/35.html | 217 +- page/36.html | 96 +- page/37.html | 113 +- page/38.html | 512 +- page/39.html | 260 +- page/4.html | 115 +- page/40.html | 285 +- page/41.html | 177 +- page/42.html | 87 +- page/43.html | 528 ++- page/44.html | 124 +- page/45.html | 272 +- page/46.html | 100 +- page/47.html | 128 +- page/48.html | 115 +- page/49.html | 157 +- page/5.html | 128 +- page/50.html | 116 +- page/51.html | 100 +- page/6.html | 100 +- page/7.html | 272 +- page/8.html | 124 +- page/9.html | 528 +-- parameterized-tests.html | 10 +- performance-test-type.html | 14 +- racing-car-retrospective.html | 12 +- refactoring-retrospective.html | 14 +- route-image-async-with-event.html | 8 +- route-image-implementation.html | 10 +- route-image-intro.html | 10 +- route-image-python.html | 10 +- rss.xml | 4161 +++++++---------- search.html | 4 +- shopping-cart-retrospective.html | 12 +- spring-test-isolation.html | 8 +- subway-retrospective.html | 12 +- tags.html | 6 +- tags/async.html | 271 +- tags/async/page/2.html | 271 +- tags/awt.html | 235 +- tags/awt/page/2.html | 235 +- tags/book.html | 73 +- tags/book/page/2.html | 8 +- tags/book/page/3.html | 73 +- tags/class.html | 10 +- tags/cloudwatch.html | 8 +- tags/composite.html | 10 +- tags/data-base.html | 188 +- tags/data-base/page/2.html | 8 +- tags/data-base/page/3.html | 188 +- tags/documentation.html | 8 +- tags/dto.html | 12 +- tags/elastic-beanstalk.html | 6 +- tags/event.html | 8 +- tags/exception.html | 8 +- tags/grasp.html | 14 +- tags/image.html | 235 +- tags/image/page/2.html | 8 +- tags/image/page/3.html | 235 +- tags/inno-db.html | 8 +- tags/intelli-j.html | 6 +- tags/isolation.html | 8 +- tags/java.html | 125 +- tags/java/page/2.html | 156 +- tags/java/page/3.html | 6 +- tags/java/page/4.html | 156 +- tags/java/page/5.html | 125 +- tags/jdbc.html | 6 +- tags/jenkins.html | 6 +- tags/kotlin.html | 8 +- tags/lock.html | 118 +- tags/lock/page/2.html | 118 +- tags/log.html | 10 +- tags/mock.html | 10 +- tags/mockito.html | 6 +- tags/monitoring.html | 8 +- tags/my-sql.html | 8 +- tags/mysql.html | 12 +- tags/oop.html | 14 +- tags/pattern.html | 10 +- tags/performance-test.html | 8 +- tags/python.html | 10 +- tags/replication.html | 10 +- tags/retrospective.html | 88 +- tags/retrospective/page/10.html | 113 +- tags/retrospective/page/11.html | 113 +- tags/retrospective/page/12.html | 74 +- tags/retrospective/page/13.html | 112 +- tags/retrospective/page/14.html | 84 +- tags/retrospective/page/15.html | 94 +- tags/retrospective/page/16.html | 111 +- tags/retrospective/page/17.html | 254 +- tags/retrospective/page/18.html | 216 +- tags/retrospective/page/19.html | 158 +- tags/retrospective/page/2.html | 158 +- tags/retrospective/page/20.html | 88 +- tags/retrospective/page/3.html | 216 +- tags/retrospective/page/4.html | 254 +- tags/retrospective/page/5.html | 111 +- tags/retrospective/page/6.html | 94 +- tags/retrospective/page/7.html | 84 +- tags/retrospective/page/8.html | 112 +- tags/retrospective/page/9.html | 74 +- tags/spring-boot.html | 8 +- tags/spring.html | 10 +- tags/static.html | 6 +- tags/teco-chat.html | 88 +- tags/teco-chat/page/2.html | 10 +- tags/teco-chat/page/3.html | 88 +- tags/test.html | 127 +- tags/test/page/2.html | 127 +- tags/time.html | 8 +- tags/transaction.html | 12 +- tags/web-application.html | 12 +- tags/web-socket.html | 6 +- tags/woowahan-techcourse.html | 140 +- tags/woowahan-techcourse/page/10.html | 67 +- tags/woowahan-techcourse/page/11.html | 66 +- tags/woowahan-techcourse/page/12.html | 105 +- tags/woowahan-techcourse/page/13.html | 278 +- tags/woowahan-techcourse/page/14.html | 140 +- tags/woowahan-techcourse/page/15.html | 204 +- tags/woowahan-techcourse/page/16.html | 140 +- tags/woowahan-techcourse/page/2.html | 204 +- tags/woowahan-techcourse/page/3.html | 140 +- tags/woowahan-techcourse/page/4.html | 278 +- tags/woowahan-techcourse/page/5.html | 105 +- tags/woowahan-techcourse/page/6.html | 66 +- tags/woowahan-techcourse/page/7.html | 67 +- tags/woowahan-techcourse/page/8.html | 137 +- tags/woowahan-techcourse/page/9.html | 137 +- tecochat-retrospective-1.html | 12 +- tecochat-retrospective-2.html | 8 +- tecochat-retrospective-3.html | 12 +- test-double.html | 12 +- the-essence-of-object-orientation.html | 12 +- tomcat-retrospective.html | 10 +- transaction-and-isolation.html | 10 +- web-application-evolution.html | 16 +- web-racing-car-retrospective.html | 14 +- websocket.html | 12 +- woowacourse-level1-retrospective.html | 16 +- woowacourse-level2-retrospective.html | 8 +- woowacourse-level3-retrospective.html | 8 +- 367 files changed, 12764 insertions(+), 14334 deletions(-) rename assets/js/{0571a526.3199c893.js => 0571a526.5b85696b.js} (97%) rename assets/js/{08e37dbc.83c072d2.js => 08e37dbc.1ff31367.js} (97%) rename assets/js/{0e33a907.8661cb3c.js => 0e33a907.d81edb95.js} (97%) rename assets/js/{101b58de.2b9af44d.js => 101b58de.2fd700f0.js} (95%) rename assets/js/{1236fad7.e7249cac.js => 1236fad7.24b71e81.js} (99%) rename assets/js/{1251d98b.8c5715bc.js => 1251d98b.9baae304.js} (98%) rename assets/js/{130df38c.c25a1b6d.js => 130df38c.d6d4e2d6.js} (98%) rename assets/js/{14dc1923.1aa6fe97.js => 14dc1923.1659bee8.js} (94%) rename assets/js/{1664646a.eba2ca7c.js => 1664646a.965e02af.js} (98%) rename assets/js/{16f719ab.0a2e8f52.js => 16f719ab.b3631b89.js} (98%) rename assets/js/{1781b1c4.511d5aa4.js => 1781b1c4.21e20787.js} (98%) rename assets/js/{1e8ecffe.de94e202.js => 1e8ecffe.564d76f3.js} (99%) rename assets/js/{1f05d14a.da3635f1.js => 1f05d14a.f5451368.js} (99%) rename assets/js/{1f61820a.d2fe9ecf.js => 1f61820a.6e34d588.js} (97%) rename assets/js/{21294bbb.58721559.js => 21294bbb.f9fbadbd.js} (97%) rename assets/js/{24b9bc70.6793a550.js => 24b9bc70.d6ffdb3f.js} (97%) rename assets/js/{26dc40bf.bd9e249d.js => 26dc40bf.116a2dcb.js} (98%) rename assets/js/{2a8faff0.bab1919e.js => 2a8faff0.1aef9017.js} (70%) rename assets/js/{2c9f5501.313f53d8.js => 2c9f5501.5b78b3b1.js} (98%) rename assets/js/{327fa616.f584e7ce.js => 327fa616.43d3c065.js} (98%) rename assets/js/{372ccfe9.2d5d0a9f.js => 372ccfe9.560e7db1.js} (99%) rename assets/js/{3dd4d232.a5b347e4.js => 3dd4d232.025b37fc.js} (97%) rename assets/js/{3f6ea930.c12b117e.js => 3f6ea930.73dad3b0.js} (97%) rename assets/js/{42957a8d.205e0091.js => 42957a8d.f8fb5118.js} (97%) rename assets/js/{4485017c.9559a624.js => 4485017c.34771f44.js} (97%) rename assets/js/{448c20a0.1a72b6ca.js => 448c20a0.55a75d0f.js} (97%) rename assets/js/{454a6d0d.64dcde7c.js => 454a6d0d.94706a96.js} (98%) rename assets/js/{48faf148.251b0554.js => 48faf148.1717462a.js} (97%) rename assets/js/{4a1c8300.cdb79bf0.js => 4a1c8300.e8eaab32.js} (97%) rename assets/js/{4b79a3c9.c3ac845d.js => 4b79a3c9.8e3e62d0.js} (98%) rename assets/js/{4d43abad.3e067cc0.js => 4d43abad.97a6cc5b.js} (97%) rename assets/js/{52106a5f.17a5eda6.js => 52106a5f.a24ae46f.js} (94%) rename assets/js/{530ffa4f.2cf34794.js => 530ffa4f.89118ba6.js} (99%) rename assets/js/{537817cb.65f6a412.js => 537817cb.910a967a.js} (95%) rename assets/js/{5a473bed.c534c8ad.js => 5a473bed.0629687d.js} (98%) rename assets/js/{5c07bdab.54ff7247.js => 5c07bdab.bae264e4.js} (97%) rename assets/js/{5d4cff52.e443e998.js => 5d4cff52.fade9e47.js} (98%) rename assets/js/{6552f31f.46a2fccb.js => 6552f31f.7b26502f.js} (97%) rename assets/js/{6675e9ab.aea6d3a6.js => 6675e9ab.2eb5bc04.js} (97%) rename assets/js/{6b54f6a4.2c404bfc.js => 6b54f6a4.b0d83dc8.js} (98%) rename assets/js/{6f385a52.b5af1364.js => 6f385a52.e1859e1c.js} (98%) rename assets/js/{70834889.15e53e1e.js => 70834889.29b52f30.js} (97%) rename assets/js/{7159c7ff.9f77b884.js => 7159c7ff.97797bc2.js} (99%) rename assets/js/{72657f57.cd507c93.js => 72657f57.6d0bc2e8.js} (97%) rename assets/js/{73688d5c.50416e9c.js => 73688d5c.124e0ac3.js} (99%) rename assets/js/{79a97f4e.6cfb3091.js => 79a97f4e.d4ad7d18.js} (96%) delete mode 100644 assets/js/814f3328.2e60c17f.js create mode 100644 assets/js/814f3328.e1e03de9.js rename assets/js/{829fa7b9.c29a2b79.js => 829fa7b9.893198b6.js} (97%) rename assets/js/{8720c147.b6a4b7a3.js => 8720c147.5c511468.js} (98%) rename assets/js/{8a24850b.b479905c.js => 8a24850b.059ab89a.js} (98%) rename assets/js/{8a27aeff.2359b403.js => 8a27aeff.557abf1c.js} (96%) rename assets/js/{8ad2f007.9b356e06.js => 8ad2f007.05e7e42b.js} (97%) rename assets/js/{905ecccc.aeeb3c76.js => 905ecccc.63be6be2.js} (99%) rename assets/js/{92ade856.9c969003.js => 92ade856.dd26f1be.js} (99%) rename assets/js/{92fef07b.fcbe78e8.js => 92fef07b.753706d5.js} (98%) rename assets/js/{9b43eac8.90a09cb8.js => 9b43eac8.65478c34.js} (96%) rename assets/js/{9bad5ae7.fa0f41bc.js => 9bad5ae7.eedb04d6.js} (98%) rename assets/js/{9d1fd2b0.80d4a2ec.js => 9d1fd2b0.dffb724e.js} (96%) rename assets/js/{9e2e3982.6ece4d4c.js => 9e2e3982.247afb43.js} (97%) rename assets/js/{a3614f73.63484f4e.js => a3614f73.a53a0551.js} (98%) rename assets/js/{a59d28a9.aacad7b2.js => a59d28a9.ad347984.js} (98%) rename assets/js/{a710d533.89036d73.js => a710d533.ad456f4c.js} (99%) rename assets/js/{a8cba70f.18be7e46.js => a8cba70f.b05901e8.js} (98%) rename assets/js/{aacfeabc.8863a050.js => aacfeabc.33e0e3f7.js} (98%) rename assets/js/{ac3fdf5d.9c827f3a.js => ac3fdf5d.a14ec008.js} (98%) rename assets/js/{ad3b7b62.f8707eac.js => ad3b7b62.16148c2a.js} (97%) rename assets/js/{ae82353f.77430c26.js => ae82353f.0d3e2a97.js} (97%) create mode 100644 assets/js/b2b675dd.09e8d7a6.js delete mode 100644 assets/js/b2b675dd.adafc1ef.js rename assets/js/{b2c8756c.4aff2828.js => b2c8756c.af1e0a2c.js} (97%) rename assets/js/{b2ebb6fd.301d7a2d.js => b2ebb6fd.4d905b58.js} (98%) rename assets/js/{b41adc00.633c89b0.js => b41adc00.70ad5b86.js} (97%) rename assets/js/{b6ffb0cb.4afb0eea.js => b6ffb0cb.13ba99fe.js} (98%) rename assets/js/{bace0b37.f928003e.js => bace0b37.8f6c96e7.js} (98%) rename assets/js/{bb221eab.15e3f1c0.js => bb221eab.fe82a60c.js} (97%) rename assets/js/{bbdd7e52.3be218d1.js => bbdd7e52.dcdab03d.js} (97%) rename assets/js/{bd4db8ee.65f63b9c.js => bd4db8ee.912a9bad.js} (99%) rename assets/js/{be497a8d.ef83736d.js => be497a8d.330d47db.js} (99%) rename assets/js/{c1b17b3f.e63c57c6.js => c1b17b3f.ba398bfc.js} (98%) delete mode 100644 assets/js/c573638f.0c33f138.js create mode 100644 assets/js/c573638f.208f0fb2.js rename assets/js/{c6d04683.2f21610f.js => c6d04683.c9a2f336.js} (98%) rename assets/js/{cb6229c3.5653afa0.js => cb6229c3.5e557995.js} (97%) rename assets/js/{cc519f63.46c3d20e.js => cc519f63.a2f54eb7.js} (99%) rename assets/js/{cd68cda1.c2b122c5.js => cd68cda1.fb88bddb.js} (97%) rename assets/js/{cef46b76.69423224.js => cef46b76.6d320653.js} (98%) rename assets/js/{d28e30d7.489aca7d.js => d28e30d7.c8b5ab46.js} (99%) rename assets/js/{d350f5d9.668ec20f.js => d350f5d9.ebc27a24.js} (70%) rename assets/js/{d5bb232a.61c24a0e.js => d5bb232a.a8801f4d.js} (98%) rename assets/js/{d65e25b7.04063c18.js => d65e25b7.d8647075.js} (98%) rename assets/js/{d7955594.3de2f6cf.js => d7955594.5a25bd6d.js} (98%) rename assets/js/{d8775059.f37a361d.js => d8775059.db70e9eb.js} (98%) rename assets/js/{daff1d93.268aa82a.js => daff1d93.59c68117.js} (97%) rename assets/js/{db86613e.2f8f2d5c.js => db86613e.1dbc4bdd.js} (97%) rename assets/js/{dca6a1e3.52680b40.js => dca6a1e3.e9780e39.js} (97%) rename assets/js/{df147deb.ff087a25.js => df147deb.fd934096.js} (98%) rename assets/js/{dfc7013c.f3d89c0c.js => dfc7013c.5b4d3dab.js} (98%) rename assets/js/{e1735da7.7747f2b7.js => e1735da7.b8fd0ff5.js} (98%) rename assets/js/{e1a06456.e625e406.js => e1a06456.58ffb480.js} (98%) rename assets/js/{e2326195.c1345a1c.js => e2326195.07314e50.js} (97%) rename assets/js/{e6a6ed43.a7a88c94.js => e6a6ed43.9f35502e.js} (98%) rename assets/js/{e9eabc5d.fcb4962f.js => e9eabc5d.60ab3c19.js} (98%) rename assets/js/{eff1d58f.886bd191.js => eff1d58f.9a2d582c.js} (98%) rename assets/js/{f06cb3e2.536ef825.js => f06cb3e2.0fe3406d.js} (99%) rename assets/js/{f25de701.7bd01fad.js => f25de701.ca61418d.js} (98%) rename assets/js/{f8409a7e.dfd38fb7.js => f8409a7e.33b7f04e.js} (97%) rename assets/js/{f87bdf62.b1ec672d.js => f87bdf62.d26f8bee.js} (98%) rename assets/js/{f90d0c52.7f1a329c.js => f90d0c52.52a08709.js} (98%) rename assets/js/{fa3d3942.73543988.js => fa3d3942.7d5090c3.js} (99%) rename assets/js/{ff4c6c5e.8132bff2.js => ff4c6c5e.05d35921.js} (98%) rename assets/js/{main.eea870a2.js => main.6df83e8f.js} (73%) rename assets/js/{main.eea870a2.js.LICENSE.txt => main.6df83e8f.js.LICENSE.txt} (100%) rename assets/js/{runtime~main.32d2bfa9.js => runtime~main.46df1ef9.js} (70%) diff --git a/2022-retrospective.html b/2022-retrospective.html index 4741b9af6..ee443683f 100644 --- a/2022-retrospective.html +++ b/2022-retrospective.html @@ -13,11 +13,11 @@ - - + + -
본문으로 건너뛰기

2022년 회고

· 약 4분

적당한 전환점, 2022년을 돌아보며

+

2022년 회고

· 약 4분

적당한 전환점, 2022년을 돌아보며

전역

약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

@@ -44,6 +44,6 @@

우아한 테크코스

우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

2023년에는

마음의 여유가 없었던 2022년이었던 것 같다.
-하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

+하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

\ No newline at end of file diff --git a/404.html b/404.html index 15fe9fbb8..388b691da 100644 --- a/404.html +++ b/404.html @@ -13,8 +13,8 @@ - - + +
본문으로 건너뛰기

페이지를 찾을 수 없습니다.

원하는 페이지를 찾을 수 없습니다.

사이트 관리자에게 링크가 깨진 것을 알려주세요.

diff --git a/accidental-duplication.html b/accidental-duplication.html index b335102c1..5f8bd9d33 100644 --- a/accidental-duplication.html +++ b/accidental-duplication.html @@ -13,11 +13,11 @@ - - + + -
본문으로 건너뛰기

중복과 우발적 중복

· 약 8분

장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
+

중복과 우발적 중복

· 약 8분

장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
요청에 담긴 Body를 통해 전달받은 값을 DTO로 매핑하여 추가와 수정을 했다.

장바구니 미션에서의 상품 추가 및 수정

중복1

@@ -26,7 +26,7 @@

장바구니 미 위 경우는 중복일까? 중복이 아닐까?

이 부분에 대해서 다음과 같은 리뷰를 받았다.

-

ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

+

ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

질문에 대해 아래와 같이 답변을 했다.

@@ -43,7 +43,7 @@

중복과 우발적 중복

하나로 사용하는 건 안좋아보이고, 중복은 제거하고 싶은 마음

지금은 추가, 수정 2가지 경우 밖에 없지만 조금 더 복잡한 요구사항이 주어져서 10가지 경우로 입력을 받으면 어떻게 해야할까?
서비스 계층에서도 계층의 분리를 위해서 다른 DTO를 사용하고 있다면 20개의 DTO를 만들어야 할까?
-리뷰어가 알려준 의존 역전을 이용한 방법을 통해 이를 해결해보자!

+리뷰어가 알려준 의존 역전을 이용한 방법을 통해 이를 해결해보자!

중복 제거 전 코드

현재 코드에서는 아래와 같은 구조로 되어있다.
Controller와 Service에서 저장, 수정할 때 각각의 DTO를 사용하고 있다. @@ -86,7 +86,7 @@

인터페이스 작성하기

구현체 작성하기

중복4

위에서 작성한 인터페이스를 구현하는 클래스를 작성한다.
-요청은 ProductRequest 클래스로 받고, 서비스에 전달할 땐 해당 인터페이스의 명세만 맞추면 문제없이 사용할 수 있다.

+요청은 ProductRequest 클래스로 받고, 서비스에 전달할 땐 해당 인터페이스의 명세만 맞추면 문제없이 사용할 수 있다.

├── controller
 │   ├── ProductController
 │   └── ProductRequest
@@ -148,6 +148,6 @@ 

정리

참고 자료

클린 아키텍처 16장 독립성, 로버트 C. 마틴
https://techblog.woowahan.com/2647/
-https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/

+https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/

\ No newline at end of file diff --git a/assets/js/0571a526.3199c893.js b/assets/js/0571a526.5b85696b.js similarity index 97% rename from assets/js/0571a526.3199c893.js rename to assets/js/0571a526.5b85696b.js index 4db29db90..1d250e594 100644 --- a/assets/js/0571a526.3199c893.js +++ b/assets/js/0571a526.5b85696b.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6204],{93516:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var r=n(85893),s=n(3905);const i={title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",slug:"performance-test-type",tags:["performance test"]},a=void 0,o={permalink:"/performance-test-type",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",source:"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",description:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8",date:"2023-09-10T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 10\uc77c",tags:[{label:"performance test",permalink:"/tags/performance-test"}],readingTime:5.8,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",slug:"performance-test-type",tags:["performance test"]},unlisted:!1,prevItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"},nextItem:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",permalink:"/db-replication"}},l={authorsImageUrls:[]},c=[{value:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8",id:"\uc131\ub2a5-\ud14c\uc2a4\ud2b8",level:2},{value:"\uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)",id:"\uc2a4\ubaa8\ud06c-\ud14c\uc2a4\ud2b8smoke-test",level:3},{value:"\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)",id:"\uc2a4\ud30c\uc774\ud06c-\ud14c\uc2a4\ud2b8spike-test",level:3},{value:"\ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)",id:"\ubd80\ud558-\ud14c\uc2a4\ud2b8load-test",level:3},{value:"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test)",id:"\uc2a4\ud2b8\ub808\uc2a4-\ud14c\uc2a4\ud2b8stress-test",level:3},{value:"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test)",id:"\ub0b4\uad6c-\ud14c\uc2a4\ud2b8endurance-test",level:3},{value:"\uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)",id:"\uc911\ub2e8\uc810-\ud14c\uc2a4\ud2b8breakpoint-test",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",h2:"h2",h3:"h3",img:"img",p:"p",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h2,{id:"\uc131\ub2a5-\ud14c\uc2a4\ud2b8",children:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsx)(t.p,{children:"API\uc758 \uc694\uccad\uc774 \ub9ce\uc740 \uc0c1\ud669\uc5d0\uc11c \uc11c\ubc84\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2dc\uc2a4\ud15c\uc5d0 \ubd80\ud558\uac00 \uac78\ub9ac\uba74 \ubb38\uc81c \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\uc591\ud55c \uc0c1\ud669\uc5d0 \ub300\ube44\ud574\uc11c \uc131\ub2a5 \ud14c\uc2a4\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"./test.png",src:n(38715).Z+"",width:"2168",height:"1002"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ubaa8\ud06c-\ud14c\uc2a4\ud2b8smoke-test",children:"\uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ucd5c\uc18c\ud55c\uc758 \ubd80\ud558\ub97c \uc8fc\uc5b4 \uc2dc\uc2a4\ud15c\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["VU\ub97c \ucd5c\uc18c\ud55c\uc73c\ub85c \ub450\uace0, \uc9e7\uc740 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \ud14c\uc2a4\ud2b8\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud568\uc73c\ub85c\uc368 \ud14c\uc2a4\ud2b8 \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc624\ub958\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uace0, \uc131\ub2a5 \uc9c0\ud45c\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc9d1, \ubaa8\ub2c8\ud130\ub9c1 \ub418\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"\uac00\uc0c1 \uc0ac\uc6a9\uc790(VU)",type:"note",children:(0,r.jsxs)(t.p,{children:["\uac00\uc0c1 \uc0ac\uc6a9\uc790\ub294 \uc11c\ubc84 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ub300\ud574 \ud2b9\uc815 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \ub2e4\ub978 \uac00\uc0c1 \uc0ac\uc6a9\uc790\uc640 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uba70, \uc5ec\ub7ec \uac00\uc0c1 \uc0ac\uc6a9\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc2dc \uc5f0\uacb0\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ub808\ub4dc\ub77c\uace0 \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud30c\uc774\ud06c-\ud14c\uc2a4\ud2b8spike-test",children:"\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc0ac\uc6a9\ub7c9\uc774 \uae09\uc99d\ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uacac\ub514\uace0 \uc131\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ud2f0\ucf13 \ubc1c\uae09, \ud560\uc778 \ucfe0\ud3f0 \ubc1c\uae09\uacfc \uac19\uc740 \uc774\ubca4\ud2b8\ub97c \ud558\ub294 \uacbd\uc6b0 \ub300\uaddc\ubaa8 \ud2b8\ub798\ud53d\uc774 \ub4e4\uc5b4\uc628\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uae09\uc99d\ud558\ub294 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\uace0, \ubd80\ud558\ub97c \uc798 \ubc84\ud2f0\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ubd80\ud558-\ud14c\uc2a4\ud2b8load-test",children:"\ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ubaa9\ud46f\uac12\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \uacac\ub51c \uc218 \uc788\uc744\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uc77c\ubc18\uc801\uc778 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub7a8\ud504\uc5c5 \ub610\ub294 \ubb19\ud46f\uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ubd80\ud558 \uae30\uac04\ub3d9\uc548 \uc131\ub2a5\uc774 \ubb38\uc81c\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uace0, \uc2dc\uc2a4\ud15c \ubcc0\uacbd \ud6c4\uc5d0\ub3c4 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ub3d9\uc77c\ud558\uac8c \ubaa9\ud46f\uac12\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"\ub7a8\ud504 \uc5c5(Ramp-up)",type:"note",children:(0,r.jsx)(t.p,{children:"\ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574 \uc124\uc815\ud55c \uac00\uc0c1 \uc0ac\uc6a9\uc790 \uc218\uc5d0 \ub3c4\ub2ec\ud558\ub294 \ub370 \uac78\ub9ac\ub294 \uc2dc\uac04"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud2b8\ub808\uc2a4-\ud14c\uc2a4\ud2b8stress-test",children:"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc2dc\uc2a4\ud15c\uc758 \ucd5c\ub300\uce58\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \ubc1b\uc558\uc744 \ub54c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uadf8\ub798\ud504\ub97c \ubd24\uc744 \ub54c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc640 \uc720\uc0ac\ud55c \ud615\ud0dc\ub85c \ubcf4\uc774\uc9c0\ub9cc, \ubd80\ud558\ub7c9\uc774 \ub2e4\ub974\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c \ud3c9\uade0\uc801\uc778 \ubaa9\ud46f\uac12 \ub300\ube44 \uc791\uac8c\ub294 50% \uc774\uc0c1, \ud544\uc694\uc758 \uacbd\uc6b0 \uadf8 \uc774\uc0c1\uc73c\ub85c \ubd80\ud558\ub97c \uc900\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub294 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c \ud6c4\uc5d0\ub9cc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4. \ubd80\ud558 \ud14c\uc2a4\ud2b8\uac00 \uc774\ub8e8\uc5b4\uc9c0\uc9c0 \uc54a\uc740 \uc0c1\ud669\uc5d0\uc11c \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \ubcd1\ubaa9 \uc9c0\uc810\uc774\ub098 \ubb38\uc81c \uc0c1\ud669\uc744 \ucc3e\uae30 \uc5b4\ub824\uc6cc\uc9c4\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub610\ud55c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c VU\uac12(\uc2a4\ub808\ub4dc \uc218)\ub9cc \uc218\uc815\ud558\uc5ec \uc7ac\uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ub0b4\uad6c-\ud14c\uc2a4\ud2b8endurance-test",children:"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ud3c9\uade0 \uc0ac\uc6a9\ub960\ub85c \uc77c\uc815 \ubd80\ud558\ub97c \uc9c0\uc18d\uc801\uc73c\ub85c \uc8fc\uba70 \uc2dc\uc2a4\ud15c\uc774 \ubb38\uc81c\ub418\ub294 \uc9c0\uc810\uc744 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ud761\uc218 \ud14c\uc2a4\ud2b8(Soak Test)\ub77c\uace0\ub3c4 \ud558\uba70, \uae30\ubcf8\uc801\uc778 \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc758 \ubcc0\ud615\uc774\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc640 \ub2ec\ub9ac \uae34 \uc2dc\uac04\ub3d9\uc548 \ud14c\uc2a4\ud2b8\ub97c \ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\uba70, \uba54\ubaa8\ub9ac \ub204\uc218 \ubb38\uc81c\uc640 \uac19\uc774 \uc7a5\uc2dc\uac04 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud560 \ub54c \uc2dc\uc2a4\ud15c\uc758 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \ubd80\ubd84\uc744 \ud655\uc778\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc911\ub2e8\uc810-\ud14c\uc2a4\ud2b8breakpoint-test",children:"\uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc784\uacc4 \uc9c0\uc810\uc744 \ucc3e\uae30 \uc704\ud574 \ubd80\ud558\ub97c \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a4\uba70 \uc9c4\ud589\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ubb38\uc81c\ub418\ub294 \ubd80\ubd84\uc744 \ub354 \ube68\ub9ac \ucc3e\uae30 \uc704\ud574 \ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\ud55c \ub2e4\uc74c\uc5d0 \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud558\uace0, \uc774 \ub54c \uc810\uc9c4\uc801\uc73c\ub85c \ubd80\ud558\ub97c \ub298\ub824\ub098\uac00\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc131\ub2a5 \ud29c\ub2dd\uacfc \ubc18\ubcf5\ud574\uc11c \uc9c4\ud589\ud55c\ub2e4\uba74, \uc2dc\uc2a4\ud15c\uc744 \ub354\uc6b1 \ubc1c\uc804\uc2dc\ud0ac \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub9cc Auto Scaling\uc774 \uc801\uc6a9\ub41c \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c\ub294 \uc9c4\ud589\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://k6.io/docs/test-types/load-test-types/",children:"Load test types, k6"}),(0,r.jsx)(t.br,{}),"\n","\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc",(0,r.jsx)(t.br,{}),"\n","\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"]})]})}function d(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),h=c(n),u=s,j=h["".concat(l,".").concat(u)]||h[u]||p[u]||i;return n?r.createElement(j,a(a({ref:t},d),{},{components:n})):r.createElement(j,a({ref:t},d))}));d.displayName="MDXCreateElement"},38715:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/test-355aba93f96ef7d6a0f3161bf6a9c25e.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6204],{93516:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var r=n(85893),s=n(3905);const i={title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",slug:"performance-test-type",tags:["performance test"]},a=void 0,o={permalink:"/performance-test-type",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",source:"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",description:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8",date:"2023-09-10T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 10\uc77c",tags:[{label:"performance test",permalink:"/tags/performance-test"}],readingTime:5.8,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",slug:"performance-test-type",tags:["performance test"]},unlisted:!1,prevItem:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",permalink:"/db-replication"},nextItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"}},l={authorsImageUrls:[]},c=[{value:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8",id:"\uc131\ub2a5-\ud14c\uc2a4\ud2b8",level:2},{value:"\uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)",id:"\uc2a4\ubaa8\ud06c-\ud14c\uc2a4\ud2b8smoke-test",level:3},{value:"\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)",id:"\uc2a4\ud30c\uc774\ud06c-\ud14c\uc2a4\ud2b8spike-test",level:3},{value:"\ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)",id:"\ubd80\ud558-\ud14c\uc2a4\ud2b8load-test",level:3},{value:"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test)",id:"\uc2a4\ud2b8\ub808\uc2a4-\ud14c\uc2a4\ud2b8stress-test",level:3},{value:"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test)",id:"\ub0b4\uad6c-\ud14c\uc2a4\ud2b8endurance-test",level:3},{value:"\uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)",id:"\uc911\ub2e8\uc810-\ud14c\uc2a4\ud2b8breakpoint-test",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",h2:"h2",h3:"h3",img:"img",p:"p",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h2,{id:"\uc131\ub2a5-\ud14c\uc2a4\ud2b8",children:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsx)(t.p,{children:"API\uc758 \uc694\uccad\uc774 \ub9ce\uc740 \uc0c1\ud669\uc5d0\uc11c \uc11c\ubc84\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2dc\uc2a4\ud15c\uc5d0 \ubd80\ud558\uac00 \uac78\ub9ac\uba74 \ubb38\uc81c \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\uc591\ud55c \uc0c1\ud669\uc5d0 \ub300\ube44\ud574\uc11c \uc131\ub2a5 \ud14c\uc2a4\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"./test.png",src:n(38715).Z+"",width:"2168",height:"1002"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ubaa8\ud06c-\ud14c\uc2a4\ud2b8smoke-test",children:"\uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ucd5c\uc18c\ud55c\uc758 \ubd80\ud558\ub97c \uc8fc\uc5b4 \uc2dc\uc2a4\ud15c\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["VU\ub97c \ucd5c\uc18c\ud55c\uc73c\ub85c \ub450\uace0, \uc9e7\uc740 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \ud14c\uc2a4\ud2b8\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud568\uc73c\ub85c\uc368 \ud14c\uc2a4\ud2b8 \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc624\ub958\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uace0, \uc131\ub2a5 \uc9c0\ud45c\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc9d1, \ubaa8\ub2c8\ud130\ub9c1 \ub418\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"\uac00\uc0c1 \uc0ac\uc6a9\uc790(VU)",type:"note",children:(0,r.jsxs)(t.p,{children:["\uac00\uc0c1 \uc0ac\uc6a9\uc790\ub294 \uc11c\ubc84 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ub300\ud574 \ud2b9\uc815 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \ub2e4\ub978 \uac00\uc0c1 \uc0ac\uc6a9\uc790\uc640 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uba70, \uc5ec\ub7ec \uac00\uc0c1 \uc0ac\uc6a9\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc2dc \uc5f0\uacb0\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ub808\ub4dc\ub77c\uace0 \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud30c\uc774\ud06c-\ud14c\uc2a4\ud2b8spike-test",children:"\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc0ac\uc6a9\ub7c9\uc774 \uae09\uc99d\ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uacac\ub514\uace0 \uc131\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ud2f0\ucf13 \ubc1c\uae09, \ud560\uc778 \ucfe0\ud3f0 \ubc1c\uae09\uacfc \uac19\uc740 \uc774\ubca4\ud2b8\ub97c \ud558\ub294 \uacbd\uc6b0 \ub300\uaddc\ubaa8 \ud2b8\ub798\ud53d\uc774 \ub4e4\uc5b4\uc628\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uae09\uc99d\ud558\ub294 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\uace0, \ubd80\ud558\ub97c \uc798 \ubc84\ud2f0\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ubd80\ud558-\ud14c\uc2a4\ud2b8load-test",children:"\ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ubaa9\ud46f\uac12\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \uacac\ub51c \uc218 \uc788\uc744\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uc77c\ubc18\uc801\uc778 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub7a8\ud504\uc5c5 \ub610\ub294 \ubb19\ud46f\uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ubd80\ud558 \uae30\uac04\ub3d9\uc548 \uc131\ub2a5\uc774 \ubb38\uc81c\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uace0, \uc2dc\uc2a4\ud15c \ubcc0\uacbd \ud6c4\uc5d0\ub3c4 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ub3d9\uc77c\ud558\uac8c \ubaa9\ud46f\uac12\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"\ub7a8\ud504 \uc5c5(Ramp-up)",type:"note",children:(0,r.jsx)(t.p,{children:"\ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574 \uc124\uc815\ud55c \uac00\uc0c1 \uc0ac\uc6a9\uc790 \uc218\uc5d0 \ub3c4\ub2ec\ud558\ub294 \ub370 \uac78\ub9ac\ub294 \uc2dc\uac04"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud2b8\ub808\uc2a4-\ud14c\uc2a4\ud2b8stress-test",children:"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc2dc\uc2a4\ud15c\uc758 \ucd5c\ub300\uce58\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \ubc1b\uc558\uc744 \ub54c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uadf8\ub798\ud504\ub97c \ubd24\uc744 \ub54c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc640 \uc720\uc0ac\ud55c \ud615\ud0dc\ub85c \ubcf4\uc774\uc9c0\ub9cc, \ubd80\ud558\ub7c9\uc774 \ub2e4\ub974\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c \ud3c9\uade0\uc801\uc778 \ubaa9\ud46f\uac12 \ub300\ube44 \uc791\uac8c\ub294 50% \uc774\uc0c1, \ud544\uc694\uc758 \uacbd\uc6b0 \uadf8 \uc774\uc0c1\uc73c\ub85c \ubd80\ud558\ub97c \uc900\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub294 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c \ud6c4\uc5d0\ub9cc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4. \ubd80\ud558 \ud14c\uc2a4\ud2b8\uac00 \uc774\ub8e8\uc5b4\uc9c0\uc9c0 \uc54a\uc740 \uc0c1\ud669\uc5d0\uc11c \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \ubcd1\ubaa9 \uc9c0\uc810\uc774\ub098 \ubb38\uc81c \uc0c1\ud669\uc744 \ucc3e\uae30 \uc5b4\ub824\uc6cc\uc9c4\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub610\ud55c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c VU\uac12(\uc2a4\ub808\ub4dc \uc218)\ub9cc \uc218\uc815\ud558\uc5ec \uc7ac\uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ub0b4\uad6c-\ud14c\uc2a4\ud2b8endurance-test",children:"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ud3c9\uade0 \uc0ac\uc6a9\ub960\ub85c \uc77c\uc815 \ubd80\ud558\ub97c \uc9c0\uc18d\uc801\uc73c\ub85c \uc8fc\uba70 \uc2dc\uc2a4\ud15c\uc774 \ubb38\uc81c\ub418\ub294 \uc9c0\uc810\uc744 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ud761\uc218 \ud14c\uc2a4\ud2b8(Soak Test)\ub77c\uace0\ub3c4 \ud558\uba70, \uae30\ubcf8\uc801\uc778 \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc758 \ubcc0\ud615\uc774\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc640 \ub2ec\ub9ac \uae34 \uc2dc\uac04\ub3d9\uc548 \ud14c\uc2a4\ud2b8\ub97c \ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\uba70, \uba54\ubaa8\ub9ac \ub204\uc218 \ubb38\uc81c\uc640 \uac19\uc774 \uc7a5\uc2dc\uac04 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud560 \ub54c \uc2dc\uc2a4\ud15c\uc758 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \ubd80\ubd84\uc744 \ud655\uc778\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc911\ub2e8\uc810-\ud14c\uc2a4\ud2b8breakpoint-test",children:"\uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc784\uacc4 \uc9c0\uc810\uc744 \ucc3e\uae30 \uc704\ud574 \ubd80\ud558\ub97c \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a4\uba70 \uc9c4\ud589\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ubb38\uc81c\ub418\ub294 \ubd80\ubd84\uc744 \ub354 \ube68\ub9ac \ucc3e\uae30 \uc704\ud574 \ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\ud55c \ub2e4\uc74c\uc5d0 \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud558\uace0, \uc774 \ub54c \uc810\uc9c4\uc801\uc73c\ub85c \ubd80\ud558\ub97c \ub298\ub824\ub098\uac00\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc131\ub2a5 \ud29c\ub2dd\uacfc \ubc18\ubcf5\ud574\uc11c \uc9c4\ud589\ud55c\ub2e4\uba74, \uc2dc\uc2a4\ud15c\uc744 \ub354\uc6b1 \ubc1c\uc804\uc2dc\ud0ac \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub9cc Auto Scaling\uc774 \uc801\uc6a9\ub41c \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c\ub294 \uc9c4\ud589\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://k6.io/docs/test-types/load-test-types/",children:"Load test types, k6"}),(0,r.jsx)(t.br,{}),"\n","\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc",(0,r.jsx)(t.br,{}),"\n","\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"]})]})}function d(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),h=c(n),u=s,j=h["".concat(l,".").concat(u)]||h[u]||p[u]||i;return n?r.createElement(j,a(a({ref:t},d),{},{components:n})):r.createElement(j,a({ref:t},d))}));d.displayName="MDXCreateElement"},38715:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/test-355aba93f96ef7d6a0f3161bf6a9c25e.png"}}]); \ No newline at end of file diff --git a/assets/js/08e37dbc.83c072d2.js b/assets/js/08e37dbc.1ff31367.js similarity index 97% rename from assets/js/08e37dbc.83c072d2.js rename to assets/js/08e37dbc.1ff31367.js index 5ba62e59a..0e25193fd 100644 --- a/assets/js/08e37dbc.83c072d2.js +++ b/assets/js/08e37dbc.1ff31367.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1328],{95883:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>a});var t=r(85893),o=r(3905);const s={title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",slug:"order-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/order-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4: AWS \ubc30\ud3ec",date:"2023-06-04T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 4\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.67,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",slug:"order-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",permalink:"/level2-interview-retrospective"},nextItem:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",permalink:"/tecochat-retrospective-3"}},l={authorsImageUrls:[]},a=[{value:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158",id:"\uc7a5\ubc14\uad6c\ub2c8-\uc8fc\ubb38-\ubbf8\uc158",level:3},{value:"\ubc30\ud3ec",id:"\ubc30\ud3ec",level:3},{value:"\ud611\uc5c5",id:"\ud611\uc5c5",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84",id:"\uc0c8\ub85c-\ubc30\uc6b4-\ubd80\ubd84",level:3}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: AWS \ubc30\ud3ec",(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-shopping-order/pull/7",children:"https://github.com/woowacourse/jwp-shopping-order/pull/7"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc7a5\ubc14\uad6c\ub2c8-\uc8fc\ubb38-\ubbf8\uc158",children:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158"}),"\n",(0,t.jsxs)(n.p,{children:["\ubc30\ud3ec \ubc0f \ud611\uc5c5\uc744 \ud560 \uc218 \uc788\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9c8\ucf54, \uc6b0\uac00, \uc6b0\ucf54, \uc6b0\uc2a4 \uadf8\ub9ac\uace0 \ub098\uae4c\uc9c0 \ud569\uccd0\uc11c 5\uba85\uc774 \ud55c \ud300\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc30\ud3ec",children:"\ubc30\ud3ec"}),"\n",(0,t.jsxs)(n.p,{children:["\uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac AWS\ub97c \uc774\uc6a9\ud574 \ubc30\ud3ec\ub97c \ud574\uc57c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac01\uc790 \ud558\ub098\uc758 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc744 \uc218 \uc788\uc5c8\uace0, \ud300 \ubcc4\ub85c DB\ub97c \uc704\ud55c \ucd94\uac00 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uacbd\ud5d8\uc744 \ud574\ubcfc \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ud22c\uc790\ud558\uc9c4 \uc54a\uc558\uace0, \ub2e4\uc74c\uacfc \uac19\uc774 \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'echo "Start Deploy Script"\nREPOSITORY_NAME=/home/ubuntu/jwp-shopping-order\nPROJECT_NAME=jwp-shopping-order\n\necho "Change Directory"\ncd $REPOSITORY_NAME\n\necho "Git Pull"\ngit pull origin step2\n\necho "Build"\n./gradlew bootJar\n\necho "Copy, Start Server"\nmv ./build/libs/$PROJECT_NAME.jar .\n\nPID=$(pgrep -f $PROJECT_NAME)\n\nif [ -n $PID ]; then\n kill -9 $PID\n\tsleep 5\nfi\n\nnohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ud611\uc5c5",children:"\ud611\uc5c5"}),"\n",(0,t.jsxs)(n.p,{children:["\uc77c\ub2e8 \uc6b0\uc2a4\ub791 \uc6b0\ucf54\uac00 \uba3c\uc800 \uc7a0\uc2e4\ub85c \uc640\uc918\uc11c \ub108\ubb34 \uac10\uc0ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc31\uc5d4\ub4dc\uac00 \uc544\ub2cc \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \ud574\ubcf4\ub294 \uccab \ud611\uc5c5\uc774\ub77c \uc57d\uac04 \ub450\uadfc\uac70\ub838\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc608\uc0c1\uc678\ub85c \ub300\ud654\uac00 \uc798 \ub418\uc5b4\uc11c, \ube60\ub974\uac8c \uba85\uc138\ub97c \uc815\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc5ec\ub7ec\uac00\uc9c0 \ubc29\ubc95\uc5d0 \ub300\ud55c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud574\ubcf4\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc31\uc5d4\ub4dc\uc640 \ud14c\uc774\ube14 \uba85\uc138\ub098 \ucfe0\ud3f0 \uad6c\ud604\uc5d0 \ub300\ud574\uc11c \uc774\uc57c\uae30\ud560 \ub54c \uc7a5\ub2e8\uc5d0 \ub300\ud574 \ub9ce\uc774 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc5ec\uc11c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud588\ub2e4\uba74 \ub354 \uc88b\uc740 \uacb0\uacfc\ubb3c\uc774 \ub098\uc624\uc9c0 \uc54a\uc558\uc744\uae4c?",(0,t.jsx)(n.br,{}),"\n","\uc55e\uc73c\ub85c \uc120\ud0dd\uc758 \uc21c\uac04\uc5d0\uc11c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub4e4\uc5ec\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ubc30\uc6b4-\ubd80\ubd84",children:"\uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"expose headers"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc6f9 \ud398\uc774\uc9c0\uc5d0\uc11c Location \ud5e4\ub354\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c ",(0,t.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header",children:"\ud5c8\uc6a9 \ubaa9\ub85d\uc5d0 \uc874\uc7ac\ud558\ub294 \uc751\ub2f5\ud5e4\ub354"}),"\ub9cc \ubc18\ud658\ud55c\ub2e4\ub294 \uac83\uc744 \ubaa8\ub974\uace0 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub97c expose headers \uc124\uc815\uc744 \ud1b5\ud574 \ud574\uacb0\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","nginx \uc124\uc815\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \ucd94\uac00\ud574 \uc8fc\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"add_header 'Access-Control-Expose-Headers' 'Location'\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158"})}),"\n",(0,t.jsxs)(n.p,{children:["\ub2e8\uc21c \uc870\ud68c \uc694\uccad\uc5d0 \ub300\ud55c \uc131\ub2a5\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc900\ub2e4\ub294 \uac83\uc774\ub77c\uace0 \uac04\ub2e8\ud788\ub9cc \uc54c\uace0 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88\uc5d0 \ucf54\uba58\ud2b8\uac00 \ub2ec\ub824\uc11c \uc870\uae08 \ub354 \uc790\uc138\ud788 \uacf5\ubd80\ud574 \ubcf4\uae30\ub85c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Transactional(readOnly = true)\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc774 \ub3d9\uc791\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"setReadOnly(true) \uc124\uc815\uc774 \ub41c Connection\uc73c\ub85c \uc5f0\uacb0\uc744 \uc2dc\ub3c4\ub97c \ud55c\ub2e4. \uc774 \uc124\uc815\uc744 \ud558\ub294 \uacbd\uc6b0 DB\ub9c8\ub2e4 \ub2e4\ub974\uac8c \ub3d9\uc791\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"h2\uc758 Connection \uad6c\ud604\uccb4\ub294 readOnly \uc124\uc815\uc744 \ubb34\uc2dc\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 Transactional \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"MySQL 8.0(InnoDB \uc0ac\uc6a9 \uc2dc)\uc758 \uacbd\uc6b0 \uc77d\uae30 \uc804\uc6a9\uc73c\ub85c \uc54c\ub824\uc9c4 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158 ID\ub97c \uc124\uc815\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uc870\ud68c \uc18d\ub3c4\uac00 \ub354 \ube68\ub77c\uc9c4\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["ORM \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 prepareTransactionalConnection\ub97c \ud638\ucd9c\ud55c\ub2e4\uace0 \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ud604\uc5c5\uc5d0\uc11c\ub294 \uace0\uac00\uc6a9\uc131 \ub0b4\uacb0\ud568\uc131 \ub4f1\uc744 \uc704\ud558\uc5ec \ud074\ub7ec\uc2a4\ud130\ub97c \uad6c\uc131\ud558\uc5ec \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uace0, \uc774 \uacbd\uc6b0 readOnly \uc124\uc815\uc774 \ub418\uc5b4\uc788\ub2e4\uba74 \uc77d\uae30 \uc804\uc6a9 DB\ub85c \uc9c8\uc758\uac00 \ub4e4\uc5b4\uac00\uc11c \ubd80\ud558 \ubd84\uc0b0\uc758 \ud6a8\uacfc\uac00 \uc788\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.strong,{children:["DAO\uc5d0 ",(0,t.jsx)(n.code,{children:"@Transactional"})," \uc801\uc6a9"]})}),"\n",(0,t.jsxs)(n.p,{children:["DAO\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \ubcf4\ub294 \uac74 \uc5b4\ub5bb\uaca0\ub0d0\uace0 \ub9ac\ubdf0\uac00 \ub2ec\ub824\uc11c \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Service \uacc4\uce35\uc5d0 \uc774\ubbf8 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \uc8fc\uace0 \uc788\uae30\uc5d0 \ud544\uc694 \uc5c6\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","DAO\ub97c \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574(\ud655\uc7a5\uc131 \uace0\ub824) ",(0,t.jsx)(n.code,{children:"@Transactional"}),"\uc744 \uc801\uc6a9\ud558\ub294 \uac83\ub3c4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."]})]})}function d(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function s(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=t.createContext({}),a=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,s=e.originalType,l=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=a(r),u=o,j=h["".concat(l,".").concat(u)]||h[u]||p[u]||s;return r?t.createElement(j,i(i({ref:n},d),{},{components:r})):t.createElement(j,i({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1328],{95883:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>a});var t=r(85893),o=r(3905);const s={title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",slug:"order-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/order-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4: AWS \ubc30\ud3ec",date:"2023-06-04T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 4\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.67,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",slug:"order-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",permalink:"/tecochat-retrospective-3"},nextItem:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",permalink:"/level2-interview-retrospective"}},l={authorsImageUrls:[]},a=[{value:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158",id:"\uc7a5\ubc14\uad6c\ub2c8-\uc8fc\ubb38-\ubbf8\uc158",level:3},{value:"\ubc30\ud3ec",id:"\ubc30\ud3ec",level:3},{value:"\ud611\uc5c5",id:"\ud611\uc5c5",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84",id:"\uc0c8\ub85c-\ubc30\uc6b4-\ubd80\ubd84",level:3}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: AWS \ubc30\ud3ec",(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-shopping-order/pull/7",children:"https://github.com/woowacourse/jwp-shopping-order/pull/7"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc7a5\ubc14\uad6c\ub2c8-\uc8fc\ubb38-\ubbf8\uc158",children:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158"}),"\n",(0,t.jsxs)(n.p,{children:["\ubc30\ud3ec \ubc0f \ud611\uc5c5\uc744 \ud560 \uc218 \uc788\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9c8\ucf54, \uc6b0\uac00, \uc6b0\ucf54, \uc6b0\uc2a4 \uadf8\ub9ac\uace0 \ub098\uae4c\uc9c0 \ud569\uccd0\uc11c 5\uba85\uc774 \ud55c \ud300\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc30\ud3ec",children:"\ubc30\ud3ec"}),"\n",(0,t.jsxs)(n.p,{children:["\uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac AWS\ub97c \uc774\uc6a9\ud574 \ubc30\ud3ec\ub97c \ud574\uc57c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac01\uc790 \ud558\ub098\uc758 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc744 \uc218 \uc788\uc5c8\uace0, \ud300 \ubcc4\ub85c DB\ub97c \uc704\ud55c \ucd94\uac00 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uacbd\ud5d8\uc744 \ud574\ubcfc \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ud22c\uc790\ud558\uc9c4 \uc54a\uc558\uace0, \ub2e4\uc74c\uacfc \uac19\uc774 \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'echo "Start Deploy Script"\nREPOSITORY_NAME=/home/ubuntu/jwp-shopping-order\nPROJECT_NAME=jwp-shopping-order\n\necho "Change Directory"\ncd $REPOSITORY_NAME\n\necho "Git Pull"\ngit pull origin step2\n\necho "Build"\n./gradlew bootJar\n\necho "Copy, Start Server"\nmv ./build/libs/$PROJECT_NAME.jar .\n\nPID=$(pgrep -f $PROJECT_NAME)\n\nif [ -n $PID ]; then\n kill -9 $PID\n\tsleep 5\nfi\n\nnohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ud611\uc5c5",children:"\ud611\uc5c5"}),"\n",(0,t.jsxs)(n.p,{children:["\uc77c\ub2e8 \uc6b0\uc2a4\ub791 \uc6b0\ucf54\uac00 \uba3c\uc800 \uc7a0\uc2e4\ub85c \uc640\uc918\uc11c \ub108\ubb34 \uac10\uc0ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc31\uc5d4\ub4dc\uac00 \uc544\ub2cc \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \ud574\ubcf4\ub294 \uccab \ud611\uc5c5\uc774\ub77c \uc57d\uac04 \ub450\uadfc\uac70\ub838\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc608\uc0c1\uc678\ub85c \ub300\ud654\uac00 \uc798 \ub418\uc5b4\uc11c, \ube60\ub974\uac8c \uba85\uc138\ub97c \uc815\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc5ec\ub7ec\uac00\uc9c0 \ubc29\ubc95\uc5d0 \ub300\ud55c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud574\ubcf4\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc31\uc5d4\ub4dc\uc640 \ud14c\uc774\ube14 \uba85\uc138\ub098 \ucfe0\ud3f0 \uad6c\ud604\uc5d0 \ub300\ud574\uc11c \uc774\uc57c\uae30\ud560 \ub54c \uc7a5\ub2e8\uc5d0 \ub300\ud574 \ub9ce\uc774 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc5ec\uc11c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud588\ub2e4\uba74 \ub354 \uc88b\uc740 \uacb0\uacfc\ubb3c\uc774 \ub098\uc624\uc9c0 \uc54a\uc558\uc744\uae4c?",(0,t.jsx)(n.br,{}),"\n","\uc55e\uc73c\ub85c \uc120\ud0dd\uc758 \uc21c\uac04\uc5d0\uc11c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub4e4\uc5ec\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ubc30\uc6b4-\ubd80\ubd84",children:"\uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"expose headers"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc6f9 \ud398\uc774\uc9c0\uc5d0\uc11c Location \ud5e4\ub354\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c ",(0,t.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header",children:"\ud5c8\uc6a9 \ubaa9\ub85d\uc5d0 \uc874\uc7ac\ud558\ub294 \uc751\ub2f5\ud5e4\ub354"}),"\ub9cc \ubc18\ud658\ud55c\ub2e4\ub294 \uac83\uc744 \ubaa8\ub974\uace0 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub97c expose headers \uc124\uc815\uc744 \ud1b5\ud574 \ud574\uacb0\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","nginx \uc124\uc815\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \ucd94\uac00\ud574 \uc8fc\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"add_header 'Access-Control-Expose-Headers' 'Location'\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158"})}),"\n",(0,t.jsxs)(n.p,{children:["\ub2e8\uc21c \uc870\ud68c \uc694\uccad\uc5d0 \ub300\ud55c \uc131\ub2a5\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc900\ub2e4\ub294 \uac83\uc774\ub77c\uace0 \uac04\ub2e8\ud788\ub9cc \uc54c\uace0 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88\uc5d0 \ucf54\uba58\ud2b8\uac00 \ub2ec\ub824\uc11c \uc870\uae08 \ub354 \uc790\uc138\ud788 \uacf5\ubd80\ud574 \ubcf4\uae30\ub85c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Transactional(readOnly = true)\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc774 \ub3d9\uc791\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"setReadOnly(true) \uc124\uc815\uc774 \ub41c Connection\uc73c\ub85c \uc5f0\uacb0\uc744 \uc2dc\ub3c4\ub97c \ud55c\ub2e4. \uc774 \uc124\uc815\uc744 \ud558\ub294 \uacbd\uc6b0 DB\ub9c8\ub2e4 \ub2e4\ub974\uac8c \ub3d9\uc791\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"h2\uc758 Connection \uad6c\ud604\uccb4\ub294 readOnly \uc124\uc815\uc744 \ubb34\uc2dc\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 Transactional \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"MySQL 8.0(InnoDB \uc0ac\uc6a9 \uc2dc)\uc758 \uacbd\uc6b0 \uc77d\uae30 \uc804\uc6a9\uc73c\ub85c \uc54c\ub824\uc9c4 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158 ID\ub97c \uc124\uc815\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uc870\ud68c \uc18d\ub3c4\uac00 \ub354 \ube68\ub77c\uc9c4\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["ORM \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 prepareTransactionalConnection\ub97c \ud638\ucd9c\ud55c\ub2e4\uace0 \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ud604\uc5c5\uc5d0\uc11c\ub294 \uace0\uac00\uc6a9\uc131 \ub0b4\uacb0\ud568\uc131 \ub4f1\uc744 \uc704\ud558\uc5ec \ud074\ub7ec\uc2a4\ud130\ub97c \uad6c\uc131\ud558\uc5ec \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uace0, \uc774 \uacbd\uc6b0 readOnly \uc124\uc815\uc774 \ub418\uc5b4\uc788\ub2e4\uba74 \uc77d\uae30 \uc804\uc6a9 DB\ub85c \uc9c8\uc758\uac00 \ub4e4\uc5b4\uac00\uc11c \ubd80\ud558 \ubd84\uc0b0\uc758 \ud6a8\uacfc\uac00 \uc788\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.strong,{children:["DAO\uc5d0 ",(0,t.jsx)(n.code,{children:"@Transactional"})," \uc801\uc6a9"]})}),"\n",(0,t.jsxs)(n.p,{children:["DAO\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \ubcf4\ub294 \uac74 \uc5b4\ub5bb\uaca0\ub0d0\uace0 \ub9ac\ubdf0\uac00 \ub2ec\ub824\uc11c \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Service \uacc4\uce35\uc5d0 \uc774\ubbf8 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \uc8fc\uace0 \uc788\uae30\uc5d0 \ud544\uc694 \uc5c6\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","DAO\ub97c \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574(\ud655\uc7a5\uc131 \uace0\ub824) ",(0,t.jsx)(n.code,{children:"@Transactional"}),"\uc744 \uc801\uc6a9\ud558\ub294 \uac83\ub3c4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."]})]})}function d(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function s(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=t.createContext({}),a=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,s=e.originalType,l=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=a(r),u=o,j=h["".concat(l,".").concat(u)]||h[u]||p[u]||s;return r?t.createElement(j,i(i({ref:n},d),{},{components:r})):t.createElement(j,i({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/0e33a907.8661cb3c.js b/assets/js/0e33a907.d81edb95.js similarity index 97% rename from assets/js/0e33a907.8661cb3c.js rename to assets/js/0e33a907.d81edb95.js index 8baae3e45..773098a4e 100644 --- a/assets/js/0e33a907.8661cb3c.js +++ b/assets/js/0e33a907.d81edb95.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3092],{33520:(A,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>s,default:()=>o,frontMatter:()=>I,metadata:()=>j,toc:()=>w});var r=n(85893),t=n(3905),E=n(17779);const I={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",slug:"woowacourse-level3-retrospective",tags:["Woowahan Techcourse","Retrospective"]},s=void 0,j={permalink:"/woowacourse-level3-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",description:"\ud68c\uace0",date:"2023-08-19T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 19\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.945,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",slug:"woowacourse-level3-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",permalink:"/db-replication"},nextItem:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/cloudwatch"}},c={authorsImageUrls:[]},w=[{value:"\ud68c\uace0",id:"\ud68c\uace0",level:3},{value:"\uc544\uc26c\uc6b4 \uc810",id:"\uc544\uc26c\uc6b4-\uc810",level:3},{value:"\uc88b\uc558\ub358 \uc810",id:"\uc88b\uc558\ub358-\uc810",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3}];function l(A){const e={a:"a",br:"br",h3:"h3",p:"p",strong:"strong",...(0,t.ah)(),...A.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(e.h3,{id:"\ud68c\uace0",children:"\ud68c\uace0"}),"\n",(0,r.jsxs)(e.p,{children:["\uc9c0\ub09c 8\uc8fc\ub294 \ub808\ubca8 1, 2 \ub54c\ubcf4\ub2e4 5\ubc30 \uc815\ub3c4 \ube60\ub974\uac8c \uc9c0\ub098\uac04 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub808\ubca8 3\uc5d0\ub294 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4, \uae30\uc220 \uc678\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4 \ubd80\uc871\ud568\uc774 \ub9ce\uc774 \ubcf4\uc600\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubd80\uc871\ud55c \ubd80\ubd84\uc744 \uc54c\uc558\uae30\uc5d0, \uc55e\uc73c\ub85c \ub354\uc6b1 \uc131\uc7a5\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub0b4\uac00 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \ud300\uc6d0\ub4e4\uc774 \uc798 \ubcf4\ucda9\ud574 \uc918\uc11c \ub4e0\ub4e0\ud588\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\uc544\uc26c\uc6b4-\uc810",children:"\uc544\uc26c\uc6b4 \uc810"}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ubb38\uc11c\ud654"})}),"\n",(0,r.jsxs)(e.p,{children:["\uac1c\uc778\uc801\uc73c\ub85c\ub294 \uae30\uc220 \uc678\uc801\uc73c\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ub0b4\uac00 \ud55c \ubd80\ubd84\uc744 \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c, \uc774\ud574\ud558\uae30 \uc27d\uac8c \ubb38\uc11c\ud654\ub97c \ud588\ub354\ub77c\uba74 \ud300\uc6d0\ub4e4\uc5d0\uac8c \ub354\uc6b1 \ub3c4\uc6c0\uc774 \ub418\uc5c8\uc744 \ud150\ub370 \uc774 \ubd80\ubd84\uc5d0 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ud22c\uc790\ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc5d0\uc11c \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubc29\ud559 \uae30\uac04 \ub3d9\uc548 \ubb38\uc11c\ud654\ub97c \ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc778 \ube14\ub85c\uadf8 \uc62c\ub9ac\uba74\uc11c \uc870\uae08 \ub354 \ucc44\uc6cc\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ub0b4\uac00 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc774\uc790"})}),"\n",(0,r.jsxs)(e.p,{children:["\uc798 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc5ec\uc11c\ub77c\ub3c4 \uc911\uac04\uc740 \uac00\ub3c4\ub85d \ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub9d0\uc744 \ud558\uae30 \uc804\uc5d0 \uc815\ub9ac\ud574\uc11c \uc758\uacac\uc744 \ub0b4\ub294 \uac83, \ubc1c\ud45c \uc900\ube44, \uac10\uc815 \uc870\uc808 \ub4f1\ub4f1\n\ubabb\ud558\ub294 \ubd80\ubd84\uc744 \uc778\uc9c0\ud558\uace0, \uac1c\uc120\ud558\uc790."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ucef4\ud3ec\ud2b8 \uc874 \ubc97\uc5b4\ub098\uae30"})}),"\n",(0,r.jsxs)(e.p,{children:["\uc870\uae08 \ub354 \ub3c4\uc804\uc801\uc73c\ub85c \ubaa9\ud45c\ub97c \uc7a1\uc558\uc73c\uba74 \uc88b\uc558\uc744 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub9e4\ubc88 \uadfc\uac70\ub97c \uac00\uc9c0\uace0 \uae30\uc220\uc744 \ub3c4\uc785\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud558\uc9c0\ub9cc \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub824\uace0 \ud558\ub294 \ubd80\ubd84\uc774 \ub2e4\uc18c \ubd80\uc871\ud588\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\uc88b\uc558\ub358-\uc810",children:"\uc88b\uc558\ub358 \uc810"}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\uc88b\uc558\ub358 \uc810\ub3c4 \ubb38\uc11c\ud654"})}),"\n",(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.a,{href:"https://tripdraw.blog",children:"\ud300 \ube14\ub85c\uadf8"}),"\ub3c4 \uba3c\uc800 \ub3c4\uc785\ud558\uc790\uace0 \uc81c\uc548\ud558\uace0, \ub0b4\uac00 \ud588\ub358 \ubd80\ubd84\uc740 \ubb38\uc11c\ud654\ub97c \uaf64 \ub9ce\uc774 \ud574\uc11c \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubc31\uc5d4\ub4dc \ud06c\ub8e8 4\uba85\uc774\uc11c \uac19\uc774 \ud55c \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c\ub294 \uae30\ub2a5 \uad6c\ud604\ud55c\ub2e4\uace0 \ubb38\uc11c\ud654\uac00 \uc870\uae08 \ubbf8\ud761\ud574\uc11c \ubcf4\ucda9\uc744 \ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ub0b4\uac00 \ub514\uc790\uc778\ud55c \ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0"})}),"\n",(0,r.jsx)("img",{src:E.Z,width:"100"}),"\n",(0,r.jsxs)(e.p,{children:["\ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0\ub97c \ub9cc\ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud300\uc6d0\ub4e4\uc774 \ub300\ud45c \uc0c9\uc0c1(\ud30c\ub780\uc0c9)\uc744 \uc815\ud574\uc92c\uace0, \uc8fc\ub9d0 \ub3d9\uc548 \uc2e0\ub098\uac8c \ub85c\uace0 \ub514\uc790\uc778\uc744 \ud588\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\uc544\ub798\uc758 D \ubd80\ubd84\uc740 \uc720\ud29c\ube0c \uac15\uc758 \ub4e4\uc73c\uba74\uc11c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\uc11c \ubfcc\ub4ef\ud558\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\uae30\uc220 \uc120\ud0dd\uc758 \uc774\uc720"})}),"\n",(0,r.jsxs)(e.p,{children:["\uae30\uc220\uc758 \ud559\uc2b5 \ube44\uc6a9, \ud604\uc7ac \uad6c\uc870\uc5d0 \uc801\ud569\ud55c\uc9c0, \uc2e4\uc81c \uac00\uc9c0\uace0 \uc788\ub294 \ub9ac\uc18c\uc2a4\ub97c \uace0\ub824\ud574\uc11c \uae30\uc220 \uc120\ud0dd\uc744 \ud558\uace0, \ub3c4\uc785\ud588\ub358 \ubd80\ubd84\uc774 \uc88b\uc558\ub2e4.",(0,r.jsx)(e.br,{}),"\n","100% \uc88b\uc740 \uc120\ud0dd\uc77c \uc21c \uc5c6\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \uc120\ud0dd\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \uc874\uc7ac\ud55c\ub2e4\uba74 \ud655\ub960\uc744 \ub192\ud600\uc8fc\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,r.jsxs)(e.p,{children:["\ud50c\ub808\uc774\uc2a4\ud1a0\uc5b4\uc5d0 \uc571\uc774 \uc62c\ub77c\uac00 \uc788\ub294 \uac70 \ub108\ubb34 \uc2e0\uae30\ud558\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\uc548\ub4dc\ub85c\uc774\ub4dc \ube0c\ub808\uba58 \uc74c\uc545\ub300(\uba67\ub3fc\uc9c0, \uc218\ub2ec, \ud551\uad6c), \uadf8\ub9ac\uace0 \ubc31\uc5d4\ub4dc \ud300\uc6d0\ub4e4(\uccb4\uc778\uc800, \ud6c4\ucd94, \ub9ac\uc624) \ub108\ubb34 \uace0\uc0dd\uc774 \ub9ce\uc558\ub2e4."]})]})}function o(A={}){const{wrapper:e}={...(0,t.ah)(),...A.components};return e?(0,r.jsx)(e,{...A,children:(0,r.jsx)(l,{...A})}):l(A)}},3905:(A,e,n)=>{n.d(e,{ah:()=>c});var r=n(67294);function t(A,e,n){return e in A?Object.defineProperty(A,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):A[e]=n,A}function E(A,e){var n=Object.keys(A);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(A);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(A,e).enumerable}))),n.push.apply(n,r)}return n}function I(A){for(var e=1;e=0||(t[n]=A[n]);return t}(A,e);if(Object.getOwnPropertySymbols){var E=Object.getOwnPropertySymbols(A);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(A,n)&&(t[n]=A[n])}return t}var j=r.createContext({}),c=function(A){var e=r.useContext(j),n=e;return A&&(n="function"==typeof A?A(e):I(I({},e),A)),n},w={inlineCode:"code",wrapper:function(A){var e=A.children;return r.createElement(r.Fragment,{},e)}},l=r.forwardRef((function(A,e){var n=A.components,t=A.mdxType,E=A.originalType,j=A.parentName,l=s(A,["components","mdxType","originalType","parentName"]),o=c(n),i=t,h=o["".concat(j,".").concat(i)]||o[i]||w[i]||E;return n?r.createElement(h,I(I({ref:e},l),{},{components:n})):r.createElement(h,I({ref:e},l))}));l.displayName="MDXCreateElement"},17779:(A,e,n)=>{n.d(e,{Z:()=>r});const r="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAbAAAAGwCAYAAADITjAqAAAACXBIWXMAACxLAAAsSwGlPZapAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAABauSURBVHgB7d1viF3lncDx59yJsZpWU6wxoqmjLthGS2vBP4u7dEqb7FIXVKIFX9Qa3xTqiyisfWeNyEKphWZgLesbxyqLi4m0wiprXHCWIlUD1bKaRljt1CjGfzSmjdaYzNn73Dg2f5wkk8w95/nd+/nANCaZ0HHM3O/8nuc551SpRYvHJhYvXLhgrJquR+sqfblK9WiqqtGPfns0AdC6uk7bq6qaSvX09jpVU52q/kOanp78y+703PbJ1dtTS6rUoI+DVU2Ppbq6IokUQHRT3QFksvua/vCuXbsnmwxaIwFb+s2JsbozsqZb8W680uIEwEDqxuzeHLM3N37nl6nP+hawj6atNd3Z8ybRAhg6U1Wdbk8f7pncNrl6KvXBvAdMuADYx1R33+ze7kR2e5pn8xqwpSvuu747Pt6W7G0BsL/eRLbt8evuTfNkXgK2dGxitD5uwUSq6rEEALP7ZbVrz83zsazYScfotBX3r5k+buRZ8QLgCFxZLxx5Nq/YpWN01BNY3us6fuFIXi68KQHAXFVp3RuPXXdzOkpHFbDekuHCkXxE8ssJAI5a9Vy1a/dVR7OkOOeAfRSvJ5KDGgDMj6nuvtjX5xqxOQVMvADokzlH7IgDJl4A9NmcInZEARMvABpyxBE7omP0Hx3YGE0A0F/dgWnBL/JJ98O942EDdtrK+36anDYEoDH1V44/vneZ1iGNHOo3exeaVelHCQCademn/+aqd3e+9IunZnuHWffA8r5XvsOGG/IC0JLt3f2wC2fbD5t1CbG77/VT8QKgRYvr4zsTs/3mJwbso3tUXZkAoE11NTbbfRM7n/z+6bCbZwDQhNykTzqVeFDAlqy83/O8ACjJ6KcWdg66cfx+hzhcsAxAobZ/sGvP2dsnV2+f+YX9J7DjRsaSeAFQnsUHTmH7BczeFwClqlO1Zt+ffxywJd+4P586HE0AUKbFS785MTbzk79OYCPTjs0DULS6M/LxFNY7xJGPJx6/cOSPCQDK9vFhjt4EtnBkwVgCgPItPmHh3mbtXUK0fAhAENNVGss/9gJWpeprCQAiqOsr8g+V/S8Aounug32286kF6SsJAALJ+2Cd1OmMJQAIZLqqR/Me2GgCgECqlL7cqevOWQkAAqmnuxNYnTx1GYBgqiovIdajCQCC6VSVCQyAcEY7CQACEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQlqQAPrkzCUnpi+edXI6adFx3X8+IZ104nHp5EULP/F93925K+1478P0p50fps1TO9KO3o/vJpiNgLUkf0FfPbYsrbjo9HTmqSf2vtCJ49U33+u9uD6+6fW0YXJrIqVLz/9cWj56Uvdtcbpk+Snz9nc6f57z5/vpzW/3wvbUC28nyKrTVt5XJxqVv7AfWHtZL1zEl19gv3fnM70X2WGS/x6vvGhp75uw5aN7p6ym5Ijlbx42bto2dJ93/krAGiZegym/oF679sk06PLf31VfW9ZdPfh8MasG+RuIiUdeSk9tfkfMhowlxIb1llbEa+Dk5bM8jeSJYNDsu9yd/z1Lk6e/O2/8au+fNz6zd0k3T2cMPgFr2DVjZyUG06ruVDJIAcvhWv2tc9INl5/b6PLgsVh58em9t1ffei+NP7jF/uSAE7CGfbG7yc1gWn72yWkQ5KXBNdec11smjCqvcuSpbM23vyBkA8weWMN+v/6KxOA6+5qHU1SDEK7Z5InslruedYJxwJjAYMhFXCqcqzyR5cNTeRIbX7/FYY8BIWAwxFaNLUs/vP5LAxuuA+XDKJeef4plxQEhYDCE8nLhnd+/sMhThf02sz92yfmnmsaCcy9EGDJ5qfCRH48NZbz2laex3jWZ7oITloDBkMjLhLdef0HvbViWDA8nT2O/umtFbw+QeCwhwhDIU8bdt1zcu+iXg/1w9d59wPH1LybiMIHBgMvRyktl4nVoN337C929sQsTcZjAYIDNxMuS4ZHJ18DlR77ka8byo10omwkMBpR4HZ18K6oHbr+sFzLKJmAwgMTr2OTP362rL0iUTcBgwMw8ske8jk1eTrQnVjYBgwEiXvMrRyzfH5IyCRgMiBwtD0udf/l04iDe4HgQCBgMiHyBsnj1R/7cugyhPAIGA+Cma0wJ/ZSn27t/cLGTiYURMAiu9xyvb9un6bc83eYHZFIOAYPg8r4Xzbjh8nPSiotOT5RBwCCwvHRo36tZP7nxQkuJhRAwCMrSYTvyfpilxDIIGARl6bA9eSlx2J+nVgIBg4DyQyktHbbLBc7tEzAIJi8drr7cAxjblicwU1i7BAyCyd/5m77K4F6J7RIwCCRPXy5YLkf+RuLqsWWJdggYBGLfpTyrfEPRGgGDebJjZ3+f4Gv6KpO9sPYIWMNefeu9xGDq939b01e5/Ldpx4JEozZPvWsDfkBtntqR+iXy9JUn0xz3P+3cvd+vf2bRgoG5w3uewPLdOXa8198pnP0JWMMemtyaVrqX2kAaf3BL6pdI3+HnYG2YfCU9vfmd3jdsr7556Mk0RywHIH9dXHL+KSmq1f90TvfvwIuJ5lSnrbyvTjTqP9b+XegvVA52zyMvpTvufT71Q56+fnXXilS6p154O42vf7H349HKqxM5ZvkWWdFWKvKU+ffffzzRnJFPn3vV2kSj8hd4vp+aB+TFl6eNf3v4/9KP/31z6pcVFy1NKy8ud2rfuGlbuv5ffp0mHn35mPcB8xJcntomHnk5vfbW+2n52Sf3vlYiyB9nnjrtczfHBNai/B1m/gL94uhJadmpi1IbzlhyQrp0ecwTVE9tfju99ub7qQ1b39rZXRp7Pz3+zOt93/f41c9WFDmN5BfqW+569pgmrsPZ+wyu88Ls/61bv8UyYoPsgbUovwDkt43dF8G2rBpbFjZgG554pbenOMjyclqJ8cp7XHdMPN/3eM9E8ndTO9Kt11+QSpe/lsaTgDXFMXoo2KoC7/KQp4wclSZP3OU9xstvmez7tXbHauY0Is0QMChUiUfn21wiy3tj1659sviIrbh4aaIZAgaFumR5WSdVS9jfyRH73p3PpJI5nNUcAYNCXTN2VipFXsIr5XBCPjTSr0sW5kPJJ0YHjYBBgfLyYSnXCuaDFKUFIwf16RfeSSXKh27sgzVDwKBAJd2t5drbnkwl+ue7flPsflj+BoT+EzAoUCkBy/tepV6Ymz+ufPF0ifK1nfSfgEFhSlk+zIF46Imyr7PLS4klTmEOcjRDwKAwpZw+zIc2Sr8tUo5XiVOYJ040Q8CgMKWcPuznLaLmU57CSmMPrBkCBgXJN4QtYflww+TWMDelzVNYaScSTWDNEDAoSCl7J4+3eH/Oo5Fv7FySKHfQj07AoCCl3IZo46ZgAStwudMU1n8CBgUp4ckAUfa+9pVvMcXwETAoRN74L2EJMWIM8j6YB0kOHwGDQpRy8WvUELT1cNPZOInYfwIGhSjl7hv54ZER5adkM1wEDArh7g0wNwIGBcjHrksJ2Ktv2ksiBgGDApi+jt2yUxelkvhGoP8EDApQyrO/MocPiELAoAB/u/zUVIqoD2Ms7REmjvX3n4BBAUp68T1jyQkpmjw1un3T8BEwaFlpL74R9+NMX8NJwKBlpb34Xnp++7ezmqtSrqGb4QBHMwQMWlbaxJNvQhttH6y06JrAmiFg0LISl+xWfX1ZiiLHq7Q7vwtYMwQMWlbiYzdKW5I7lFVj5cX2d7+PeTuuaAQMWlbiBJanmgh7YfkAzNVjn0+lMYE1Q8CgRcvPLvfE35przkulK/Vj9HyyZggYtOiMU8u95qr0KSxPriVOXxEfCBqVgEGLSr/mquQp7O4fXJxKZPpqjoBBi0oPWJ7AVn/rnFSaW6+/oMjDL9nTL7yTaIaAQYtOPnFhKt0PV3+pqKXEGy4/t/dWKhNYcwQMWlTaXThmc/ctFxdxl/q855Wnr1LleDmB2BwBg5bk+x9GuQFt/jgfWHtZqxHL8brzxgtTyRzgaJaAQUuiPXcr7znliLWxb5eXDEuPV/b4pm2J5ggYtCTic7dyxB65c6yxgx158rvz+xcWvWw4Iy8dmsCatSABrYj42JIZ+WDH8rMXp/H1W/p25/V8cCRPXaWeNjzQU04fNk7AoCWfWRT7y+/qsWW9t3seeSlNPPryvIUshytffxbtsS7jD25JNEvAoCWRJ7B9zRxr3zC5NT00+cpRLaPlpcIcwxUXnR7yeWT539npw+YJGLQkwjVgczEzke3Y+WHvBf3pzW+nzVM7ej/f8d6H+71vXhY8o/u2fPSkXrCix3x8/YuJ5gkYtCT6EuJs8jS18uLTe2/DwOGN9jiFCC2JcjiBQxt/0PTVFgGDFkS6iJnZ5elrQ3ffj3YIGLQg4jVgHOyWu55NtEfAoAXR7sLBwfKpS3tf7RIwgDnKJytd99U+AYMWlPwkZg7vnkdfct1XAQQMWmAJMa4cLicPyyBgAEcoLx1ee9uTiTIIGLTANWAx5TtuWDosh4ABHIF80+L8RjkEDFqw7NRFiTjse5VJwAAOIccr73sdeENi2idg0IJBvZHvIPrej5+x71UoAYMWuA9iDLf87Nm0eerdRJkEDOATrFu/JW14wo16SyZg0ALH6MuW4+XQRvkEDGAf4hWHgAF8RLxiETCAJF4ROcsLDbP/VZ477n3eXTYCEjBgaOWb8+anKm/c9HoiHgEDhlK+ODlfpOw6r7gEDBg6OVrusBGfgAFDZcPkK+mOiefd23AACBgwNBzWGCwCBgy8vFSYD2s89cLbicEhYMBA27hpW7rlX39jyXAACRg07MwlrgNrQj4iP77+RUuGA0zAoGEmgf7LS4V5ydApw8EmYNCwHX8WsH7KU9e6B7ckBp+AAQPB1DV8BAwIzV7X8BIwIKx8wvCOif81dQ0pAQPCcV0XmYABYeTlwolHX3ZIgx4BA0LIe1z5gZMuQ2CGgAFFc7qQ2QgYNMwL8ZHJ4cqnC+1zMRsBA4oiXBwpAQOKIFzMlYABrRIujpaAQQvyPtiZpw73XemFi2MlYECjNkxuTQ9NviJcHDMBA/pu5gLke/7zJddxMW8EDFrw2pvvD8US4uapd7vT1ta04YlXhIt5J2DAvLO/RRMEDFqw9a2d6ZJ0ShoklglpmoABx8S0RVsEDFoQfULJe1uPb9pm2qJVAgYtyMtt0eSPecPkK71wmbYogYBBC/60c3eKIEcrT1t5iXDz7981bVEUAYMWvLtzVypZnrDypOX4OyUTMGhBiVEQLaIRMGjBa2+9n9o2szwoWkQlYNCCHX9uJxY5WjlYv87T1jOvixahCRhhlTDFHK18N/qm7kj/6pvvpY2bXnd6kIEjYEPu6RfeSVHlU3GR5XsErrnmvDTf9l0azOHKAYNBJGBDLk8B+QXvpEXHpUjyJBF9+eueR15Kq8aWzcsUloM1cwjDcXeGhYDRu8bn1usvSJHk6SW6/I3Dtbc9mR64/bI5R2xmWXDz1A57WQyt6rSV99WJoXfr6gvSDd86N0Wwbv2WNP7gi2lQ5Hj95MavpkvOn/3mvjlYT29+p3f44unNb1sWhCRg7OPS8z/XW9JaPnpy70W1lGXFPKnkpc6ZJbJBPYiQP/8rLlqali1Z1Pv51jd3mrDgEAQMgJA6CQACEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAELKAZtKABDLdhMYAAFVU51UV1MJACKpp7d3qmr6DwkAAqk63Qmsnq6eSwAQSV3/oVNbQgQgmunpyc6uPbsnEwAE8pfd6bnO9snV25Oj9ABEUaWp3K69x+jr+uEEAAFUKU3mH3sBq6c7kwkAAqjqqjd09QKW98HqOm1PAFC493ftPbvRC1heS6yq+n8SABSsqtK9H53d+OvNfKvp6XUJAAo2s3zY++d9f2PJivv+2K3b4gQApanS1BuPXXf2zE/3u5lvp6rHEwAUqJpOt+/78/0C9pdd0+sc5gCgON3pK43smdz3l/YLWO/CMFMYAIWp6vrn2/5r9dS+v3bQ88DyFNYrHQCUoNukbRu/u/bAXz4oYL0j9QesMwJAW2ZrUjXbHzjtH+5/ItX1WAKA1lS/fGPjd676pN/pzPpHqt2rHegAoC11d1Gw6uy+ebbfnzVgebOsqi0lAtCOTp1uPvDgxr5GDvWHd778i6c+fc6Vn+2OY5cmAGhKVY2/sfG6Hx3qXTrpMD74cHptnarnEgA047dvPPadmw73TocNWO/asM7uqxytB6Dvuq2pOnuuPLJ3PUJL/3FitK5Hnujuqo0mAJhvOV7Vnq8fat9r/3efAxEDoC/mGK+9f2SORAyAeXUU8coOuwd2oN7x+u7/kYMdAMyD3x5NvLI5T2D7Om3Fz9elqlqTAGCuqmr8gw92r515wvKc/3g6RktX3Hf9dEo/9SBMAI5E7w4bVbr9jceuW5eOwTEHLOvti013uh9IdUUCgNnU1WQ1snv10SwZHmheAjYjT2N1J93mgAcA+8kHNabT7dsev+7eNE/mNWAzlq78+dq6qr4rZADDLS8XdlI9np81ebR7XbPpS8CyvKyY9oyMmcgAhk8/wzWjbwHb15JvTFzZGelcWafuVAbAQOodzkjdPa7p3ePb/nv1ZOqzRgI2Y/HYxOKFI2msF7Oq+prJDCC8qVTVD9e7pyd37UmT/Zq2PkmjATtQDtqnFqSvpE5nbLquzuqWe7Rb8MXdT8ZolRzLByjEVO9/62qqTnV+VuRv63rPVNPBOtD/A6oeNVega6lDAAAAAElFTkSuQmCC"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3092],{33520:(A,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>s,default:()=>o,frontMatter:()=>I,metadata:()=>j,toc:()=>w});var r=n(85893),t=n(3905),E=n(17779);const I={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",slug:"woowacourse-level3-retrospective",tags:["Woowahan Techcourse","Retrospective"]},s=void 0,j={permalink:"/woowacourse-level3-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",description:"\ud68c\uace0",date:"2023-08-19T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 19\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.945,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",slug:"woowacourse-level3-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/cloudwatch"},nextItem:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",permalink:"/db-replication"}},c={authorsImageUrls:[]},w=[{value:"\ud68c\uace0",id:"\ud68c\uace0",level:3},{value:"\uc544\uc26c\uc6b4 \uc810",id:"\uc544\uc26c\uc6b4-\uc810",level:3},{value:"\uc88b\uc558\ub358 \uc810",id:"\uc88b\uc558\ub358-\uc810",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3}];function l(A){const e={a:"a",br:"br",h3:"h3",p:"p",strong:"strong",...(0,t.ah)(),...A.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(e.h3,{id:"\ud68c\uace0",children:"\ud68c\uace0"}),"\n",(0,r.jsxs)(e.p,{children:["\uc9c0\ub09c 8\uc8fc\ub294 \ub808\ubca8 1, 2 \ub54c\ubcf4\ub2e4 5\ubc30 \uc815\ub3c4 \ube60\ub974\uac8c \uc9c0\ub098\uac04 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub808\ubca8 3\uc5d0\ub294 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4, \uae30\uc220 \uc678\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4 \ubd80\uc871\ud568\uc774 \ub9ce\uc774 \ubcf4\uc600\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubd80\uc871\ud55c \ubd80\ubd84\uc744 \uc54c\uc558\uae30\uc5d0, \uc55e\uc73c\ub85c \ub354\uc6b1 \uc131\uc7a5\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub0b4\uac00 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \ud300\uc6d0\ub4e4\uc774 \uc798 \ubcf4\ucda9\ud574 \uc918\uc11c \ub4e0\ub4e0\ud588\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\uc544\uc26c\uc6b4-\uc810",children:"\uc544\uc26c\uc6b4 \uc810"}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ubb38\uc11c\ud654"})}),"\n",(0,r.jsxs)(e.p,{children:["\uac1c\uc778\uc801\uc73c\ub85c\ub294 \uae30\uc220 \uc678\uc801\uc73c\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ub0b4\uac00 \ud55c \ubd80\ubd84\uc744 \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c, \uc774\ud574\ud558\uae30 \uc27d\uac8c \ubb38\uc11c\ud654\ub97c \ud588\ub354\ub77c\uba74 \ud300\uc6d0\ub4e4\uc5d0\uac8c \ub354\uc6b1 \ub3c4\uc6c0\uc774 \ub418\uc5c8\uc744 \ud150\ub370 \uc774 \ubd80\ubd84\uc5d0 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ud22c\uc790\ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc5d0\uc11c \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubc29\ud559 \uae30\uac04 \ub3d9\uc548 \ubb38\uc11c\ud654\ub97c \ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc778 \ube14\ub85c\uadf8 \uc62c\ub9ac\uba74\uc11c \uc870\uae08 \ub354 \ucc44\uc6cc\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ub0b4\uac00 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc774\uc790"})}),"\n",(0,r.jsxs)(e.p,{children:["\uc798 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc5ec\uc11c\ub77c\ub3c4 \uc911\uac04\uc740 \uac00\ub3c4\ub85d \ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub9d0\uc744 \ud558\uae30 \uc804\uc5d0 \uc815\ub9ac\ud574\uc11c \uc758\uacac\uc744 \ub0b4\ub294 \uac83, \ubc1c\ud45c \uc900\ube44, \uac10\uc815 \uc870\uc808 \ub4f1\ub4f1\n\ubabb\ud558\ub294 \ubd80\ubd84\uc744 \uc778\uc9c0\ud558\uace0, \uac1c\uc120\ud558\uc790."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ucef4\ud3ec\ud2b8 \uc874 \ubc97\uc5b4\ub098\uae30"})}),"\n",(0,r.jsxs)(e.p,{children:["\uc870\uae08 \ub354 \ub3c4\uc804\uc801\uc73c\ub85c \ubaa9\ud45c\ub97c \uc7a1\uc558\uc73c\uba74 \uc88b\uc558\uc744 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub9e4\ubc88 \uadfc\uac70\ub97c \uac00\uc9c0\uace0 \uae30\uc220\uc744 \ub3c4\uc785\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud558\uc9c0\ub9cc \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub824\uace0 \ud558\ub294 \ubd80\ubd84\uc774 \ub2e4\uc18c \ubd80\uc871\ud588\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\uc88b\uc558\ub358-\uc810",children:"\uc88b\uc558\ub358 \uc810"}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\uc88b\uc558\ub358 \uc810\ub3c4 \ubb38\uc11c\ud654"})}),"\n",(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.a,{href:"https://tripdraw.blog",children:"\ud300 \ube14\ub85c\uadf8"}),"\ub3c4 \uba3c\uc800 \ub3c4\uc785\ud558\uc790\uace0 \uc81c\uc548\ud558\uace0, \ub0b4\uac00 \ud588\ub358 \ubd80\ubd84\uc740 \ubb38\uc11c\ud654\ub97c \uaf64 \ub9ce\uc774 \ud574\uc11c \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubc31\uc5d4\ub4dc \ud06c\ub8e8 4\uba85\uc774\uc11c \uac19\uc774 \ud55c \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c\ub294 \uae30\ub2a5 \uad6c\ud604\ud55c\ub2e4\uace0 \ubb38\uc11c\ud654\uac00 \uc870\uae08 \ubbf8\ud761\ud574\uc11c \ubcf4\ucda9\uc744 \ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ub0b4\uac00 \ub514\uc790\uc778\ud55c \ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0"})}),"\n",(0,r.jsx)("img",{src:E.Z,width:"100"}),"\n",(0,r.jsxs)(e.p,{children:["\ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0\ub97c \ub9cc\ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud300\uc6d0\ub4e4\uc774 \ub300\ud45c \uc0c9\uc0c1(\ud30c\ub780\uc0c9)\uc744 \uc815\ud574\uc92c\uace0, \uc8fc\ub9d0 \ub3d9\uc548 \uc2e0\ub098\uac8c \ub85c\uace0 \ub514\uc790\uc778\uc744 \ud588\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\uc544\ub798\uc758 D \ubd80\ubd84\uc740 \uc720\ud29c\ube0c \uac15\uc758 \ub4e4\uc73c\uba74\uc11c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\uc11c \ubfcc\ub4ef\ud558\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\uae30\uc220 \uc120\ud0dd\uc758 \uc774\uc720"})}),"\n",(0,r.jsxs)(e.p,{children:["\uae30\uc220\uc758 \ud559\uc2b5 \ube44\uc6a9, \ud604\uc7ac \uad6c\uc870\uc5d0 \uc801\ud569\ud55c\uc9c0, \uc2e4\uc81c \uac00\uc9c0\uace0 \uc788\ub294 \ub9ac\uc18c\uc2a4\ub97c \uace0\ub824\ud574\uc11c \uae30\uc220 \uc120\ud0dd\uc744 \ud558\uace0, \ub3c4\uc785\ud588\ub358 \ubd80\ubd84\uc774 \uc88b\uc558\ub2e4.",(0,r.jsx)(e.br,{}),"\n","100% \uc88b\uc740 \uc120\ud0dd\uc77c \uc21c \uc5c6\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \uc120\ud0dd\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \uc874\uc7ac\ud55c\ub2e4\uba74 \ud655\ub960\uc744 \ub192\ud600\uc8fc\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,r.jsxs)(e.p,{children:["\ud50c\ub808\uc774\uc2a4\ud1a0\uc5b4\uc5d0 \uc571\uc774 \uc62c\ub77c\uac00 \uc788\ub294 \uac70 \ub108\ubb34 \uc2e0\uae30\ud558\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\uc548\ub4dc\ub85c\uc774\ub4dc \ube0c\ub808\uba58 \uc74c\uc545\ub300(\uba67\ub3fc\uc9c0, \uc218\ub2ec, \ud551\uad6c), \uadf8\ub9ac\uace0 \ubc31\uc5d4\ub4dc \ud300\uc6d0\ub4e4(\uccb4\uc778\uc800, \ud6c4\ucd94, \ub9ac\uc624) \ub108\ubb34 \uace0\uc0dd\uc774 \ub9ce\uc558\ub2e4."]})]})}function o(A={}){const{wrapper:e}={...(0,t.ah)(),...A.components};return e?(0,r.jsx)(e,{...A,children:(0,r.jsx)(l,{...A})}):l(A)}},3905:(A,e,n)=>{n.d(e,{ah:()=>c});var r=n(67294);function t(A,e,n){return e in A?Object.defineProperty(A,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):A[e]=n,A}function E(A,e){var n=Object.keys(A);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(A);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(A,e).enumerable}))),n.push.apply(n,r)}return n}function I(A){for(var e=1;e=0||(t[n]=A[n]);return t}(A,e);if(Object.getOwnPropertySymbols){var E=Object.getOwnPropertySymbols(A);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(A,n)&&(t[n]=A[n])}return t}var j=r.createContext({}),c=function(A){var e=r.useContext(j),n=e;return A&&(n="function"==typeof A?A(e):I(I({},e),A)),n},w={inlineCode:"code",wrapper:function(A){var e=A.children;return r.createElement(r.Fragment,{},e)}},l=r.forwardRef((function(A,e){var n=A.components,t=A.mdxType,E=A.originalType,j=A.parentName,l=s(A,["components","mdxType","originalType","parentName"]),o=c(n),i=t,h=o["".concat(j,".").concat(i)]||o[i]||w[i]||E;return n?r.createElement(h,I(I({ref:e},l),{},{components:n})):r.createElement(h,I({ref:e},l))}));l.displayName="MDXCreateElement"},17779:(A,e,n)=>{n.d(e,{Z:()=>r});const r="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAbAAAAGwCAYAAADITjAqAAAACXBIWXMAACxLAAAsSwGlPZapAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAABauSURBVHgB7d1viF3lncDx59yJsZpWU6wxoqmjLthGS2vBP4u7dEqb7FIXVKIFX9Qa3xTqiyisfWeNyEKphWZgLesbxyqLi4m0wiprXHCWIlUD1bKaRljt1CjGfzSmjdaYzNn73Dg2f5wkk8w95/nd+/nANCaZ0HHM3O/8nuc551SpRYvHJhYvXLhgrJquR+sqfblK9WiqqtGPfns0AdC6uk7bq6qaSvX09jpVU52q/kOanp78y+703PbJ1dtTS6rUoI+DVU2Ppbq6IokUQHRT3QFksvua/vCuXbsnmwxaIwFb+s2JsbozsqZb8W680uIEwEDqxuzeHLM3N37nl6nP+hawj6atNd3Z8ybRAhg6U1Wdbk8f7pncNrl6KvXBvAdMuADYx1R33+ze7kR2e5pn8xqwpSvuu747Pt6W7G0BsL/eRLbt8evuTfNkXgK2dGxitD5uwUSq6rEEALP7ZbVrz83zsazYScfotBX3r5k+buRZ8QLgCFxZLxx5Nq/YpWN01BNY3us6fuFIXi68KQHAXFVp3RuPXXdzOkpHFbDekuHCkXxE8ssJAI5a9Vy1a/dVR7OkOOeAfRSvJ5KDGgDMj6nuvtjX5xqxOQVMvADokzlH7IgDJl4A9NmcInZEARMvABpyxBE7omP0Hx3YGE0A0F/dgWnBL/JJ98O942EDdtrK+36anDYEoDH1V44/vneZ1iGNHOo3exeaVelHCQCademn/+aqd3e+9IunZnuHWffA8r5XvsOGG/IC0JLt3f2wC2fbD5t1CbG77/VT8QKgRYvr4zsTs/3mJwbso3tUXZkAoE11NTbbfRM7n/z+6bCbZwDQhNykTzqVeFDAlqy83/O8ACjJ6KcWdg66cfx+hzhcsAxAobZ/sGvP2dsnV2+f+YX9J7DjRsaSeAFQnsUHTmH7BczeFwClqlO1Zt+ffxywJd+4P586HE0AUKbFS785MTbzk79OYCPTjs0DULS6M/LxFNY7xJGPJx6/cOSPCQDK9vFhjt4EtnBkwVgCgPItPmHh3mbtXUK0fAhAENNVGss/9gJWpeprCQAiqOsr8g+V/S8Aounug32286kF6SsJAALJ+2Cd1OmMJQAIZLqqR/Me2GgCgECqlL7cqevOWQkAAqmnuxNYnTx1GYBgqiovIdajCQCC6VSVCQyAcEY7CQACEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQlqQAPrkzCUnpi+edXI6adFx3X8+IZ104nHp5EULP/F93925K+1478P0p50fps1TO9KO3o/vJpiNgLUkf0FfPbYsrbjo9HTmqSf2vtCJ49U33+u9uD6+6fW0YXJrIqVLz/9cWj56Uvdtcbpk+Snz9nc6f57z5/vpzW/3wvbUC28nyKrTVt5XJxqVv7AfWHtZL1zEl19gv3fnM70X2WGS/x6vvGhp75uw5aN7p6ym5Ijlbx42bto2dJ93/krAGiZegym/oF679sk06PLf31VfW9ZdPfh8MasG+RuIiUdeSk9tfkfMhowlxIb1llbEa+Dk5bM8jeSJYNDsu9yd/z1Lk6e/O2/8au+fNz6zd0k3T2cMPgFr2DVjZyUG06ruVDJIAcvhWv2tc9INl5/b6PLgsVh58em9t1ffei+NP7jF/uSAE7CGfbG7yc1gWn72yWkQ5KXBNdec11smjCqvcuSpbM23vyBkA8weWMN+v/6KxOA6+5qHU1SDEK7Z5InslruedYJxwJjAYMhFXCqcqzyR5cNTeRIbX7/FYY8BIWAwxFaNLUs/vP5LAxuuA+XDKJeef4plxQEhYDCE8nLhnd+/sMhThf02sz92yfmnmsaCcy9EGDJ5qfCRH48NZbz2laex3jWZ7oITloDBkMjLhLdef0HvbViWDA8nT2O/umtFbw+QeCwhwhDIU8bdt1zcu+iXg/1w9d59wPH1LybiMIHBgMvRyktl4nVoN337C929sQsTcZjAYIDNxMuS4ZHJ18DlR77ka8byo10omwkMBpR4HZ18K6oHbr+sFzLKJmAwgMTr2OTP362rL0iUTcBgwMw8ske8jk1eTrQnVjYBgwEiXvMrRyzfH5IyCRgMiBwtD0udf/l04iDe4HgQCBgMiHyBsnj1R/7cugyhPAIGA+Cma0wJ/ZSn27t/cLGTiYURMAiu9xyvb9un6bc83eYHZFIOAYPg8r4Xzbjh8nPSiotOT5RBwCCwvHRo36tZP7nxQkuJhRAwCMrSYTvyfpilxDIIGARl6bA9eSlx2J+nVgIBg4DyQyktHbbLBc7tEzAIJi8drr7cAxjblicwU1i7BAyCyd/5m77K4F6J7RIwCCRPXy5YLkf+RuLqsWWJdggYBGLfpTyrfEPRGgGDebJjZ3+f4Gv6KpO9sPYIWMNefeu9xGDq939b01e5/Ldpx4JEozZPvWsDfkBtntqR+iXy9JUn0xz3P+3cvd+vf2bRgoG5w3uewPLdOXa8198pnP0JWMMemtyaVrqX2kAaf3BL6pdI3+HnYG2YfCU9vfmd3jdsr7556Mk0RywHIH9dXHL+KSmq1f90TvfvwIuJ5lSnrbyvTjTqP9b+XegvVA52zyMvpTvufT71Q56+fnXXilS6p154O42vf7H349HKqxM5ZvkWWdFWKvKU+ffffzzRnJFPn3vV2kSj8hd4vp+aB+TFl6eNf3v4/9KP/31z6pcVFy1NKy8ud2rfuGlbuv5ffp0mHn35mPcB8xJcntomHnk5vfbW+2n52Sf3vlYiyB9nnjrtczfHBNai/B1m/gL94uhJadmpi1IbzlhyQrp0ecwTVE9tfju99ub7qQ1b39rZXRp7Pz3+zOt93/f41c9WFDmN5BfqW+569pgmrsPZ+wyu88Ls/61bv8UyYoPsgbUovwDkt43dF8G2rBpbFjZgG554pbenOMjyclqJ8cp7XHdMPN/3eM9E8ndTO9Kt11+QSpe/lsaTgDXFMXoo2KoC7/KQp4wclSZP3OU9xstvmez7tXbHauY0Is0QMChUiUfn21wiy3tj1659sviIrbh4aaIZAgaFumR5WSdVS9jfyRH73p3PpJI5nNUcAYNCXTN2VipFXsIr5XBCPjTSr0sW5kPJJ0YHjYBBgfLyYSnXCuaDFKUFIwf16RfeSSXKh27sgzVDwKBAJd2t5drbnkwl+ue7flPsflj+BoT+EzAoUCkBy/tepV6Ymz+ufPF0ifK1nfSfgEFhSlk+zIF46Imyr7PLS4klTmEOcjRDwKAwpZw+zIc2Sr8tUo5XiVOYJ040Q8CgMKWcPuznLaLmU57CSmMPrBkCBgXJN4QtYflww+TWMDelzVNYaScSTWDNEDAoSCl7J4+3eH/Oo5Fv7FySKHfQj07AoCCl3IZo46ZgAStwudMU1n8CBgUp4ckAUfa+9pVvMcXwETAoRN74L2EJMWIM8j6YB0kOHwGDQpRy8WvUELT1cNPZOInYfwIGhSjl7hv54ZER5adkM1wEDArh7g0wNwIGBcjHrksJ2Ktv2ksiBgGDApi+jt2yUxelkvhGoP8EDApQyrO/MocPiELAoAB/u/zUVIqoD2Ms7REmjvX3n4BBAUp68T1jyQkpmjw1un3T8BEwaFlpL74R9+NMX8NJwKBlpb34Xnp++7ezmqtSrqGb4QBHMwQMWlbaxJNvQhttH6y06JrAmiFg0LISl+xWfX1ZiiLHq7Q7vwtYMwQMWlbiYzdKW5I7lFVj5cX2d7+PeTuuaAQMWlbiBJanmgh7YfkAzNVjn0+lMYE1Q8CgRcvPLvfE35przkulK/Vj9HyyZggYtOiMU8u95qr0KSxPriVOXxEfCBqVgEGLSr/mquQp7O4fXJxKZPpqjoBBi0oPWJ7AVn/rnFSaW6+/oMjDL9nTL7yTaIaAQYtOPnFhKt0PV3+pqKXEGy4/t/dWKhNYcwQMWlTaXThmc/ctFxdxl/q855Wnr1LleDmB2BwBg5bk+x9GuQFt/jgfWHtZqxHL8brzxgtTyRzgaJaAQUuiPXcr7znliLWxb5eXDEuPV/b4pm2J5ggYtCTic7dyxB65c6yxgx158rvz+xcWvWw4Iy8dmsCatSABrYj42JIZ+WDH8rMXp/H1W/p25/V8cCRPXaWeNjzQU04fNk7AoCWfWRT7y+/qsWW9t3seeSlNPPryvIUshytffxbtsS7jD25JNEvAoCWRJ7B9zRxr3zC5NT00+cpRLaPlpcIcwxUXnR7yeWT539npw+YJGLQkwjVgczEzke3Y+WHvBf3pzW+nzVM7ej/f8d6H+71vXhY8o/u2fPSkXrCix3x8/YuJ5gkYtCT6EuJs8jS18uLTe2/DwOGN9jiFCC2JcjiBQxt/0PTVFgGDFkS6iJnZ5elrQ3ffj3YIGLQg4jVgHOyWu55NtEfAoAXR7sLBwfKpS3tf7RIwgDnKJytd99U+AYMWlPwkZg7vnkdfct1XAQQMWmAJMa4cLicPyyBgAEcoLx1ee9uTiTIIGLTANWAx5TtuWDosh4ABHIF80+L8RjkEDFqw7NRFiTjse5VJwAAOIccr73sdeENi2idg0IJBvZHvIPrej5+x71UoAYMWuA9iDLf87Nm0eerdRJkEDOATrFu/JW14wo16SyZg0ALH6MuW4+XQRvkEDGAf4hWHgAF8RLxiETCAJF4ROcsLDbP/VZ477n3eXTYCEjBgaOWb8+anKm/c9HoiHgEDhlK+ODlfpOw6r7gEDBg6OVrusBGfgAFDZcPkK+mOiefd23AACBgwNBzWGCwCBgy8vFSYD2s89cLbicEhYMBA27hpW7rlX39jyXAACRg07MwlrgNrQj4iP77+RUuGA0zAoGEmgf7LS4V5ydApw8EmYNCwHX8WsH7KU9e6B7ckBp+AAQPB1DV8BAwIzV7X8BIwIKx8wvCOif81dQ0pAQPCcV0XmYABYeTlwolHX3ZIgx4BA0LIe1z5gZMuQ2CGgAFFc7qQ2QgYNMwL8ZHJ4cqnC+1zMRsBA4oiXBwpAQOKIFzMlYABrRIujpaAQQvyPtiZpw73XemFi2MlYECjNkxuTQ9NviJcHDMBA/pu5gLke/7zJddxMW8EDFrw2pvvD8US4uapd7vT1ta04YlXhIt5J2DAvLO/RRMEDFqw9a2d6ZJ0ShoklglpmoABx8S0RVsEDFoQfULJe1uPb9pm2qJVAgYtyMtt0eSPecPkK71wmbYogYBBC/60c3eKIEcrT1t5iXDz7981bVEUAYMWvLtzVypZnrDypOX4OyUTMGhBiVEQLaIRMGjBa2+9n9o2szwoWkQlYNCCHX9uJxY5WjlYv87T1jOvixahCRhhlTDFHK18N/qm7kj/6pvvpY2bXnd6kIEjYEPu6RfeSVHlU3GR5XsErrnmvDTf9l0azOHKAYNBJGBDLk8B+QXvpEXHpUjyJBF9+eueR15Kq8aWzcsUloM1cwjDcXeGhYDRu8bn1usvSJHk6SW6/I3Dtbc9mR64/bI5R2xmWXDz1A57WQyt6rSV99WJoXfr6gvSDd86N0Wwbv2WNP7gi2lQ5Hj95MavpkvOn/3mvjlYT29+p3f44unNb1sWhCRg7OPS8z/XW9JaPnpy70W1lGXFPKnkpc6ZJbJBPYiQP/8rLlqali1Z1Pv51jd3mrDgEAQMgJA6CQACEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAELKAZtKABDLdhMYAAFVU51UV1MJACKpp7d3qmr6DwkAAqk63Qmsnq6eSwAQSV3/oVNbQgQgmunpyc6uPbsnEwAE8pfd6bnO9snV25Oj9ABEUaWp3K69x+jr+uEEAAFUKU3mH3sBq6c7kwkAAqjqqjd09QKW98HqOm1PAFC493ftPbvRC1heS6yq+n8SABSsqtK9H53d+OvNfKvp6XUJAAo2s3zY++d9f2PJivv+2K3b4gQApanS1BuPXXf2zE/3u5lvp6rHEwAUqJpOt+/78/0C9pdd0+sc5gCgON3pK43smdz3l/YLWO/CMFMYAIWp6vrn2/5r9dS+v3bQ88DyFNYrHQCUoNukbRu/u/bAXz4oYL0j9QesMwJAW2ZrUjXbHzjtH+5/ItX1WAKA1lS/fGPjd676pN/pzPpHqt2rHegAoC11d1Gw6uy+ebbfnzVgebOsqi0lAtCOTp1uPvDgxr5GDvWHd778i6c+fc6Vn+2OY5cmAGhKVY2/sfG6Hx3qXTrpMD74cHptnarnEgA047dvPPadmw73TocNWO/asM7uqxytB6Dvuq2pOnuuPLJ3PUJL/3FitK5Hnujuqo0mAJhvOV7Vnq8fat9r/3efAxEDoC/mGK+9f2SORAyAeXUU8coOuwd2oN7x+u7/kYMdAMyD3x5NvLI5T2D7Om3Fz9elqlqTAGCuqmr8gw92r515wvKc/3g6RktX3Hf9dEo/9SBMAI5E7w4bVbr9jceuW5eOwTEHLOvti013uh9IdUUCgNnU1WQ1snv10SwZHmheAjYjT2N1J93mgAcA+8kHNabT7dsev+7eNE/mNWAzlq78+dq6qr4rZADDLS8XdlI9np81ebR7XbPpS8CyvKyY9oyMmcgAhk8/wzWjbwHb15JvTFzZGelcWafuVAbAQOodzkjdPa7p3ePb/nv1ZOqzRgI2Y/HYxOKFI2msF7Oq+prJDCC8qVTVD9e7pyd37UmT/Zq2PkmjATtQDtqnFqSvpE5nbLquzuqWe7Rb8MXdT8ZolRzLByjEVO9/62qqTnV+VuRv63rPVNPBOtD/A6oeNVega6lDAAAAAElFTkSuQmCC"}}]); \ No newline at end of file diff --git a/assets/js/101b58de.2b9af44d.js b/assets/js/101b58de.2fd700f0.js similarity index 95% rename from assets/js/101b58de.2b9af44d.js rename to assets/js/101b58de.2fd700f0.js index c88f088be..ef4d86569 100644 --- a/assets/js/101b58de.2b9af44d.js +++ b/assets/js/101b58de.2fd700f0.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6084],{86942:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var r=n(85893),a=n(3905);const l={title:"JSR-310",slug:"jsr-310",tags:["Java","Time"]},i=void 0,o={permalink:"/jsr-310",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-08-JSR-310.mdx",source:"@site/blog/2023-1/2023-01-08-JSR-310.mdx",title:"JSR-310",description:"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API",date:"2023-01-08T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 8\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Time",permalink:"/tags/time"}],readingTime:1.685,hasTruncateMarker:!1,authors:[],frontMatter:{title:"JSR-310",slug:"jsr-310",tags:["Java","Time"]},unlisted:!1,prevItem:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",permalink:"/kotlin-null"},nextItem:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",permalink:"/the-essence-of-object-orientation"}},s={authorsImageUrls:[]},c=[{value:"LocalDate, LocalTime, LocalDateTime",id:"localdate-localtime-localdatetime",level:3},{value:"Instant",id:"instant",level:3},{value:"Duration, Period",id:"duration-period",level:3},{value:"TemporalAdjusters",id:"temporaladjusters",level:3},{value:"DateTimeFormatter",id:"datetimeformatter",level:3},{value:"ZoneId, ZoneOffset",id:"zoneid-zoneoffset",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API",(0,r.jsx)(t.br,{}),"\n","ISO-8601\uc744 \uae30\ubc18\uc73c\ub85c \uc791\uc131",(0,r.jsx)(t.br,{}),"\n","\uc124\uacc4 \ubaa9\ud45c \u2192 \ubd88\ubcc0, Fluent API, \uba85\ud655\ud558\uace0 \uba85\uc2dc\uc801, \ud655\uc7a5 \uac00\ub2a5\uc131"]}),"\n",(0,r.jsx)(t.admonition,{title:"ISO-8601",type:"note",children:(0,r.jsx)(t.p,{children:"\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc5d0 \uad00\ub828\ub41c \ub370\uc774\ud130\ub97c \ub2e4\ub8e8\ub294 \uad6d\uc81c \ud45c\uc900"})}),"\n",(0,r.jsx)(t.h3,{id:"localdate-localtime-localdatetime",children:"LocalDate, LocalTime, LocalDateTime"}),"\n",(0,r.jsx)(t.p,{children:"\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4"}),"\n",(0,r.jsx)(t.h3,{id:"instant",children:"Instant"}),"\n",(0,r.jsxs)(t.p,{children:["\uc720\ub2c9\uc2a4 \uc2dc\uac04(1970-01-01, 00:00:00 UTC) \uae30\uc900\uc73c\ub85c \ud2b9\uc815 \uc9c0\uc810\uae4c\uc9c0\uc758 \uc2dc\uac04\uc744 \ucd08\ub85c \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4",(0,r.jsx)(t.br,{}),"\n","\uae30\uacc4\uc758 \uad00\uc810\uc5d0\uc11c \uc2dc\uac04 \ud45c\ud604"]}),"\n",(0,r.jsx)(t.h3,{id:"duration-period",children:"Duration, Period"}),"\n",(0,r.jsx)(t.p,{children:"\uac04\uaca9\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4"}),"\n",(0,r.jsx)(t.h3,{id:"temporaladjusters",children:"TemporalAdjusters"}),"\n",(0,r.jsxs)(t.p,{children:["\ubcf5\uc7a1\ud55c \ub0a0\uc9dc \uc870\uc815\uc774 \ud544\uc694\ud560 \ub54c \uc0ac\uc6a9",(0,r.jsx)(t.br,{}),"\n","\ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uc5ec \ucee4\uc2a4\ud140 TemporalAdjuster\ub97c \uad6c\ud604 \uac00\ub2a5"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"@FunctionalInterface\npublic interface TemporalAdjuster {\n Temporal adjustInto(Temporal temporal);\n}\n"})}),"\n",(0,r.jsx)(t.h3,{id:"datetimeformatter",children:"DateTimeFormatter"}),"\n",(0,r.jsxs)(t.p,{children:["\ub0a0\uc9dc\uc640 \uc2dc\uac04 \ud3ec\ub9f7 \ud074\ub798\uc2a4",(0,r.jsx)(t.br,{}),"\n","\ud2b9\uc815 \ub0a0\uc9dc \ud328\ud134\uc774\ub098, DateTimeFormatterBuilder\ub97c \uc774\uc6a9\ud574\uc11c \ucee4\uc2a4\ud140\ud55c \ud3ec\ub9f7\uc744 \uc0dd\uc131 \uac00\ub2a5"]}),"\n",(0,r.jsx)(t.h3,{id:"zoneid-zoneoffset",children:"ZoneId, ZoneOffset"}),"\n",(0,r.jsxs)(t.p,{children:["ZoneId\ub294 \uc9c0\uc5ed ID\ub294 ",(0,r.jsx)(t.code,{children:"\u2018\uc9c0\uc5ed/\ub3c4\uc2dc\u2019"})," \ud615\uc2dd, ZoneOffset\uc740 \uc2dc\ucc28 UTC \uae30\uc900 \uace0\uc815\ub41c \uc2dc\uac04 \ucc28\uc774 \uc774\uc6a9",(0,r.jsx)(t.br,{}),"\n","ZoneId\uc758 \uacbd\uc6b0 IANA Time Zone Database\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc9c0\uc5ed \uc9d1\ud569 \uc815\ubcf4 \uc0ac\uc6a9"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"Instant instant = Instant.now();\nLocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);\n"})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://product.kyobobook.co.kr/detail/S000001810171",children:"\ubaa8\ub358 \uc790\ubc14 \uc778 \uc561\uc158"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://d2.naver.com/helloworld/645609",children:"Java\uc758 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://www.w3.org/TR/NOTE-datetime",children:"ISO-8601"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://download.oracle.com/otn-pub/jcp/date_time-0.2-edr-oth-JSpec/date_time-0_2-edr-spec.pdf?AuthParam=1673171124_74a718be92efe4911c6977c02965aff4",children:"JSR-310 Spec"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://www.baeldung.com/java-temporal-adjuster",children:"Temporal Adjuster"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html",children:"DateTimeFormatter"})}),"\n"]})]})}function m(e={}){const{wrapper:t}={...(0,a.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),p=c(n),u=a,h=p["".concat(s,".").concat(u)]||p[u]||d[u]||l;return n?r.createElement(h,i(i({ref:t},m),{},{components:n})):r.createElement(h,i({ref:t},m))}));m.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6084],{86942:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var r=n(85893),a=n(3905);const l={title:"JSR-310",slug:"jsr-310",tags:["Java","Time"]},i=void 0,o={permalink:"/jsr-310",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-08-JSR-310.mdx",source:"@site/blog/2023-1/2023-01-08-JSR-310.mdx",title:"JSR-310",description:"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API",date:"2023-01-08T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 8\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Time",permalink:"/tags/time"}],readingTime:1.685,hasTruncateMarker:!1,authors:[],frontMatter:{title:"JSR-310",slug:"jsr-310",tags:["Java","Time"]},unlisted:!1,prevItem:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",permalink:"/the-essence-of-object-orientation"},nextItem:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",permalink:"/kotlin-null"}},s={authorsImageUrls:[]},c=[{value:"LocalDate, LocalTime, LocalDateTime",id:"localdate-localtime-localdatetime",level:3},{value:"Instant",id:"instant",level:3},{value:"Duration, Period",id:"duration-period",level:3},{value:"TemporalAdjusters",id:"temporaladjusters",level:3},{value:"DateTimeFormatter",id:"datetimeformatter",level:3},{value:"ZoneId, ZoneOffset",id:"zoneid-zoneoffset",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API",(0,r.jsx)(t.br,{}),"\n","ISO-8601\uc744 \uae30\ubc18\uc73c\ub85c \uc791\uc131",(0,r.jsx)(t.br,{}),"\n","\uc124\uacc4 \ubaa9\ud45c \u2192 \ubd88\ubcc0, Fluent API, \uba85\ud655\ud558\uace0 \uba85\uc2dc\uc801, \ud655\uc7a5 \uac00\ub2a5\uc131"]}),"\n",(0,r.jsx)(t.admonition,{title:"ISO-8601",type:"note",children:(0,r.jsx)(t.p,{children:"\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc5d0 \uad00\ub828\ub41c \ub370\uc774\ud130\ub97c \ub2e4\ub8e8\ub294 \uad6d\uc81c \ud45c\uc900"})}),"\n",(0,r.jsx)(t.h3,{id:"localdate-localtime-localdatetime",children:"LocalDate, LocalTime, LocalDateTime"}),"\n",(0,r.jsx)(t.p,{children:"\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4"}),"\n",(0,r.jsx)(t.h3,{id:"instant",children:"Instant"}),"\n",(0,r.jsxs)(t.p,{children:["\uc720\ub2c9\uc2a4 \uc2dc\uac04(1970-01-01, 00:00:00 UTC) \uae30\uc900\uc73c\ub85c \ud2b9\uc815 \uc9c0\uc810\uae4c\uc9c0\uc758 \uc2dc\uac04\uc744 \ucd08\ub85c \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4",(0,r.jsx)(t.br,{}),"\n","\uae30\uacc4\uc758 \uad00\uc810\uc5d0\uc11c \uc2dc\uac04 \ud45c\ud604"]}),"\n",(0,r.jsx)(t.h3,{id:"duration-period",children:"Duration, Period"}),"\n",(0,r.jsx)(t.p,{children:"\uac04\uaca9\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4"}),"\n",(0,r.jsx)(t.h3,{id:"temporaladjusters",children:"TemporalAdjusters"}),"\n",(0,r.jsxs)(t.p,{children:["\ubcf5\uc7a1\ud55c \ub0a0\uc9dc \uc870\uc815\uc774 \ud544\uc694\ud560 \ub54c \uc0ac\uc6a9",(0,r.jsx)(t.br,{}),"\n","\ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uc5ec \ucee4\uc2a4\ud140 TemporalAdjuster\ub97c \uad6c\ud604 \uac00\ub2a5"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"@FunctionalInterface\npublic interface TemporalAdjuster {\n Temporal adjustInto(Temporal temporal);\n}\n"})}),"\n",(0,r.jsx)(t.h3,{id:"datetimeformatter",children:"DateTimeFormatter"}),"\n",(0,r.jsxs)(t.p,{children:["\ub0a0\uc9dc\uc640 \uc2dc\uac04 \ud3ec\ub9f7 \ud074\ub798\uc2a4",(0,r.jsx)(t.br,{}),"\n","\ud2b9\uc815 \ub0a0\uc9dc \ud328\ud134\uc774\ub098, DateTimeFormatterBuilder\ub97c \uc774\uc6a9\ud574\uc11c \ucee4\uc2a4\ud140\ud55c \ud3ec\ub9f7\uc744 \uc0dd\uc131 \uac00\ub2a5"]}),"\n",(0,r.jsx)(t.h3,{id:"zoneid-zoneoffset",children:"ZoneId, ZoneOffset"}),"\n",(0,r.jsxs)(t.p,{children:["ZoneId\ub294 \uc9c0\uc5ed ID\ub294 ",(0,r.jsx)(t.code,{children:"\u2018\uc9c0\uc5ed/\ub3c4\uc2dc\u2019"})," \ud615\uc2dd, ZoneOffset\uc740 \uc2dc\ucc28 UTC \uae30\uc900 \uace0\uc815\ub41c \uc2dc\uac04 \ucc28\uc774 \uc774\uc6a9",(0,r.jsx)(t.br,{}),"\n","ZoneId\uc758 \uacbd\uc6b0 IANA Time Zone Database\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc9c0\uc5ed \uc9d1\ud569 \uc815\ubcf4 \uc0ac\uc6a9"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"Instant instant = Instant.now();\nLocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);\n"})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://product.kyobobook.co.kr/detail/S000001810171",children:"\ubaa8\ub358 \uc790\ubc14 \uc778 \uc561\uc158"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://d2.naver.com/helloworld/645609",children:"Java\uc758 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://www.w3.org/TR/NOTE-datetime",children:"ISO-8601"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://download.oracle.com/otn-pub/jcp/date_time-0.2-edr-oth-JSpec/date_time-0_2-edr-spec.pdf?AuthParam=1673171124_74a718be92efe4911c6977c02965aff4",children:"JSR-310 Spec"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://www.baeldung.com/java-temporal-adjuster",children:"Temporal Adjuster"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html",children:"DateTimeFormatter"})}),"\n"]})]})}function m(e={}){const{wrapper:t}={...(0,a.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),p=c(n),u=a,h=p["".concat(s,".").concat(u)]||p[u]||d[u]||l;return n?r.createElement(h,i(i({ref:t},m),{},{components:n})):r.createElement(h,i({ref:t},m))}));m.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/1236fad7.e7249cac.js b/assets/js/1236fad7.24b71e81.js similarity index 99% rename from assets/js/1236fad7.e7249cac.js rename to assets/js/1236fad7.24b71e81.js index ce219e47e..d87b30d5c 100644 --- a/assets/js/1236fad7.e7249cac.js +++ b/assets/js/1236fad7.24b71e81.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6515],{38491:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var t=s(85893),r=s(3905);const i={title:"Docusaurus",slug:"docusaurus",tags:["Documentation"]},a=void 0,c={permalink:"/docusaurus",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",source:"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",title:"Docusaurus",description:"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4.",date:"2023-06-18T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 18\uc77c",tags:[{label:"Documentation",permalink:"/tags/documentation"}],readingTime:10.095,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Docusaurus",slug:"docusaurus",tags:["Documentation"]},unlisted:!1,prevItem:{title:"\uc6f9\uc18c\ucf13",permalink:"/websocket"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",permalink:"/woowacourse-level2-retrospective"}},l={authorsImageUrls:[]},o=[{value:"\uc124\uce58",id:"\uc124\uce58",level:2},{value:"\ubc30\ud3ec",id:"\ubc30\ud3ec",level:2},{value:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131",id:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac-\uc0dd\uc131",level:3},{value:"\uc124\uc815 \ud30c\uc77c \uc218\uc815",id:"\uc124\uc815-\ud30c\uc77c-\uc218\uc815",level:3},{value:"\ud1a0\ud070 \uc124\uc815",id:"\ud1a0\ud070-\uc124\uc815",level:3},{value:"\ube0c\ub79c\uce58 \uc0dd\uc131",id:"\ube0c\ub79c\uce58-\uc0dd\uc131",level:3},{value:"\uc6cc\ud06c\ud50c\ub85c \uc791\uc131",id:"\uc6cc\ud06c\ud50c\ub85c-\uc791\uc131",level:3},{value:"\ub313\uae00 \uae30\ub2a5",id:"\ub313\uae00-\uae30\ub2a5",level:2},{value:"giscus \uc124\uc815",id:"giscus-\uc124\uc815",level:3},{value:"docusaurus \uc124\uc815",id:"docusaurus-\uc124\uc815",level:3},{value:"\uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30",id:"\uc54c\uace0\ub9ac\uc544-\uc124\uc815-\ubc0f-\uc9c1\uc811-\uad00\ub9ac\ud558\uae30",level:2},{value:"\uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778",id:"\uc54c\uace0\ub9ac\uc544-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\uc0dd\uc131-\ubc0f-\ud0a4-\ud655\uc778",level:3},{value:"\ud0a4 \uc0dd\uc131",id:"\ud0a4-\uc0dd\uc131",level:3},{value:".env \ud30c\uc77c \uc0dd\uc131",id:"env-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"config \ud30c\uc77c \uc0dd\uc131",id:"config-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1",id:"docker-\uc774\uc6a9\ud558\uc5ec-\ud06c\ub864\ub9c1",level:3},{value:"docusaurus \uc124\uc815",id:"docusaurus-\uc124\uc815-1",level:3},{value:"\ubd80\uac00 \uc124\uc815",id:"\ubd80\uac00-\uc124\uc815",level:2},{value:"\ud654\uba74 \uc0c1\ub2e8 Github Icon",id:"\ud654\uba74-\uc0c1\ub2e8-github-icon",level:3},{value:"\ucf54\ub4dc\ube14\ub7ed",id:"\ucf54\ub4dc\ube14\ub7ed",level:3},{value:"mermaid",id:"mermaid",level:3},{value:"\uad6d\uc81c\ud654 \uc124\uc815",id:"\uad6d\uc81c\ud654-\uc124\uc815",level:3},{value:"\ube14\ub85c\uadf8 \uae00 author",id:"\ube14\ub85c\uadf8-\uae00-author",level:3}];function u(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,r.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h2,{id:"\uc124\uce58",children:"\uc124\uce58"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/docs/installation",children:"\uacf5\uc2dd \ud648\ud398\uc774\uc9c0"}),"\uc5d0 \ub4e4\uc5b4\uac00\uc11c \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn create docusaurus\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ubc30\ud3ec",children:"\ubc30\ud3ec"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/docs/next/deployment#deploying-to-github-pages",children:"\ubc30\ud3ec \uc548\ub0b4 \ubb38\uc11c"}),(0,t.jsx)(n.br,{}),"\n","netlify\ub098 vercel \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ud50c\ub7ab\ud3fc\uc744 \ucd94\ucc9c\ud558\uace0 \uc788\uace0, \uac04\ub2e8\ud558\uace0, \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \ubc30\ud3ec\ub97c \ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 github pages\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac-\uc0dd\uc131",children:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["github pages\ub97c \uc774\uc6a9\ud558\ub824\uba74 ",(0,t.jsx)(n.a,{href:"https://github.com/greeng00se/greeng00se.github.io",children:"\uc608\uc2dc"}),"\uc640 \uac19\uc774 ",(0,t.jsx)(n.code,{children:"username.github.io"})," \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c organization\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ",(0,t.jsx)(n.code,{children:"organization.github.io"})," \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc124\uc815-\ud30c\uc77c-\uc218\uc815",children:"\uc124\uc815 \ud30c\uc77c \uc218\uc815"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"module.exports = {\n // ...\n url: 'https://greeng00se.github.io',\n baseUrl: '/',\n projectName: 'greeng00se.github.io',\n organizationName: 'greeng00se',\n trailingSlash: false,\n // ...\n};\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ud1a0\ud070-\uc124\uc815",children:"\ud1a0\ud070 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["github action\uc744 \uc704\ud574 \ubc30\ud3ec\uc6a9 \ud1a0\ud070\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uc5ec \uc0dd\uc131\ud55c \ub808\ud3ec\uc9c0\ud1a0\ub9ac\uc5d0 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 \ud1a0\ud070\uc744 \ud074\ub798\uc2dd \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ud588\uace0 \uc2a4\ucf54\ud504\ub294 [repo, user, workflow] \uc744 \uc124\uc815\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"github",src:s(29094).Z+"",width:"1598",height:"1670"})}),"\n",(0,t.jsx)(n.h3,{id:"\ube0c\ub79c\uce58-\uc0dd\uc131",children:"\ube0c\ub79c\uce58 \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["github\uc5d0\uc11c gh-pages \ube0c\ub79c\uce58\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","repository -> settings -> pages -> branch\uc5d0\uc11c \uc0dd\uc131\ud55c gh-pages\ub85c \ube0c\ub79c\uce58\ub97c \ubcc0\uacbd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc124\uc815\ud55c \ube0c\ub79c\uce58\uac00 \ubc30\ud3ec \ube0c\ub79c\uce58\uac00 \ub418\uba70, \ud574\ub2f9 \ube0c\ub79c\uce58\uc5d0 \uc788\ub294 \ud30c\uc77c\ub4e4\uc744 \uc774\uc6a9\ud574\uc11c \uc815\uc801 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc6cc\ud06c\ud50c\ub85c-\uc791\uc131",children:"\uc6cc\ud06c\ud50c\ub85c \uc791\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["Docusaurus 2.0 \uae30\uc900 Node.js 16.14 \uc774\uc0c1\uc758 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec\uc2dc\uc5d0\ub294 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c DEPLOY_TOKEN \uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yml",metastring:'title=".github/workflows/deploy.yml"',children:"name: blog\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n name: Deploy to GitHub Pages\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v2\n - uses: actions/setup-node@v3\n with:\n node-version: 18\n cache: yarn\n\n - name: Install dependencies\n run: yarn install --frozen-lockfile\n - name: Build website\n run: yarn build\n\n - name: Deploy to GitHub Pages\n uses: peaceiris/actions-gh-pages@v3\n with:\n github_token: ${{ secrets.DEPLOY_TOKEN }}\n publish_dir: ./build\n user_name: github-actions[bot]\n user_email: 41898282+github-actions[bot]@users.noreply.github.com\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ub313\uae00-\uae30\ub2a5",children:"\ub313\uae00 \uae30\ub2a5"}),"\n",(0,t.jsx)(n.p,{children:"giscus\ub97c \uc774\uc6a9\ud558\uc5ec \ub313\uae00 \uae30\ub2a5\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"giscus-\uc124\uc815",children:"giscus \uc124\uc815"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"\uacf5\uac1c \uc800\uc7a5\uc18c\uc5ec\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"giscus \uc571\uc774 \uc124\uce58\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Discussions \uae30\ub2a5\uc774 \ud574\ub2f9 \uc800\uc7a5\uc18c\uc5d0\uc11c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ",(0,t.jsx)(n.a,{href:"https://giscus.app/ko",children:"giscus"}),"\ub97c \ud655\uc778\ud558\uc790."]}),"\n",(0,t.jsx)(n.h3,{id:"docusaurus-\uc124\uc815",children:"docusaurus \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/ko/docs/next/swizzling",children:"swizzling"}),"\uc744 \uc774\uc6a9\ud558\uc5ec \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac10\uc2fc\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc5d0 \uac8c\uc2dc\ubb3c\uc744 giscus\uac00 \ud3ec\ud568\ub41c \ub9ac\uc561\ud2b8 \ucef4\ud3ec\ub10c\ud2b8\ub85c \uac10\uc2f8\ub294 \ud615\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec BlogPostItem\uc744 \ucd94\ucd9c\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap\n"})}),"\n",(0,t.jsxs)(n.p,{children:["\uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uba74 ",(0,t.jsx)(n.code,{children:"/src/theme/BlogPostItem/index.js"})," \uc704\uce58\uc5d0 \ud30c\uc77c\uc774 \uc0dd\uc131\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud30c\uc77c\uc758 \ub0b4\uc6a9\uc744 \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud558\uace0, \uc774\ub54c setAttribute \ubd80\ubd84\uc740 \uc801\uc808\ud558\uac8c \uc790\uc2e0\uc758 giscus \uc124\uc815\uc744 \uc774\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="/src/theme/BlogPostItem/index.js"',children:'import OriginalBlogPostItem from "@theme-original/BlogPostItem";\nimport React, { useEffect, useRef } from "react";\n// @ts-expect-error internal code\nimport { useColorMode } from "@docusaurus/theme-common";\nimport { useBlogPost } from "@docusaurus/theme-common/internal";\n\nconst giscusSelector = "iframe.giscus-frame";\n\nfunction BlogPostItem(props) {\n const { colorMode } = useColorMode();\n const { isBlogPostPage } = useBlogPost();\n const giscusTheme = colorMode === "dark" ? "dark" : "light";\n const containerRef = useRef(null);\n\n useEffect(() => {\n if (!isBlogPostPage) return;\n\n const giscusEl = containerRef.current.querySelector(giscusSelector);\n\n const createGiscusEl = () => {\n const script = document.createElement("script");\n\n script.src = "https://giscus.app/client.js";\n script.setAttribute("data-repo", "teco-chat/teco-chat.github.io");\n script.setAttribute("data-repo-id", "R_kgDOJZ5j0Q");\n script.setAttribute("data-category", "Announcements");\n script.setAttribute("data-category-id", "DIC_kwDOJZ5j0c4CXS_Q");\n script.setAttribute("data-mapping", "pathname");\n script.setAttribute("data-strict", "0");\n script.setAttribute("data-reactions-enabled", "1");\n script.setAttribute("data-emit-metadata", "0");\n script.setAttribute("data-input-position", "bottom");\n script.setAttribute("data-theme", giscusTheme);\n script.setAttribute("data-lang", "ko");\n script.crossOrigin = "anonymous";\n script.async = true;\n \n containerRef.current.appendChild(script);\n };\n\n const postThemeMessage = () => {\n const message = {\n setConfig: {\n theme: giscusTheme,\n }\n };\n\n giscusEl.contentWindow.postMessage({ giscus: message }, "https://giscus.app");\n };\n\n giscusEl ? postThemeMessage() : createGiscusEl();\n }, [giscusTheme]);\n\n return (\n <>\n \n {isBlogPostPage &&
}\n \n );\n}\n\nexport default BlogPostItem;\n'})}),"\n",(0,t.jsx)(n.h2,{id:"\uc54c\uace0\ub9ac\uc544-\uc124\uc815-\ubc0f-\uc9c1\uc811-\uad00\ub9ac\ud558\uae30",children:"\uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uc54c\uace0\ub9ac\uc544\ub97c \uc0ac\uc6a9\ud558\uba74 \uac80\uc0c9 \uae30\ub2a5\uc744 \ucd94\uac00\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc720\ub8cc \ud50c\ub79c\uc774\ub098 netlify\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ud06c\ub864\ub7ec\ub97c \ub530\ub85c \uc81c\uacf5\ud574 \uc8fc\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ubb34\ub8cc \ud50c\ub79c\uc740 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uacfc, ",(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/",children:"docsearch"}),"\ub97c \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","docsearch\uc5d0 \ub4f1\ub85d\ud55c\ub2e4\uba74 \uc77c\uc8fc\uc77c\uc5d0 \ud55c \ubc88\uc529 \ud06c\ub864\ub9c1\uc774 \uc9c4\ud589\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/run-your-own/",children:"\uc9c1\uc811 \uc778\ub371\uc2a4 \uc218\uc9d1"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/config-file",children:"\uc124\uc815 \ud30c\uc77c"})}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc54c\uace0\ub9ac\uc544-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\uc0dd\uc131-\ubc0f-\ud0a4-\ud655\uc778",children:"\uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778"}),"\n",(0,t.jsxs)(n.p,{children:["\ud68c\uc6d0\uac00\uc785\uc744 \ud558\uace0 \uc0c8\ub85c\uc6b4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131\uc744 \ub204\ub978\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0dd\uc131\uc744 \ub2e4 \ub9c8\uce58\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 api \ud0a4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"algolia",src:s(41785).Z+"",width:"3194",height:"1520"})}),"\n",(0,t.jsx)(n.h3,{id:"\ud0a4-\uc0dd\uc131",children:"\ud0a4 \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\uae30 \uc704\ud55c \ud0a4\ub97c \uc0dd\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","addObject, editSettings, deleteIndex acl(\uc811\uadfc \uc81c\uc5b4 \ubaa9\ub85d)\uc774 \uc788\uc73c\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"key",src:s(4730).Z+"",width:"2496",height:"832"})}),"\n",(0,t.jsx)(n.h3,{id:"env-\ud30c\uc77c-\uc0dd\uc131",children:".env \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,t.jsx)(n.p,{children:"\ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0c1\ub2e8\uc5d0 .env \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:"APPLICATION_ID=MVIU5UEMOM\nAPI_KEY=\uc778\ub371\uc2a4_\uc0dd\uc131\uc6a9_\ud0a4\n"})}),"\n",(0,t.jsx)(n.h3,{id:"config-\ud30c\uc77c-\uc0dd\uc131",children:"config \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["\ub9c8\ucc2c\uac00\uc9c0\ub85c \ucd5c\uc0c1\ub2e8\uc5d0 config.json \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4.\n\uc124\uc815 \ud30c\uc77c\uc740 \ud574\ub2f9 ",(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/config-file",children:"\ub9c1\ud06c"}),"\ub97c \ucc38\uace0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ub294 Docusaurus\uc758 ",(0,t.jsx)(n.a,{href:"https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json",children:"\uc124\uc815 \ud30c\uc77c"}),"\uc744 \ucc38\uace0\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",metastring:'title="config.json"',children:'{\n "index_name": "teco",\n "start_urls": [\n "https://teco-chat.github.io/"\n ],\n "sitemap_urls": [\n "https://teco-chat.github.io/sitemap.xml"\n ],\n "sitemap_alternate_links": true,\n "stop_urls": [\n "/tests"\n ],\n "selectors": {\n "lvl0": {\n "selector": "(//ul[contains(@class,\'menu__list\')]//a[contains(@class, \'menu__link menu__link--sublist menu__link--active\')]/text() | //nav[contains(@class, \'navbar\')]//a[contains(@class, \'navbar__link--active\')]/text())[last()]",\n "type": "xpath",\n "global": true,\n "default_value": "Documentation"\n },\n "lvl1": "header h1",\n "lvl2": "article h2",\n "lvl3": "article h3",\n "lvl4": "article h4",\n "lvl5": "article h5, article td:first-child",\n "lvl6": "article h6",\n "text": "article p, article li, article td:last-child"\n },\n "strip_chars": " .,;:#",\n "custom_settings": {\n "separatorsToIndex": "_",\n "attributesForFaceting": [\n "language",\n "version",\n "type",\n "docusaurus_tag"\n ],\n "attributesToRetrieve": [\n "hierarchy",\n "content",\n "anchor",\n "url",\n "url_without_anchor",\n "type"\n ]\n },\n "conversation_id": [\n "833762294"\n ],\n "nb_hits": 46250\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"docker-\uc774\uc6a9\ud558\uc5ec-\ud06c\ub864\ub9c1",children:"docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1"}),"\n",(0,t.jsxs)(n.p,{children:["docker\uc640 jq\uac00 \ud544\uc694\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","jq\uac00 \uc124\uce58\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74 mac \uae30\uc900 brew\ub97c \uc774\uc6a9\ud574\uc11c \uc124\uce58\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"brew install jq\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec .env\uc640 config.json\uc744 \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\uc744 \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper\n'})}),"\n",(0,t.jsx)(n.h3,{id:"docusaurus-\uc124\uc815-1",children:"docusaurus \uc124\uc815"}),"\n",(0,t.jsx)(n.p,{children:"\uc804\uc5d0 \ud655\uc778\ud55c APP ID, Search-Only API KEY, IndexName\uc744 \uc774\uc6a9\ud558\uc5ec docusaurus.config \ud30c\uc77c\uc5d0 \uc124\uc815\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"themeConfig:\n /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n ({\n ...\n algolia: {\n appId: 'MVIU5UEMOM', // Application ID\n apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key\n indexName: 'teco', // config.json\uc5d0 \uc124\uc815\ud55c \uc778\ub371\uc2a4\uba85\n contextualSearch: true,\n },\n })\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ubd80\uac00-\uc124\uc815",children:"\ubd80\uac00 \uc124\uc815"}),"\n",(0,t.jsx)(n.h3,{id:"\ud654\uba74-\uc0c1\ub2e8-github-icon",children:"\ud654\uba74 \uc0c1\ub2e8 Github Icon"}),"\n",(0,t.jsx)(n.p,{children:"\ud30c\uc77c \ucd5c\ud558\ub2e8\uc5d0 \uc544\ub798 css \uad6c\ubb38\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-css",metastring:'title="/src/css/custom.css"',children:".header-github-link:hover {\n opacity: 0.6;\n}\n\n.header-github-link:before {\n content: '';\n width: 24px;\n height: 24px;\n display: flex;\n background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\")\n no-repeat;\n}\n\nhtml[data-theme='dark'] .header-github-link:before {\n background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\")\n no-repeat;\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"themeconfig -> navbar\uc5d0 github link\ub97c \uc124\uc815\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"navbar: {\n title: 'HELLO',\n items: [\n {\n href: 'https://github.com/greeng00se',\n position: 'right',\n className: 'header-github-link',\n 'aria-label': 'GitHub repository',\n },\n ],\n},\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ucf54\ub4dc\ube14\ub7ed",children:"\ucf54\ub4dc\ube14\ub7ed"}),"\n",(0,t.jsxs)(n.p,{children:["java\ub098 kotlin\uc758 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ub77c\uc774\ud305\uc744 \uc9c0\uc6d0\ud574 \uc8fc\uc9c0 \uc54a\ub294\ub2e4.",(0,t.jsx)(n.br,{}),"\n","prism \uc124\uc815\uc744 \uc544\ub798\uc640 \uac19\uc774 \ubcc0\uacbd\ud574 \uc900\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"prism: {\n theme: lightCodeTheme,\n darkTheme: darkCodeTheme,\n additionalLanguages: ['java', 'kotlin'],\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"mermaid",children:"mermaid"}),"\n",(0,t.jsxs)(n.p,{children:["mermaid\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 ",(0,t.jsx)(n.code,{children:"@docusaurus/theme-mermaid"})," \ub97c \uc124\uce58\ud574\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn add @docusaurus/theme-mermaid\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc124\uce58 \ud6c4 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"const config = {\n ...\n markdown: {\n mermaid: true,\n },\n themes: [\n '@docusaurus/theme-mermaid'\n ],\n};\n"})}),"\n",(0,t.jsx)(n.p,{children:"themeConfig\uc5d0\uc11c mermaid\uc758 \ud14c\ub9c8\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"themeConfig:\n /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n ({\n ...\n mermaid: {\n theme: {\n light: 'neutral', \n dark: 'dark'\n },\n },\n }),\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uad6d\uc81c\ud654-\uc124\uc815",children:"\uad6d\uc81c\ud654 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uad6d\uc81c\ud654 \uc124\uc815\uc744 \ud55c\ub2e4\uba74 ",(0,t.jsx)(n.code,{children:"Older Entries"})," \ud615\ud0dc\uc758 \uc124\uba85\uc774 ",(0,t.jsx)(n.code,{children:"\ub2e4\uc74c \ud398\uc774\uc9c0"})," \ub85c \ubcc0\uacbd\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc124\uc815\ud30c\uc77c\uc5d0\uc11c i18n\uc5d0 \uc788\ub294 \ub85c\ucf00\uc77c \uc124\uc815\uc744 ko\ub85c \ubcc0\uacbd\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:'i18n: {\n defaultLocale: "ko",\n locales: ["ko"],\n},\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ube14\ub85c\uadf8-\uae00-author",children:"\ube14\ub85c\uadf8 \uae00 author"}),"\n",(0,t.jsx)(n.p,{children:"\ud300\uc6d0 \ubcc4\ub85c \ubb38\uc11c\ub97c \uad00\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc5b4\ub5a4 \ud300\uc6d0\uc774 \uae00\uc744 \uc791\uc131\ud588\ub294\uc9c0 \uc124\uc815\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"author",src:s(31897).Z+"",width:"2362",height:"1076"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"authors.yml"})," \ud30c\uc77c\uc744 \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \uae30\ubcf8 \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yml",metastring:'title="/blog/authors.yml"',children:"herb:\n name: \ud5c8\ube0c\n title: Backend\n url: https://github.com/greeng00se\n image_url: https://github.com/greeng00se.png\n\nmallang:\n name: \ub9d0\ub791\n title: Backend\n url: https://github.com/shin-mallang\n image_url: https://github.com/shin-mallang.png\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ube14\ub85c\uadf8 \uae00\uc744 \uc791\uc131\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc774 authors\uc5d0 \ub123\uc5b4\uc8fc\uae30\ub9cc \ud558\uba74 \ub41c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-mdx",children:"---\nslug: 1\ntitle: Hello World\nauthors: [herb, mallang]\ntags: [hello, docusaurus]\n---\n\n\uccab \ubc88\uc9f8 \ubb38\uc11c \ub0b4\uc6a9\n"})})]})}function d(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},3905:(e,n,s)=>{s.d(n,{ah:()=>o});var t=s(67294);function r(e,n,s){return n in e?Object.defineProperty(e,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[n]=s,e}function i(e,n){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),s.push.apply(s,t)}return s}function a(e){for(var n=1;n=0||(r[s]=e[s]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,s)&&(r[s]=e[s])}return r}var l=t.createContext({}),o=function(e){var n=t.useContext(l),s=n;return e&&(s="function"==typeof e?e(n):a(a({},n),e)),s},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var s=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=o(s),g=r,p=h["".concat(l,".").concat(g)]||h[g]||u[g]||i;return s?t.createElement(p,a(a({ref:n},d),{},{components:s})):t.createElement(p,a({ref:n},d))}));d.displayName="MDXCreateElement"},41785:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/algolia-3dbac5c1606f7f0daed9cb27a429db50.png"},31897:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/author-1bd517bb7763257e2139e1063fd92492.png"},29094:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/github-d866f69755a1e17d4f17a262bd30d56d.png"},4730:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/key-2d0b59e69e9ca0b21c49b76159266e74.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6515],{38491:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var t=s(85893),r=s(3905);const i={title:"Docusaurus",slug:"docusaurus",tags:["Documentation"]},a=void 0,c={permalink:"/docusaurus",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",source:"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",title:"Docusaurus",description:"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4.",date:"2023-06-18T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 18\uc77c",tags:[{label:"Documentation",permalink:"/tags/documentation"}],readingTime:10.095,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Docusaurus",slug:"docusaurus",tags:["Documentation"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",permalink:"/woowacourse-level2-retrospective"},nextItem:{title:"\uc6f9\uc18c\ucf13",permalink:"/websocket"}},l={authorsImageUrls:[]},o=[{value:"\uc124\uce58",id:"\uc124\uce58",level:2},{value:"\ubc30\ud3ec",id:"\ubc30\ud3ec",level:2},{value:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131",id:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac-\uc0dd\uc131",level:3},{value:"\uc124\uc815 \ud30c\uc77c \uc218\uc815",id:"\uc124\uc815-\ud30c\uc77c-\uc218\uc815",level:3},{value:"\ud1a0\ud070 \uc124\uc815",id:"\ud1a0\ud070-\uc124\uc815",level:3},{value:"\ube0c\ub79c\uce58 \uc0dd\uc131",id:"\ube0c\ub79c\uce58-\uc0dd\uc131",level:3},{value:"\uc6cc\ud06c\ud50c\ub85c \uc791\uc131",id:"\uc6cc\ud06c\ud50c\ub85c-\uc791\uc131",level:3},{value:"\ub313\uae00 \uae30\ub2a5",id:"\ub313\uae00-\uae30\ub2a5",level:2},{value:"giscus \uc124\uc815",id:"giscus-\uc124\uc815",level:3},{value:"docusaurus \uc124\uc815",id:"docusaurus-\uc124\uc815",level:3},{value:"\uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30",id:"\uc54c\uace0\ub9ac\uc544-\uc124\uc815-\ubc0f-\uc9c1\uc811-\uad00\ub9ac\ud558\uae30",level:2},{value:"\uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778",id:"\uc54c\uace0\ub9ac\uc544-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\uc0dd\uc131-\ubc0f-\ud0a4-\ud655\uc778",level:3},{value:"\ud0a4 \uc0dd\uc131",id:"\ud0a4-\uc0dd\uc131",level:3},{value:".env \ud30c\uc77c \uc0dd\uc131",id:"env-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"config \ud30c\uc77c \uc0dd\uc131",id:"config-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1",id:"docker-\uc774\uc6a9\ud558\uc5ec-\ud06c\ub864\ub9c1",level:3},{value:"docusaurus \uc124\uc815",id:"docusaurus-\uc124\uc815-1",level:3},{value:"\ubd80\uac00 \uc124\uc815",id:"\ubd80\uac00-\uc124\uc815",level:2},{value:"\ud654\uba74 \uc0c1\ub2e8 Github Icon",id:"\ud654\uba74-\uc0c1\ub2e8-github-icon",level:3},{value:"\ucf54\ub4dc\ube14\ub7ed",id:"\ucf54\ub4dc\ube14\ub7ed",level:3},{value:"mermaid",id:"mermaid",level:3},{value:"\uad6d\uc81c\ud654 \uc124\uc815",id:"\uad6d\uc81c\ud654-\uc124\uc815",level:3},{value:"\ube14\ub85c\uadf8 \uae00 author",id:"\ube14\ub85c\uadf8-\uae00-author",level:3}];function u(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,r.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h2,{id:"\uc124\uce58",children:"\uc124\uce58"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/docs/installation",children:"\uacf5\uc2dd \ud648\ud398\uc774\uc9c0"}),"\uc5d0 \ub4e4\uc5b4\uac00\uc11c \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn create docusaurus\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ubc30\ud3ec",children:"\ubc30\ud3ec"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/docs/next/deployment#deploying-to-github-pages",children:"\ubc30\ud3ec \uc548\ub0b4 \ubb38\uc11c"}),(0,t.jsx)(n.br,{}),"\n","netlify\ub098 vercel \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ud50c\ub7ab\ud3fc\uc744 \ucd94\ucc9c\ud558\uace0 \uc788\uace0, \uac04\ub2e8\ud558\uace0, \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \ubc30\ud3ec\ub97c \ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 github pages\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac-\uc0dd\uc131",children:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["github pages\ub97c \uc774\uc6a9\ud558\ub824\uba74 ",(0,t.jsx)(n.a,{href:"https://github.com/greeng00se/greeng00se.github.io",children:"\uc608\uc2dc"}),"\uc640 \uac19\uc774 ",(0,t.jsx)(n.code,{children:"username.github.io"})," \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c organization\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ",(0,t.jsx)(n.code,{children:"organization.github.io"})," \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc124\uc815-\ud30c\uc77c-\uc218\uc815",children:"\uc124\uc815 \ud30c\uc77c \uc218\uc815"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"module.exports = {\n // ...\n url: 'https://greeng00se.github.io',\n baseUrl: '/',\n projectName: 'greeng00se.github.io',\n organizationName: 'greeng00se',\n trailingSlash: false,\n // ...\n};\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ud1a0\ud070-\uc124\uc815",children:"\ud1a0\ud070 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["github action\uc744 \uc704\ud574 \ubc30\ud3ec\uc6a9 \ud1a0\ud070\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uc5ec \uc0dd\uc131\ud55c \ub808\ud3ec\uc9c0\ud1a0\ub9ac\uc5d0 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 \ud1a0\ud070\uc744 \ud074\ub798\uc2dd \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ud588\uace0 \uc2a4\ucf54\ud504\ub294 [repo, user, workflow] \uc744 \uc124\uc815\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"github",src:s(29094).Z+"",width:"1598",height:"1670"})}),"\n",(0,t.jsx)(n.h3,{id:"\ube0c\ub79c\uce58-\uc0dd\uc131",children:"\ube0c\ub79c\uce58 \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["github\uc5d0\uc11c gh-pages \ube0c\ub79c\uce58\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","repository -> settings -> pages -> branch\uc5d0\uc11c \uc0dd\uc131\ud55c gh-pages\ub85c \ube0c\ub79c\uce58\ub97c \ubcc0\uacbd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc124\uc815\ud55c \ube0c\ub79c\uce58\uac00 \ubc30\ud3ec \ube0c\ub79c\uce58\uac00 \ub418\uba70, \ud574\ub2f9 \ube0c\ub79c\uce58\uc5d0 \uc788\ub294 \ud30c\uc77c\ub4e4\uc744 \uc774\uc6a9\ud574\uc11c \uc815\uc801 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc6cc\ud06c\ud50c\ub85c-\uc791\uc131",children:"\uc6cc\ud06c\ud50c\ub85c \uc791\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["Docusaurus 2.0 \uae30\uc900 Node.js 16.14 \uc774\uc0c1\uc758 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec\uc2dc\uc5d0\ub294 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c DEPLOY_TOKEN \uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yml",metastring:'title=".github/workflows/deploy.yml"',children:"name: blog\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n name: Deploy to GitHub Pages\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v2\n - uses: actions/setup-node@v3\n with:\n node-version: 18\n cache: yarn\n\n - name: Install dependencies\n run: yarn install --frozen-lockfile\n - name: Build website\n run: yarn build\n\n - name: Deploy to GitHub Pages\n uses: peaceiris/actions-gh-pages@v3\n with:\n github_token: ${{ secrets.DEPLOY_TOKEN }}\n publish_dir: ./build\n user_name: github-actions[bot]\n user_email: 41898282+github-actions[bot]@users.noreply.github.com\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ub313\uae00-\uae30\ub2a5",children:"\ub313\uae00 \uae30\ub2a5"}),"\n",(0,t.jsx)(n.p,{children:"giscus\ub97c \uc774\uc6a9\ud558\uc5ec \ub313\uae00 \uae30\ub2a5\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"giscus-\uc124\uc815",children:"giscus \uc124\uc815"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"\uacf5\uac1c \uc800\uc7a5\uc18c\uc5ec\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"giscus \uc571\uc774 \uc124\uce58\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Discussions \uae30\ub2a5\uc774 \ud574\ub2f9 \uc800\uc7a5\uc18c\uc5d0\uc11c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ",(0,t.jsx)(n.a,{href:"https://giscus.app/ko",children:"giscus"}),"\ub97c \ud655\uc778\ud558\uc790."]}),"\n",(0,t.jsx)(n.h3,{id:"docusaurus-\uc124\uc815",children:"docusaurus \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/ko/docs/next/swizzling",children:"swizzling"}),"\uc744 \uc774\uc6a9\ud558\uc5ec \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac10\uc2fc\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc5d0 \uac8c\uc2dc\ubb3c\uc744 giscus\uac00 \ud3ec\ud568\ub41c \ub9ac\uc561\ud2b8 \ucef4\ud3ec\ub10c\ud2b8\ub85c \uac10\uc2f8\ub294 \ud615\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec BlogPostItem\uc744 \ucd94\ucd9c\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap\n"})}),"\n",(0,t.jsxs)(n.p,{children:["\uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uba74 ",(0,t.jsx)(n.code,{children:"/src/theme/BlogPostItem/index.js"})," \uc704\uce58\uc5d0 \ud30c\uc77c\uc774 \uc0dd\uc131\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud30c\uc77c\uc758 \ub0b4\uc6a9\uc744 \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud558\uace0, \uc774\ub54c setAttribute \ubd80\ubd84\uc740 \uc801\uc808\ud558\uac8c \uc790\uc2e0\uc758 giscus \uc124\uc815\uc744 \uc774\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="/src/theme/BlogPostItem/index.js"',children:'import OriginalBlogPostItem from "@theme-original/BlogPostItem";\nimport React, { useEffect, useRef } from "react";\n// @ts-expect-error internal code\nimport { useColorMode } from "@docusaurus/theme-common";\nimport { useBlogPost } from "@docusaurus/theme-common/internal";\n\nconst giscusSelector = "iframe.giscus-frame";\n\nfunction BlogPostItem(props) {\n const { colorMode } = useColorMode();\n const { isBlogPostPage } = useBlogPost();\n const giscusTheme = colorMode === "dark" ? "dark" : "light";\n const containerRef = useRef(null);\n\n useEffect(() => {\n if (!isBlogPostPage) return;\n\n const giscusEl = containerRef.current.querySelector(giscusSelector);\n\n const createGiscusEl = () => {\n const script = document.createElement("script");\n\n script.src = "https://giscus.app/client.js";\n script.setAttribute("data-repo", "teco-chat/teco-chat.github.io");\n script.setAttribute("data-repo-id", "R_kgDOJZ5j0Q");\n script.setAttribute("data-category", "Announcements");\n script.setAttribute("data-category-id", "DIC_kwDOJZ5j0c4CXS_Q");\n script.setAttribute("data-mapping", "pathname");\n script.setAttribute("data-strict", "0");\n script.setAttribute("data-reactions-enabled", "1");\n script.setAttribute("data-emit-metadata", "0");\n script.setAttribute("data-input-position", "bottom");\n script.setAttribute("data-theme", giscusTheme);\n script.setAttribute("data-lang", "ko");\n script.crossOrigin = "anonymous";\n script.async = true;\n \n containerRef.current.appendChild(script);\n };\n\n const postThemeMessage = () => {\n const message = {\n setConfig: {\n theme: giscusTheme,\n }\n };\n\n giscusEl.contentWindow.postMessage({ giscus: message }, "https://giscus.app");\n };\n\n giscusEl ? postThemeMessage() : createGiscusEl();\n }, [giscusTheme]);\n\n return (\n <>\n \n {isBlogPostPage &&
}\n \n );\n}\n\nexport default BlogPostItem;\n'})}),"\n",(0,t.jsx)(n.h2,{id:"\uc54c\uace0\ub9ac\uc544-\uc124\uc815-\ubc0f-\uc9c1\uc811-\uad00\ub9ac\ud558\uae30",children:"\uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uc54c\uace0\ub9ac\uc544\ub97c \uc0ac\uc6a9\ud558\uba74 \uac80\uc0c9 \uae30\ub2a5\uc744 \ucd94\uac00\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc720\ub8cc \ud50c\ub79c\uc774\ub098 netlify\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ud06c\ub864\ub7ec\ub97c \ub530\ub85c \uc81c\uacf5\ud574 \uc8fc\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ubb34\ub8cc \ud50c\ub79c\uc740 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uacfc, ",(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/",children:"docsearch"}),"\ub97c \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","docsearch\uc5d0 \ub4f1\ub85d\ud55c\ub2e4\uba74 \uc77c\uc8fc\uc77c\uc5d0 \ud55c \ubc88\uc529 \ud06c\ub864\ub9c1\uc774 \uc9c4\ud589\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/run-your-own/",children:"\uc9c1\uc811 \uc778\ub371\uc2a4 \uc218\uc9d1"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/config-file",children:"\uc124\uc815 \ud30c\uc77c"})}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc54c\uace0\ub9ac\uc544-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\uc0dd\uc131-\ubc0f-\ud0a4-\ud655\uc778",children:"\uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778"}),"\n",(0,t.jsxs)(n.p,{children:["\ud68c\uc6d0\uac00\uc785\uc744 \ud558\uace0 \uc0c8\ub85c\uc6b4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131\uc744 \ub204\ub978\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0dd\uc131\uc744 \ub2e4 \ub9c8\uce58\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 api \ud0a4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"algolia",src:s(41785).Z+"",width:"3194",height:"1520"})}),"\n",(0,t.jsx)(n.h3,{id:"\ud0a4-\uc0dd\uc131",children:"\ud0a4 \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\uae30 \uc704\ud55c \ud0a4\ub97c \uc0dd\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","addObject, editSettings, deleteIndex acl(\uc811\uadfc \uc81c\uc5b4 \ubaa9\ub85d)\uc774 \uc788\uc73c\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"key",src:s(4730).Z+"",width:"2496",height:"832"})}),"\n",(0,t.jsx)(n.h3,{id:"env-\ud30c\uc77c-\uc0dd\uc131",children:".env \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,t.jsx)(n.p,{children:"\ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0c1\ub2e8\uc5d0 .env \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:"APPLICATION_ID=MVIU5UEMOM\nAPI_KEY=\uc778\ub371\uc2a4_\uc0dd\uc131\uc6a9_\ud0a4\n"})}),"\n",(0,t.jsx)(n.h3,{id:"config-\ud30c\uc77c-\uc0dd\uc131",children:"config \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["\ub9c8\ucc2c\uac00\uc9c0\ub85c \ucd5c\uc0c1\ub2e8\uc5d0 config.json \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4.\n\uc124\uc815 \ud30c\uc77c\uc740 \ud574\ub2f9 ",(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/config-file",children:"\ub9c1\ud06c"}),"\ub97c \ucc38\uace0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ub294 Docusaurus\uc758 ",(0,t.jsx)(n.a,{href:"https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json",children:"\uc124\uc815 \ud30c\uc77c"}),"\uc744 \ucc38\uace0\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",metastring:'title="config.json"',children:'{\n "index_name": "teco",\n "start_urls": [\n "https://teco-chat.github.io/"\n ],\n "sitemap_urls": [\n "https://teco-chat.github.io/sitemap.xml"\n ],\n "sitemap_alternate_links": true,\n "stop_urls": [\n "/tests"\n ],\n "selectors": {\n "lvl0": {\n "selector": "(//ul[contains(@class,\'menu__list\')]//a[contains(@class, \'menu__link menu__link--sublist menu__link--active\')]/text() | //nav[contains(@class, \'navbar\')]//a[contains(@class, \'navbar__link--active\')]/text())[last()]",\n "type": "xpath",\n "global": true,\n "default_value": "Documentation"\n },\n "lvl1": "header h1",\n "lvl2": "article h2",\n "lvl3": "article h3",\n "lvl4": "article h4",\n "lvl5": "article h5, article td:first-child",\n "lvl6": "article h6",\n "text": "article p, article li, article td:last-child"\n },\n "strip_chars": " .,;:#",\n "custom_settings": {\n "separatorsToIndex": "_",\n "attributesForFaceting": [\n "language",\n "version",\n "type",\n "docusaurus_tag"\n ],\n "attributesToRetrieve": [\n "hierarchy",\n "content",\n "anchor",\n "url",\n "url_without_anchor",\n "type"\n ]\n },\n "conversation_id": [\n "833762294"\n ],\n "nb_hits": 46250\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"docker-\uc774\uc6a9\ud558\uc5ec-\ud06c\ub864\ub9c1",children:"docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1"}),"\n",(0,t.jsxs)(n.p,{children:["docker\uc640 jq\uac00 \ud544\uc694\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","jq\uac00 \uc124\uce58\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74 mac \uae30\uc900 brew\ub97c \uc774\uc6a9\ud574\uc11c \uc124\uce58\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"brew install jq\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec .env\uc640 config.json\uc744 \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\uc744 \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper\n'})}),"\n",(0,t.jsx)(n.h3,{id:"docusaurus-\uc124\uc815-1",children:"docusaurus \uc124\uc815"}),"\n",(0,t.jsx)(n.p,{children:"\uc804\uc5d0 \ud655\uc778\ud55c APP ID, Search-Only API KEY, IndexName\uc744 \uc774\uc6a9\ud558\uc5ec docusaurus.config \ud30c\uc77c\uc5d0 \uc124\uc815\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"themeConfig:\n /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n ({\n ...\n algolia: {\n appId: 'MVIU5UEMOM', // Application ID\n apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key\n indexName: 'teco', // config.json\uc5d0 \uc124\uc815\ud55c \uc778\ub371\uc2a4\uba85\n contextualSearch: true,\n },\n })\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ubd80\uac00-\uc124\uc815",children:"\ubd80\uac00 \uc124\uc815"}),"\n",(0,t.jsx)(n.h3,{id:"\ud654\uba74-\uc0c1\ub2e8-github-icon",children:"\ud654\uba74 \uc0c1\ub2e8 Github Icon"}),"\n",(0,t.jsx)(n.p,{children:"\ud30c\uc77c \ucd5c\ud558\ub2e8\uc5d0 \uc544\ub798 css \uad6c\ubb38\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-css",metastring:'title="/src/css/custom.css"',children:".header-github-link:hover {\n opacity: 0.6;\n}\n\n.header-github-link:before {\n content: '';\n width: 24px;\n height: 24px;\n display: flex;\n background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\")\n no-repeat;\n}\n\nhtml[data-theme='dark'] .header-github-link:before {\n background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\")\n no-repeat;\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"themeconfig -> navbar\uc5d0 github link\ub97c \uc124\uc815\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"navbar: {\n title: 'HELLO',\n items: [\n {\n href: 'https://github.com/greeng00se',\n position: 'right',\n className: 'header-github-link',\n 'aria-label': 'GitHub repository',\n },\n ],\n},\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ucf54\ub4dc\ube14\ub7ed",children:"\ucf54\ub4dc\ube14\ub7ed"}),"\n",(0,t.jsxs)(n.p,{children:["java\ub098 kotlin\uc758 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ub77c\uc774\ud305\uc744 \uc9c0\uc6d0\ud574 \uc8fc\uc9c0 \uc54a\ub294\ub2e4.",(0,t.jsx)(n.br,{}),"\n","prism \uc124\uc815\uc744 \uc544\ub798\uc640 \uac19\uc774 \ubcc0\uacbd\ud574 \uc900\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"prism: {\n theme: lightCodeTheme,\n darkTheme: darkCodeTheme,\n additionalLanguages: ['java', 'kotlin'],\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"mermaid",children:"mermaid"}),"\n",(0,t.jsxs)(n.p,{children:["mermaid\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 ",(0,t.jsx)(n.code,{children:"@docusaurus/theme-mermaid"})," \ub97c \uc124\uce58\ud574\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn add @docusaurus/theme-mermaid\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc124\uce58 \ud6c4 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"const config = {\n ...\n markdown: {\n mermaid: true,\n },\n themes: [\n '@docusaurus/theme-mermaid'\n ],\n};\n"})}),"\n",(0,t.jsx)(n.p,{children:"themeConfig\uc5d0\uc11c mermaid\uc758 \ud14c\ub9c8\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"themeConfig:\n /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n ({\n ...\n mermaid: {\n theme: {\n light: 'neutral', \n dark: 'dark'\n },\n },\n }),\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uad6d\uc81c\ud654-\uc124\uc815",children:"\uad6d\uc81c\ud654 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uad6d\uc81c\ud654 \uc124\uc815\uc744 \ud55c\ub2e4\uba74 ",(0,t.jsx)(n.code,{children:"Older Entries"})," \ud615\ud0dc\uc758 \uc124\uba85\uc774 ",(0,t.jsx)(n.code,{children:"\ub2e4\uc74c \ud398\uc774\uc9c0"})," \ub85c \ubcc0\uacbd\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc124\uc815\ud30c\uc77c\uc5d0\uc11c i18n\uc5d0 \uc788\ub294 \ub85c\ucf00\uc77c \uc124\uc815\uc744 ko\ub85c \ubcc0\uacbd\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:'i18n: {\n defaultLocale: "ko",\n locales: ["ko"],\n},\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ube14\ub85c\uadf8-\uae00-author",children:"\ube14\ub85c\uadf8 \uae00 author"}),"\n",(0,t.jsx)(n.p,{children:"\ud300\uc6d0 \ubcc4\ub85c \ubb38\uc11c\ub97c \uad00\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc5b4\ub5a4 \ud300\uc6d0\uc774 \uae00\uc744 \uc791\uc131\ud588\ub294\uc9c0 \uc124\uc815\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"author",src:s(31897).Z+"",width:"2362",height:"1076"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"authors.yml"})," \ud30c\uc77c\uc744 \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \uae30\ubcf8 \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yml",metastring:'title="/blog/authors.yml"',children:"herb:\n name: \ud5c8\ube0c\n title: Backend\n url: https://github.com/greeng00se\n image_url: https://github.com/greeng00se.png\n\nmallang:\n name: \ub9d0\ub791\n title: Backend\n url: https://github.com/shin-mallang\n image_url: https://github.com/shin-mallang.png\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ube14\ub85c\uadf8 \uae00\uc744 \uc791\uc131\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc774 authors\uc5d0 \ub123\uc5b4\uc8fc\uae30\ub9cc \ud558\uba74 \ub41c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-mdx",children:"---\nslug: 1\ntitle: Hello World\nauthors: [herb, mallang]\ntags: [hello, docusaurus]\n---\n\n\uccab \ubc88\uc9f8 \ubb38\uc11c \ub0b4\uc6a9\n"})})]})}function d(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},3905:(e,n,s)=>{s.d(n,{ah:()=>o});var t=s(67294);function r(e,n,s){return n in e?Object.defineProperty(e,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[n]=s,e}function i(e,n){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),s.push.apply(s,t)}return s}function a(e){for(var n=1;n=0||(r[s]=e[s]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,s)&&(r[s]=e[s])}return r}var l=t.createContext({}),o=function(e){var n=t.useContext(l),s=n;return e&&(s="function"==typeof e?e(n):a(a({},n),e)),s},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var s=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=o(s),g=r,p=h["".concat(l,".").concat(g)]||h[g]||u[g]||i;return s?t.createElement(p,a(a({ref:n},d),{},{components:s})):t.createElement(p,a({ref:n},d))}));d.displayName="MDXCreateElement"},41785:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/algolia-3dbac5c1606f7f0daed9cb27a429db50.png"},31897:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/author-1bd517bb7763257e2139e1063fd92492.png"},29094:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/github-d866f69755a1e17d4f17a262bd30d56d.png"},4730:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/key-2d0b59e69e9ca0b21c49b76159266e74.png"}}]); \ No newline at end of file diff --git a/assets/js/1251d98b.8c5715bc.js b/assets/js/1251d98b.9baae304.js similarity index 98% rename from assets/js/1251d98b.8c5715bc.js rename to assets/js/1251d98b.9baae304.js index 946a12804..c23f214de 100644 --- a/assets/js/1251d98b.8c5715bc.js +++ b/assets/js/1251d98b.9baae304.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6276],{40469:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>j,frontMatter:()=>c,metadata:()=>l,toc:()=>a});var s=r(85893),t=r(3905);const c={title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",slug:"chess-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,l={permalink:"/chess-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",description:"1, 2\ub2e8\uacc4//github.com/woowacourse/java-chess/pull/441",date:"2023-03-31T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 31\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.705,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",slug:"chess-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",permalink:"/woowacourse-level1-retrospective"},nextItem:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",permalink:"/grasp"}},o={authorsImageUrls:[]},a=[{value:"\uccb4\uc2a4",id:"\uccb4\uc2a4",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function h(e){const n={a:"a",admonition:"admonition",br:"br",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.ah)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,s.jsxs)(n.p,{children:["1, 2\ub2e8\uacc4: ",(0,s.jsx)(n.a,{href:"https://github.com/woowacourse/java-chess/pull/441",children:"https://github.com/woowacourse/java-chess/pull/441"}),(0,s.jsx)(n.br,{}),"\n","3, 4\ub2e8\uacc4: ",(0,s.jsx)(n.a,{href:"https://github.com/woowacourse/java-chess/pull/529",children:"https://github.com/woowacourse/java-chess/pull/529"})]})}),"\n",(0,s.jsx)(n.h3,{id:"\uccb4\uc2a4",children:"\uccb4\uc2a4"}),"\n",(0,s.jsxs)(n.p,{children:["\uccb4\uc2a4 \ubbf8\uc158\uc5d0\ub294 \uac00\ube44\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4!",(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4\ub294 \uc774\uc804 \ubbf8\uc158\ub4e4\ubcf4\ub2e4 \ud6e8\uc52c \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778\uc774\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \uac00\ube44\uc640 \ub098\ub294 \uccb4\uc2a4 \ub3c4\uba54\uc778\uc774 \uc775\uc219\ud574\uc11c \ub354 \ud3b8\ud55c \ub9c8\uc74c\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc5b4\ub824\uc6e0\ub358 \ubd80\ubd84\uc740 \uae30\ubb3c\uc758 \uc774\ub3d9, \uc774\ub3d9\uc2dc \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:["\uac00\ube44\uac00 \uc9d1\uc5d0\uac00\uc11c\ub3c4 \uae30\ubb3c\uc758 \uc774\ub3d9 \uad00\ub828\ud574 \uc0dd\uac01 \uc815\ub9ac\ud55c \uae00\uc744 \ubcf4\ub0b4\uc918\uc11c \ub354\uc6b1 \ube68\ub9ac \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ucd5c\uc885\uc801\uc73c\ub85c \uacb0\uc815\ud55c \ubd80\ubd84\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5\uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","Rank\uc640 File\uc740 \uac01\uac01 \uc704\uce58\uac12\uc744 \uac00\uc9c0\uace0 \uc788\uace0, \uac12\uc758 \ucc28\uc774\ub97c \uc774\uc6a9\ud574\uc11c \uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uacc4\uc0b0\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc9c1\uc120 \u2192 Rank\uc640 File \ucc28\uc774 \uc911 \ud558\ub098\uac00 0\uc774\uc5b4\uc57c \ud55c\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub300\uac01\uc120 \u2192 Rank\uc640 File \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \uac19\uc544\uc57c \ud55c\ub2e4. ex) abs(-2) == abs(2)",(0,s.jsx)(n.br,{}),"\n","\ub098\uc774\ud2b8 \u2192 \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \ud558\ub098\ub294 2 \ub098\uba38\uc9c0 \ud558\ub098\ub294 1\uc774\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ub3c4\ucc29 \uce78\uc758 \uae30\ubb3c \uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","\uc544\uad70 \u2192 \uc774\ub3d9\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc801\uad70 \u2192 \uc774\ub3d9\uc774 \uac00\ub2a5\ud558\ub2e4. \uc801\uad70\uc744 \uc7a1\ub294\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc911\uac04\uc5d0 \uae30\ubb3c \uc874\uc7ac \uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","\uc774\ub3d9 \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\uba74 \uc548\ub41c\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9"}),(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4 \ubbf8\uc158\uc740 \ud2b9\ubcc4\ud558\uac8c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc5f0\uacb0\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4 \uac8c\uc784\uc758 \uc0c1\ud0dc\ub97c \ub2e4\uc74c\uc758 \ub450\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uc815\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95"}),"\n",(0,s.jsx)(n.li,{children:"\uae30\ubcf4\ub97c \uc800\uc7a5\ud558\uace0 \uac8c\uc784\uc744 \ubd88\ub7ec\uc640 \uae30\ubcf4\ub300\ub85c \uc774\ub3d9\uc2dc\ud0a4\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\uae30\ubb3c\uc774 \uc774\ub3d9\ud560 \ub54c\ub9c8\ub2e4 \uac12\uc744 \uc800\uc7a5\ud558\uace0 \uc2f6\uc5c8\uace0, \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc774\uc720\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\ud134\uacfc \uac19\uc740 \ubd80\uac00\uc801\uc778 \uc694\uc18c\ub97c \uc800\uc7a5\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,s.jsx)(n.li,{children:"\uc774\ub3d9\uc744 \ud560 \ub54c \uae30\ubb3c\uc774 \uc7a1\ud788\ub294 \uacbd\uc6b0 update \ucffc\ub9ac(\uc774\ub3d9 \uae30\ubb3c)\uc640 delete(\uc7a1\ud78c \uae30\ubb3c) 2\uac1c\uc758 \ucffc\ub9ac\ub97c \ub0a0\ub824\uc57c \ud55c\ub2e4."}),"\n",(0,s.jsx)(n.li,{children:"\ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ub3c4\uba54\uc778\uc758 \ubcc0\uacbd\uc774 \ud06c\uac8c(\ucd08\uae30 \uc0c1\ud0dc\ub97c \uad6c\uc131\ud558\ub294 \ubd80\ubd84) \uc77c\uc5b4\ub098\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\uc815\ub9ac\ud558\uc790\uba74 \uae30\ubb3c \uc804\uccb4 \uc800\uc7a5\uacfc \uae30\ubcf4 \uc800\uc7a5\uc740 \ub2e4\uc74c\uacfc \ucc28\uc774\uac00 \uc788\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ubcf4\ub4dc\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc\uc5d0\uc11c 32\uac1c\uc758 Insert \ucffc\ub9ac(\uae30\ubb3c\uc758 \uc704\uce58) + \uae30\ubb3c \uc774\ub3d9 \uc2dc \uc6c0\uc9c1\uc784 \ubcc0\uacbd(\uc7a1\ud788\ub294 \uacbd\uc6b0 2\uac1c\uc758 \ucffc\ub9ac)",(0,s.jsx)(n.br,{}),"\n","\uae30\ubcf4\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uad6c\uc131 + \uc800\uc7a5\ub41c \uae30\ubcf4\ub97c select \ucffc\ub9ac\ub85c \uc870\ud68c\ud574\uc11c \uc0ac\uc6a9(1\ud68c) + insert \ucffc\ub9ac(\uc774\ub3d9 \ub2f9 1\ud68c)"]}),"\n",(0,s.jsx)(n.p,{children:"\ucd94\uac00\ub85c \uae30\ubcf4\uc800\uc7a5\uc774 \uad6c\ud604\ub3c4 \ub354\uc6b1 \uac04\ub2e8\ud558\ub2e4. \ud83d\udc4d"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"\ubd80\uac00\uc801\uc778 \ubd80\ubd84"})}),"\n",(0,s.jsx)(n.p,{children:"\ub9ac\ubdf0\uc5b4\uc778 \ucc30\ub9ac\ud83c\udf6b\uac00 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uac8c\uc784\uc774 \uc9c4\ud589\ub41c\ub2e4\uba74 \uc5b4\ub5a8\uc9c0? \uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ub2e4\uc591\ud55c \uc2dc\ub3c4\ub97c \ud574\ubd24\ub2e4."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\ub204\ub204\uc758 \ub3c4\uc6c0\uc73c\ub85c ConnectionPool \uad6c\ud604"}),"\n",(0,s.jsx)(n.li,{children:"ThreadLocal \uc0ac\uc6a9\ud574\uc11c \uc4f0\ub808\ub4dc \ubcc4 \uc138\uc158 \uad00\ub9ac"}),"\n",(0,s.jsx)(n.li,{children:"\uc2e4\uc81c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub0b4\uc5d0\uc11c \uccb4\uc2a4 \uac8c\uc784\uc774 \uc9c4\ud589\ub418\ub294 Board\ub97c ConcurrentHashMap\uc73c\ub85c \uc800\uc7a5(\uc0ac\uc2e4 \uc774 \ubd80\ubd84\uc740 \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ud544\uc694\uc5c6\uc9c0\ub9cc 2\uba85\uc774 \uc11c\ub85c \uac8c\uc784\ud558\ub294 \uacbd\uc6b0\ub97c \uc0dd\uac01\ud574\uc11c \ub123\uc5b4\ubcf4\uc558\ub2e4.)"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"\ub450 \uba85\uc774 \uc11c\ub85c \uac19\uc740 \ubc29\uc5d0 \uc785\uc7a5\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4\uba74 \ucd9c\ub825\ud558\ub294 \ubd80\ubd84\uc774 \uae4c\ub2e4\ub85c\uc6cc\uc9c8 \uac83 \uac19\ub2e4\uace0 \uc608\uc0c1\ub418\uc5b4(Board\uc5d0 \uc635\uc800\ubc84 \ud328\ud134\uc744 \uc0ac\uc6a9\ud574\uc57c\ub418\ub098?) \ud574\ubcfc \uc5c4\ub450\uac00 \ub098\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,s.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc9c0 \ubabb\ud55c \ubd80\ubd84"}),(0,s.jsx)(n.br,{}),"\n","DB \uad00\ub828 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0\ub9cc \uc9d1\uc911\ud558\ub2e4\ubcf4\ub2c8 \uc815\uc801 \uc911\uc694\ud55c DB\uc758 \ucf54\ub4dc\uc758 \uc608\uc678\ucc98\ub9ac, \ube48 \uac12\uc744 \ubc18\ud658 \ud558\ub294 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucc98\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ucc30\ub9ac\uc758 \uaf3c\uaf3c\ud55c \ub9ac\ubdf0\ub85c DB\ubd80\ubd84\uacfc \ub098\ub9cc\uc758 JdbcTemplate\uc744 \uae54\ub054\ud558\uac8c \uad6c\ud604\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ub2f4\uac10"}),(0,s.jsx)(n.br,{}),"\n","\ucd08\ubc18\uc5d0\ub294 \uc5ec\uc720\ub86d\uc9c0\ub9cc \uc81c\ucd9c \ub9c8\uac10\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \uc218\ub85d \uc0ac\ub78c\uc774 \uae09\ud574\uc9c0\ub294 \uac83 \uac19\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\ud560 \ub550 \uc18d\ub3c4\ub97c \uc870\uc808\ud558\uace0, \ub9c8\uc74c\uc5d0 \uc5ec\uc720\ub97c \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,s.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"DAO \uc911\ubcf5 \uc81c\uac70"})}),"\n",(0,s.jsxs)(n.p,{children:["\ud504\ub864\ub85c\uadf8\uc5d0 ",(0,s.jsx)(n.a,{href:"https://prolog.techcourse.co.kr/studylogs/2947",children:"\uae00"}),"\uc744 \uc791\uc131\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","DAO\ub97c \uc791\uc131\ud558\ub294\ub370 try-catch-resources\uc640 \uc5ec\ub7ec \ucf54\ub4dc\uac00 \uc911\ubcf5\ub418\uc11c \uc81c\uac70\ud558\uace0\uc2f6\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc73c\ub85c \uae54\ub054\ud558\uac8c \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\udc4d"]}),"\n",(0,s.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ud398\uc5b4 \uc0dd\uac01\ud558\uae30"}),(0,s.jsx)(n.br,{}),"\n","\uac00\ube44\ub294 \ub204\uad6c\ubcf4\ub2e4 \ud398\uc5b4\ub97c \uc0dd\uac01\ud558\uace0, \ubc30\ub824\ud574\uc8fc\ub294 \ud398\uc5b4\uc600\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ub2f9 \ub5a8\uc5b4\uc9c8\uae4c\ubd10 \uac71\uc815\ub3c4 \ud574\uc8fc\uace0, \ub098\uc758 \ucee8\ub514\uc158\ub3c4 \ud655\uc778\ud574\uc92c\ub2e4!"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ubbf8\uc158 \ubab0\uc785\ud558\uae30"}),(0,s.jsx)(n.br,{}),"\n","\ucd5c\uadfc\uc5d0 \ubbf8\uc158\uc5d0 \uc798 \ubab0\uc785\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uac00\ube44\ub294 \ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \ubbf8\uc158\uc5d0 \ub300\ud55c \ubab0\uc785\ub3c4\uac00 \ub9e4\uc6b0 \uc88b\uc558\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc9d1\uc5d0\uac00\uc11c\ub3c4 \uccb4\uc2a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ub85c\uc9c1\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560 \uc9c0 \uc0dd\uac01\ud55c \ub4a4 \uaf3c\uaf3c\ud574\uc11c \uc815\ub9ac\ud574\uc11c \ub098\uc5d0\uac8c \ubcf4\ub0b4\uc8fc\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub355\ubd84\uc5d0 \ub098\ub3c4 \uac00\ube44\uc758 \uc0dd\uac01\uc744 \uc54c \uc218 \uc788\uc5b4\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294\ub370 \uac00\uc18d\ub3c4\uac00 \ubd99\uc740 \uac83 \uac19\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub610\ud55c \ubbf8\uc158\uc744 \uc798 \ub9c8\ubb34\ub9ac\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\uc774 \uc804\ub2ec\ub418\uc11c \uadf8\ub7f0\uc9c0 \ub098\ub3c4 \ub369\ub2ec\uc544 \uc5f4\uc2ec\ud788 \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\ude04"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc194\uc9c1\ud568"}),(0,s.jsx)(n.br,{}),"\n","\uba3c\uc800 \ud68c\uace0\ud558\uc790\uace0 \ub9d0 \uac78\uc5b4\uc918\uc11c \uc815\ub9d0 \uace0\ub9c8\uc6e0\ub2e4\uace0 \ud45c\ud604\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\ubaa8\ub974\ub294\uac8c \uc788\uc73c\uba74 \uc194\uc9c1\ud558\uac8c \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\ub098\uc758 \uc758\uacac\uc744 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud55c \uc0c1\ud0dc\ub85c \uc804\ub2ec\ud560 \ub54c \uc774\ud574\uac00 \uc548\ub418\uc5c8\ub2e4\uace0 \uc815\ud655\ud788 \uc804\ub2ec\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\uc194\uc9c1\ud568\uc740 \ud398\uc5b4\ud560 \ub54c \uc911\uc694\ud55c \ubd80\ubd84\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,s.jsx)(n.p,{children:"\ub9c8\uc9c0\ub9c9\uc73c\ub85c \ucc30\ub9ac\ud83c\udf6b \uccb4\uc2a4 \ubbf8\uc158\ub54c \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0 \ub0a8\uaca8\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4!"})]})}function j(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var s=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function c(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);n&&(s=s.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,s)}return r}function i(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var o=s.createContext({}),a=function(e){var n=s.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},h={inlineCode:"code",wrapper:function(e){var n=e.children;return s.createElement(s.Fragment,{},n)}},j=s.forwardRef((function(e,n){var r=e.components,t=e.mdxType,c=e.originalType,o=e.parentName,j=l(e,["components","mdxType","originalType","parentName"]),x=a(r),p=t,d=x["".concat(o,".").concat(p)]||x[p]||h[p]||c;return r?s.createElement(d,i(i({ref:n},j),{},{components:r})):s.createElement(d,i({ref:n},j))}));j.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6276],{40469:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>j,frontMatter:()=>c,metadata:()=>l,toc:()=>a});var s=r(85893),t=r(3905);const c={title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",slug:"chess-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,l={permalink:"/chess-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",description:"1, 2\ub2e8\uacc4//github.com/woowacourse/java-chess/pull/441",date:"2023-03-31T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 31\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.705,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",slug:"chess-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",permalink:"/grasp"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",permalink:"/woowacourse-level1-retrospective"}},o={authorsImageUrls:[]},a=[{value:"\uccb4\uc2a4",id:"\uccb4\uc2a4",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function h(e){const n={a:"a",admonition:"admonition",br:"br",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.ah)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,s.jsxs)(n.p,{children:["1, 2\ub2e8\uacc4: ",(0,s.jsx)(n.a,{href:"https://github.com/woowacourse/java-chess/pull/441",children:"https://github.com/woowacourse/java-chess/pull/441"}),(0,s.jsx)(n.br,{}),"\n","3, 4\ub2e8\uacc4: ",(0,s.jsx)(n.a,{href:"https://github.com/woowacourse/java-chess/pull/529",children:"https://github.com/woowacourse/java-chess/pull/529"})]})}),"\n",(0,s.jsx)(n.h3,{id:"\uccb4\uc2a4",children:"\uccb4\uc2a4"}),"\n",(0,s.jsxs)(n.p,{children:["\uccb4\uc2a4 \ubbf8\uc158\uc5d0\ub294 \uac00\ube44\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4!",(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4\ub294 \uc774\uc804 \ubbf8\uc158\ub4e4\ubcf4\ub2e4 \ud6e8\uc52c \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778\uc774\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \uac00\ube44\uc640 \ub098\ub294 \uccb4\uc2a4 \ub3c4\uba54\uc778\uc774 \uc775\uc219\ud574\uc11c \ub354 \ud3b8\ud55c \ub9c8\uc74c\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc5b4\ub824\uc6e0\ub358 \ubd80\ubd84\uc740 \uae30\ubb3c\uc758 \uc774\ub3d9, \uc774\ub3d9\uc2dc \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:["\uac00\ube44\uac00 \uc9d1\uc5d0\uac00\uc11c\ub3c4 \uae30\ubb3c\uc758 \uc774\ub3d9 \uad00\ub828\ud574 \uc0dd\uac01 \uc815\ub9ac\ud55c \uae00\uc744 \ubcf4\ub0b4\uc918\uc11c \ub354\uc6b1 \ube68\ub9ac \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ucd5c\uc885\uc801\uc73c\ub85c \uacb0\uc815\ud55c \ubd80\ubd84\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5\uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","Rank\uc640 File\uc740 \uac01\uac01 \uc704\uce58\uac12\uc744 \uac00\uc9c0\uace0 \uc788\uace0, \uac12\uc758 \ucc28\uc774\ub97c \uc774\uc6a9\ud574\uc11c \uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uacc4\uc0b0\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc9c1\uc120 \u2192 Rank\uc640 File \ucc28\uc774 \uc911 \ud558\ub098\uac00 0\uc774\uc5b4\uc57c \ud55c\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub300\uac01\uc120 \u2192 Rank\uc640 File \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \uac19\uc544\uc57c \ud55c\ub2e4. ex) abs(-2) == abs(2)",(0,s.jsx)(n.br,{}),"\n","\ub098\uc774\ud2b8 \u2192 \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \ud558\ub098\ub294 2 \ub098\uba38\uc9c0 \ud558\ub098\ub294 1\uc774\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ub3c4\ucc29 \uce78\uc758 \uae30\ubb3c \uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","\uc544\uad70 \u2192 \uc774\ub3d9\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc801\uad70 \u2192 \uc774\ub3d9\uc774 \uac00\ub2a5\ud558\ub2e4. \uc801\uad70\uc744 \uc7a1\ub294\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc911\uac04\uc5d0 \uae30\ubb3c \uc874\uc7ac \uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","\uc774\ub3d9 \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\uba74 \uc548\ub41c\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9"}),(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4 \ubbf8\uc158\uc740 \ud2b9\ubcc4\ud558\uac8c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc5f0\uacb0\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4 \uac8c\uc784\uc758 \uc0c1\ud0dc\ub97c \ub2e4\uc74c\uc758 \ub450\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uc815\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95"}),"\n",(0,s.jsx)(n.li,{children:"\uae30\ubcf4\ub97c \uc800\uc7a5\ud558\uace0 \uac8c\uc784\uc744 \ubd88\ub7ec\uc640 \uae30\ubcf4\ub300\ub85c \uc774\ub3d9\uc2dc\ud0a4\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\uae30\ubb3c\uc774 \uc774\ub3d9\ud560 \ub54c\ub9c8\ub2e4 \uac12\uc744 \uc800\uc7a5\ud558\uace0 \uc2f6\uc5c8\uace0, \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc774\uc720\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\ud134\uacfc \uac19\uc740 \ubd80\uac00\uc801\uc778 \uc694\uc18c\ub97c \uc800\uc7a5\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,s.jsx)(n.li,{children:"\uc774\ub3d9\uc744 \ud560 \ub54c \uae30\ubb3c\uc774 \uc7a1\ud788\ub294 \uacbd\uc6b0 update \ucffc\ub9ac(\uc774\ub3d9 \uae30\ubb3c)\uc640 delete(\uc7a1\ud78c \uae30\ubb3c) 2\uac1c\uc758 \ucffc\ub9ac\ub97c \ub0a0\ub824\uc57c \ud55c\ub2e4."}),"\n",(0,s.jsx)(n.li,{children:"\ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ub3c4\uba54\uc778\uc758 \ubcc0\uacbd\uc774 \ud06c\uac8c(\ucd08\uae30 \uc0c1\ud0dc\ub97c \uad6c\uc131\ud558\ub294 \ubd80\ubd84) \uc77c\uc5b4\ub098\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\uc815\ub9ac\ud558\uc790\uba74 \uae30\ubb3c \uc804\uccb4 \uc800\uc7a5\uacfc \uae30\ubcf4 \uc800\uc7a5\uc740 \ub2e4\uc74c\uacfc \ucc28\uc774\uac00 \uc788\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ubcf4\ub4dc\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc\uc5d0\uc11c 32\uac1c\uc758 Insert \ucffc\ub9ac(\uae30\ubb3c\uc758 \uc704\uce58) + \uae30\ubb3c \uc774\ub3d9 \uc2dc \uc6c0\uc9c1\uc784 \ubcc0\uacbd(\uc7a1\ud788\ub294 \uacbd\uc6b0 2\uac1c\uc758 \ucffc\ub9ac)",(0,s.jsx)(n.br,{}),"\n","\uae30\ubcf4\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uad6c\uc131 + \uc800\uc7a5\ub41c \uae30\ubcf4\ub97c select \ucffc\ub9ac\ub85c \uc870\ud68c\ud574\uc11c \uc0ac\uc6a9(1\ud68c) + insert \ucffc\ub9ac(\uc774\ub3d9 \ub2f9 1\ud68c)"]}),"\n",(0,s.jsx)(n.p,{children:"\ucd94\uac00\ub85c \uae30\ubcf4\uc800\uc7a5\uc774 \uad6c\ud604\ub3c4 \ub354\uc6b1 \uac04\ub2e8\ud558\ub2e4. \ud83d\udc4d"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"\ubd80\uac00\uc801\uc778 \ubd80\ubd84"})}),"\n",(0,s.jsx)(n.p,{children:"\ub9ac\ubdf0\uc5b4\uc778 \ucc30\ub9ac\ud83c\udf6b\uac00 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uac8c\uc784\uc774 \uc9c4\ud589\ub41c\ub2e4\uba74 \uc5b4\ub5a8\uc9c0? \uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ub2e4\uc591\ud55c \uc2dc\ub3c4\ub97c \ud574\ubd24\ub2e4."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\ub204\ub204\uc758 \ub3c4\uc6c0\uc73c\ub85c ConnectionPool \uad6c\ud604"}),"\n",(0,s.jsx)(n.li,{children:"ThreadLocal \uc0ac\uc6a9\ud574\uc11c \uc4f0\ub808\ub4dc \ubcc4 \uc138\uc158 \uad00\ub9ac"}),"\n",(0,s.jsx)(n.li,{children:"\uc2e4\uc81c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub0b4\uc5d0\uc11c \uccb4\uc2a4 \uac8c\uc784\uc774 \uc9c4\ud589\ub418\ub294 Board\ub97c ConcurrentHashMap\uc73c\ub85c \uc800\uc7a5(\uc0ac\uc2e4 \uc774 \ubd80\ubd84\uc740 \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ud544\uc694\uc5c6\uc9c0\ub9cc 2\uba85\uc774 \uc11c\ub85c \uac8c\uc784\ud558\ub294 \uacbd\uc6b0\ub97c \uc0dd\uac01\ud574\uc11c \ub123\uc5b4\ubcf4\uc558\ub2e4.)"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"\ub450 \uba85\uc774 \uc11c\ub85c \uac19\uc740 \ubc29\uc5d0 \uc785\uc7a5\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4\uba74 \ucd9c\ub825\ud558\ub294 \ubd80\ubd84\uc774 \uae4c\ub2e4\ub85c\uc6cc\uc9c8 \uac83 \uac19\ub2e4\uace0 \uc608\uc0c1\ub418\uc5b4(Board\uc5d0 \uc635\uc800\ubc84 \ud328\ud134\uc744 \uc0ac\uc6a9\ud574\uc57c\ub418\ub098?) \ud574\ubcfc \uc5c4\ub450\uac00 \ub098\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,s.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc9c0 \ubabb\ud55c \ubd80\ubd84"}),(0,s.jsx)(n.br,{}),"\n","DB \uad00\ub828 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0\ub9cc \uc9d1\uc911\ud558\ub2e4\ubcf4\ub2c8 \uc815\uc801 \uc911\uc694\ud55c DB\uc758 \ucf54\ub4dc\uc758 \uc608\uc678\ucc98\ub9ac, \ube48 \uac12\uc744 \ubc18\ud658 \ud558\ub294 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucc98\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ucc30\ub9ac\uc758 \uaf3c\uaf3c\ud55c \ub9ac\ubdf0\ub85c DB\ubd80\ubd84\uacfc \ub098\ub9cc\uc758 JdbcTemplate\uc744 \uae54\ub054\ud558\uac8c \uad6c\ud604\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ub2f4\uac10"}),(0,s.jsx)(n.br,{}),"\n","\ucd08\ubc18\uc5d0\ub294 \uc5ec\uc720\ub86d\uc9c0\ub9cc \uc81c\ucd9c \ub9c8\uac10\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \uc218\ub85d \uc0ac\ub78c\uc774 \uae09\ud574\uc9c0\ub294 \uac83 \uac19\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\ud560 \ub550 \uc18d\ub3c4\ub97c \uc870\uc808\ud558\uace0, \ub9c8\uc74c\uc5d0 \uc5ec\uc720\ub97c \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,s.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"DAO \uc911\ubcf5 \uc81c\uac70"})}),"\n",(0,s.jsxs)(n.p,{children:["\ud504\ub864\ub85c\uadf8\uc5d0 ",(0,s.jsx)(n.a,{href:"https://prolog.techcourse.co.kr/studylogs/2947",children:"\uae00"}),"\uc744 \uc791\uc131\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","DAO\ub97c \uc791\uc131\ud558\ub294\ub370 try-catch-resources\uc640 \uc5ec\ub7ec \ucf54\ub4dc\uac00 \uc911\ubcf5\ub418\uc11c \uc81c\uac70\ud558\uace0\uc2f6\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc73c\ub85c \uae54\ub054\ud558\uac8c \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\udc4d"]}),"\n",(0,s.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ud398\uc5b4 \uc0dd\uac01\ud558\uae30"}),(0,s.jsx)(n.br,{}),"\n","\uac00\ube44\ub294 \ub204\uad6c\ubcf4\ub2e4 \ud398\uc5b4\ub97c \uc0dd\uac01\ud558\uace0, \ubc30\ub824\ud574\uc8fc\ub294 \ud398\uc5b4\uc600\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ub2f9 \ub5a8\uc5b4\uc9c8\uae4c\ubd10 \uac71\uc815\ub3c4 \ud574\uc8fc\uace0, \ub098\uc758 \ucee8\ub514\uc158\ub3c4 \ud655\uc778\ud574\uc92c\ub2e4!"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ubbf8\uc158 \ubab0\uc785\ud558\uae30"}),(0,s.jsx)(n.br,{}),"\n","\ucd5c\uadfc\uc5d0 \ubbf8\uc158\uc5d0 \uc798 \ubab0\uc785\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uac00\ube44\ub294 \ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \ubbf8\uc158\uc5d0 \ub300\ud55c \ubab0\uc785\ub3c4\uac00 \ub9e4\uc6b0 \uc88b\uc558\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc9d1\uc5d0\uac00\uc11c\ub3c4 \uccb4\uc2a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ub85c\uc9c1\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560 \uc9c0 \uc0dd\uac01\ud55c \ub4a4 \uaf3c\uaf3c\ud574\uc11c \uc815\ub9ac\ud574\uc11c \ub098\uc5d0\uac8c \ubcf4\ub0b4\uc8fc\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub355\ubd84\uc5d0 \ub098\ub3c4 \uac00\ube44\uc758 \uc0dd\uac01\uc744 \uc54c \uc218 \uc788\uc5b4\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294\ub370 \uac00\uc18d\ub3c4\uac00 \ubd99\uc740 \uac83 \uac19\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub610\ud55c \ubbf8\uc158\uc744 \uc798 \ub9c8\ubb34\ub9ac\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\uc774 \uc804\ub2ec\ub418\uc11c \uadf8\ub7f0\uc9c0 \ub098\ub3c4 \ub369\ub2ec\uc544 \uc5f4\uc2ec\ud788 \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\ude04"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc194\uc9c1\ud568"}),(0,s.jsx)(n.br,{}),"\n","\uba3c\uc800 \ud68c\uace0\ud558\uc790\uace0 \ub9d0 \uac78\uc5b4\uc918\uc11c \uc815\ub9d0 \uace0\ub9c8\uc6e0\ub2e4\uace0 \ud45c\ud604\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\ubaa8\ub974\ub294\uac8c \uc788\uc73c\uba74 \uc194\uc9c1\ud558\uac8c \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\ub098\uc758 \uc758\uacac\uc744 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud55c \uc0c1\ud0dc\ub85c \uc804\ub2ec\ud560 \ub54c \uc774\ud574\uac00 \uc548\ub418\uc5c8\ub2e4\uace0 \uc815\ud655\ud788 \uc804\ub2ec\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\uc194\uc9c1\ud568\uc740 \ud398\uc5b4\ud560 \ub54c \uc911\uc694\ud55c \ubd80\ubd84\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,s.jsx)(n.p,{children:"\ub9c8\uc9c0\ub9c9\uc73c\ub85c \ucc30\ub9ac\ud83c\udf6b \uccb4\uc2a4 \ubbf8\uc158\ub54c \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0 \ub0a8\uaca8\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4!"})]})}function j(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var s=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function c(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);n&&(s=s.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,s)}return r}function i(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var o=s.createContext({}),a=function(e){var n=s.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},h={inlineCode:"code",wrapper:function(e){var n=e.children;return s.createElement(s.Fragment,{},n)}},j=s.forwardRef((function(e,n){var r=e.components,t=e.mdxType,c=e.originalType,o=e.parentName,j=l(e,["components","mdxType","originalType","parentName"]),x=a(r),p=t,d=x["".concat(o,".").concat(p)]||x[p]||h[p]||c;return r?s.createElement(d,i(i({ref:n},j),{},{components:r})):s.createElement(d,i({ref:n},j))}));j.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/130df38c.c25a1b6d.js b/assets/js/130df38c.d6d4e2d6.js similarity index 98% rename from assets/js/130df38c.c25a1b6d.js rename to assets/js/130df38c.d6d4e2d6.js index 5c19f4cae..032f7aa4b 100644 --- a/assets/js/130df38c.c25a1b6d.js +++ b/assets/js/130df38c.d6d4e2d6.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6493],{83278:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>i,metadata:()=>l,toc:()=>d});var r=t(85893),c=t(3905);const i={title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"innodb-lock",tags:["DataBase","Lock","InnoDB"]},s=void 0,l={permalink:"/innodb-lock",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",source:"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",description:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",date:"2023-04-07T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 7\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Lock",permalink:"/tags/lock"},{label:"InnoDB",permalink:"/tags/inno-db"}],readingTime:5.805,hasTruncateMarker:!1,authors:[],frontMatter:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"innodb-lock",tags:["DataBase","Lock","InnoDB"]},unlisted:!1,prevItem:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",permalink:"/book-leadership-and-self-deception"},nextItem:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/mysql-lock"}},o={authorsImageUrls:[]},d=[{value:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",id:"innodb-\uc2a4\ud1a0\ub9ac\uc9c0-\uc5d4\uc9c4\uc758-\uc7a0\uae08",level:2},{value:"Shared & Exclusive Locks",id:"shared--exclusive-locks",level:3},{value:"Intention Locks",id:"intention-locks",level:3},{value:"Record Locks",id:"record-locks",level:3},{value:"Gap Locks",id:"gap-locks",level:3},{value:"Next-Key Locks",id:"next-key-locks",level:3},{value:"AUTO-INC Locks",id:"auto-inc-locks",level:3},{value:"\uc7a0\uae08 \uc608\uc2dc",id:"\uc7a0\uae08-\uc608\uc2dc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function a(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,c.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"innodb-\uc2a4\ud1a0\ub9ac\uc9c0-\uc5d4\uc9c4\uc758-\uc7a0\uae08",children:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08"}),"\n",(0,r.jsxs)(n.p,{children:["MySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08\uacfc \ubcc4\uac1c\ub85c \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub0b4\ubd80\uc5d0\uc11c \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubcf4\ud1b5 \uba85\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\ub294 \ub4dc\ubb3c\uace0, \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ubb35\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc774 \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub3d9\uc2dc\uc131 \uc81c\uc5b4 \ubc29\uc2dd\uc5d0\ub294 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uacfc \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc774 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB\ub294 \uae30\ubcf8\uc801\uc73c\ub85c MVCC(\ub2e4\uc911 \ubc84\uc804 \ub3d9\uc2dc\uc131 \uc81c\uc5b4)\ub97c \ud1b5\ud574 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uace0 \ub77d\uc744 \ud1b5\ud574 \ud2b9\uc815 \uc0c1\ud669\uc5d0\uc11c \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.admonition,{title:"\ub099\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(OCC, Optimistic concurrency control)",type:"note",children:(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \uc11c\ub85c \ucda9\ub3cc\ud558\uc9c0 \uc54a\ub294\ub2e4\uace0 \uac00\uc815\ud558\ub294 \ubc29\uc2dd"})}),"\n",(0,r.jsx)(n.admonition,{title:"\ube44\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(PCC, Pessimistic Concurrency Control)",type:"note",children:(0,r.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc774 \ucda9\ub3cc\ud558\ub294 \uac00\uc815\ud558\uc5d0 \uc7a0\uae08\uc744 \uac70\ub294 \ubc29\uc2dd",(0,r.jsx)(n.br,{}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c\xa0Shared Lock, Exclusive Lock\uc744 \ud1b5\ud574 \uc774\ub97c \uad6c\ud604\ud55c\ub2e4."]})}),"\n",(0,r.jsx)(n.h3,{id:"shared--exclusive-locks",children:"Shared & Exclusive Locks"}),"\n",(0,r.jsx)(n.p,{children:"InnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc218\ud589\ud560 \ub54c \uacf5\uc720 \uc7a0\uae08\uacfc \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uacf5\uc720 \uc7a0\uae08(S, shared lock)"})}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130 \uc870\ud68c\ub97c \uc704\ud55c \ub77d, \uc77d\uae30 \uc7a0\uae08(read lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uae30\uac00 \uac00\ub2a5\ud558\uc9c0\ub9cc, \uc4f0\uae30\ub294 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608) ",(0,r.jsx)(n.code,{children:"SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;"})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\ubc30\ud0c0\uc801 \uc7a0\uae08(X, exclusive lock)"})}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130 \ubcc0\uacbd\uc744 \uc704\ud55c \ub77d, \uc4f0\uae30 \uc7a0\uae08(write lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub77d\uc744 \uac74 \ud2b8\ub79c\uc7ad\uc158\ub9cc\uc774 \ud574\ub2f9 \ub370\uc774\ud130\uc5d0 \uc811\uadfc \uac00\ub2a5\ud558\ub2e4. \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \uc77d\uae30, \uc4f0\uae30\uac00 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608) ",(0,r.jsx)(n.code,{children:"SELECT * FROM table_name WHERE id = 1 FOR UPDATE;"})]}),"\n",(0,r.jsx)(n.h3,{id:"intention-locks",children:"Intention Locks"}),"\n",(0,r.jsxs)(n.p,{children:["InnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uacfc \ud14c\uc774\ube14 \uc7a0\uae08\uc758 \uacf5\uc874\uc744 \uc704\ud574 \uc778\ud14d\uc158 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ub85c\uc6b0\uc5d0 \ub300\ud574\uc11c \ub098\uc911\uc5d0 \uc694\uccad\ub418\ub294 \uac83\uc774 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uc7a0\uae08\uc778\uc9c0 \uac00\ub9ac\ud0a4\uae30 \uc704\ud574 \uc0ac\uc6a9\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 \uc778\ud150\uc158 \uc7a0\uae08\uc744 \uba3c\uc800 \ud68d\ub4dd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc778\ud150\uc158 \ub77d\uc740 \uae30\ubcf8\uc801\uc73c\ub85c \ucda9\ub3cc\uc744 \ubc29\uc9c0\ud558\uace0 \ub370\ub4dc\ub77d\uc744 \ubc29\uc9c0\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uc778\ud150\uc158 \uacf5\uc720 \uc7a0\uae08(IS, intention shared lock)"})}),"\n",(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \uacf5\uc720 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uc778\ud150\uc158 \ubc30\ud0c0\uc801 \uc7a0\uae08(IX, intention exclusive lock)"})}),"\n",(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:"** \uc7a0\uae08\uac04\uc758 \ud638\ud658\uc131 **"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{}),(0,r.jsx)(n.th,{children:"X"}),(0,r.jsx)(n.th,{children:"IX"}),(0,r.jsx)(n.th,{children:"S"}),(0,r.jsx)(n.th,{children:"IS"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"X"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"IX"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"S"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"IS"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"record-locks",children:"Record Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc \uc790\uccb4\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc740 \ub808\ucf54\ub4dc \uc790\uccb4\uac00 \uc544\ub2c8\ub77c \uc778\ub371\uc2a4\uc758 \ub808\ucf54\ub4dc\ub97c \uc7a0\uadfc\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"gap-locks",children:"Gap Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub808\ucf54\ub4dc\uc640 \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\uc5d0 \uc0c8\ub85c\uc6b4 \ub808\ucf54\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \uc81c\uc5b4\ud558\uace0, \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc758 \uc77c\ubd80\ub85c \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"next-key-locks",children:"Next-Key Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ud32c\ud140 \ub9ac\ub4dc\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uc7a0\uae08\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"auto-inc-locks",children:"AUTO-INC Locks"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"AUTO_INCREMENT"})," \uce7c\ub9bc\uc774 \uc0ac\uc6a9\ub41c \ud14c\uc774\ube14\uc5d0 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \ub808\ucf54\ub4dc\uac00 ",(0,r.jsx)(n.code,{children:"INSERT"}),"\ub418\ub294 \uacbd\uc6b0, \uac01 \ub808\ucf54\ub4dc\ub294 \uc911\ubcf5\ub418\uc9c0 \uc54a\uace0 \uc800\uc7a5\ub41c \uc21c\uc11c\ub300\ub85c \uc99d\uac00\ud558\ub294 \uc77c\ub828\ubc88\ud638 \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB \ub294 \ub0b4\ubd80\uc801\uc73c\ub85c AUTO-INC \ub77d\uc774\ub77c\uace0 \ud558\ub294 \ud14c\uc774\ube14 \uc218\uc900\uc758 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uacfc \uad00\uacc4 \uc5c6\uc774 ",(0,r.jsx)(n.code,{children:"INSERT"}),"\ub098 ",(0,r.jsx)(n.code,{children:"REPLACE"})," \ubb38\uc7a5\uc5d0\uc11c ",(0,r.jsx)(n.code,{children:"AUTO_INCREMENT"})," \uac12\uc744 \uac00\uc838\uc624\ub294 \uc21c\uac04\ub9cc \ub77d\uc774 \uac78\ub838\ub2e4\uac00 \ud574\uc81c\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc7a0\uae08-\uc608\uc2dc",children:"\uc7a0\uae08 \uc608\uc2dc"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-sql",children:"-- \ub808\ucf54\ub4dc\ub294 id \uae30\uc900 10, 20, 30, 40, 50\uc774 \uc788\ub2e4\uace0 \uac00\uc815\n-- Record Locks: 10\uc5d0 \ub300\ud574 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id = 10 for update;\n\n-- Gap Locks: 51\ubd80\ud130 PositiveInfinity\uae4c\uc9c0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id > 100 for update;\n\n-- Next-Key Locks: 21\ubd80\ud130 30, 31\ubd80\ud130 40\uc5d0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id BETWEEN 25 AND 35 for update;\n"})}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.ibm.com/docs/en/rational-clearquest/9.0.0?topic=clearquest-optimistic-pessimistic-record-locking",children:"Optimistic and Pessimistic record locking, IBM"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://cecil1018.wordpress.com/2016/06/18/mysql-innodb-locks/",children:"MySQL Innodb Locks, cecil1018"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html",children:"MySQL 8.0 InnoDB Locks, MySQL"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html",children:"Locks Set by Different SQL Statements in InnoDB, MySQL"})]})]})}function h(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var r=t(67294);function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(c[t]=e[t]);return c}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(c[t]=e[t])}return c}var o=r.createContext({}),d=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},a={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},h=r.forwardRef((function(e,n){var t=e.components,c=e.mdxType,i=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),x=d(t),j=c,p=x["".concat(o,".").concat(j)]||x[j]||a[j]||i;return t?r.createElement(p,s(s({ref:n},h),{},{components:t})):r.createElement(p,s({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6493],{83278:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>i,metadata:()=>l,toc:()=>d});var r=t(85893),c=t(3905);const i={title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"innodb-lock",tags:["DataBase","Lock","InnoDB"]},s=void 0,l={permalink:"/innodb-lock",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",source:"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",description:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",date:"2023-04-07T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 7\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Lock",permalink:"/tags/lock"},{label:"InnoDB",permalink:"/tags/inno-db"}],readingTime:5.805,hasTruncateMarker:!1,authors:[],frontMatter:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"innodb-lock",tags:["DataBase","Lock","InnoDB"]},unlisted:!1,prevItem:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/mysql-lock"},nextItem:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",permalink:"/book-leadership-and-self-deception"}},o={authorsImageUrls:[]},d=[{value:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",id:"innodb-\uc2a4\ud1a0\ub9ac\uc9c0-\uc5d4\uc9c4\uc758-\uc7a0\uae08",level:2},{value:"Shared & Exclusive Locks",id:"shared--exclusive-locks",level:3},{value:"Intention Locks",id:"intention-locks",level:3},{value:"Record Locks",id:"record-locks",level:3},{value:"Gap Locks",id:"gap-locks",level:3},{value:"Next-Key Locks",id:"next-key-locks",level:3},{value:"AUTO-INC Locks",id:"auto-inc-locks",level:3},{value:"\uc7a0\uae08 \uc608\uc2dc",id:"\uc7a0\uae08-\uc608\uc2dc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function a(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,c.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"innodb-\uc2a4\ud1a0\ub9ac\uc9c0-\uc5d4\uc9c4\uc758-\uc7a0\uae08",children:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08"}),"\n",(0,r.jsxs)(n.p,{children:["MySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08\uacfc \ubcc4\uac1c\ub85c \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub0b4\ubd80\uc5d0\uc11c \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubcf4\ud1b5 \uba85\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\ub294 \ub4dc\ubb3c\uace0, \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ubb35\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc774 \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub3d9\uc2dc\uc131 \uc81c\uc5b4 \ubc29\uc2dd\uc5d0\ub294 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uacfc \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc774 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB\ub294 \uae30\ubcf8\uc801\uc73c\ub85c MVCC(\ub2e4\uc911 \ubc84\uc804 \ub3d9\uc2dc\uc131 \uc81c\uc5b4)\ub97c \ud1b5\ud574 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uace0 \ub77d\uc744 \ud1b5\ud574 \ud2b9\uc815 \uc0c1\ud669\uc5d0\uc11c \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.admonition,{title:"\ub099\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(OCC, Optimistic concurrency control)",type:"note",children:(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \uc11c\ub85c \ucda9\ub3cc\ud558\uc9c0 \uc54a\ub294\ub2e4\uace0 \uac00\uc815\ud558\ub294 \ubc29\uc2dd"})}),"\n",(0,r.jsx)(n.admonition,{title:"\ube44\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(PCC, Pessimistic Concurrency Control)",type:"note",children:(0,r.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc774 \ucda9\ub3cc\ud558\ub294 \uac00\uc815\ud558\uc5d0 \uc7a0\uae08\uc744 \uac70\ub294 \ubc29\uc2dd",(0,r.jsx)(n.br,{}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c\xa0Shared Lock, Exclusive Lock\uc744 \ud1b5\ud574 \uc774\ub97c \uad6c\ud604\ud55c\ub2e4."]})}),"\n",(0,r.jsx)(n.h3,{id:"shared--exclusive-locks",children:"Shared & Exclusive Locks"}),"\n",(0,r.jsx)(n.p,{children:"InnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc218\ud589\ud560 \ub54c \uacf5\uc720 \uc7a0\uae08\uacfc \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uacf5\uc720 \uc7a0\uae08(S, shared lock)"})}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130 \uc870\ud68c\ub97c \uc704\ud55c \ub77d, \uc77d\uae30 \uc7a0\uae08(read lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uae30\uac00 \uac00\ub2a5\ud558\uc9c0\ub9cc, \uc4f0\uae30\ub294 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608) ",(0,r.jsx)(n.code,{children:"SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;"})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\ubc30\ud0c0\uc801 \uc7a0\uae08(X, exclusive lock)"})}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130 \ubcc0\uacbd\uc744 \uc704\ud55c \ub77d, \uc4f0\uae30 \uc7a0\uae08(write lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub77d\uc744 \uac74 \ud2b8\ub79c\uc7ad\uc158\ub9cc\uc774 \ud574\ub2f9 \ub370\uc774\ud130\uc5d0 \uc811\uadfc \uac00\ub2a5\ud558\ub2e4. \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \uc77d\uae30, \uc4f0\uae30\uac00 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608) ",(0,r.jsx)(n.code,{children:"SELECT * FROM table_name WHERE id = 1 FOR UPDATE;"})]}),"\n",(0,r.jsx)(n.h3,{id:"intention-locks",children:"Intention Locks"}),"\n",(0,r.jsxs)(n.p,{children:["InnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uacfc \ud14c\uc774\ube14 \uc7a0\uae08\uc758 \uacf5\uc874\uc744 \uc704\ud574 \uc778\ud14d\uc158 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ub85c\uc6b0\uc5d0 \ub300\ud574\uc11c \ub098\uc911\uc5d0 \uc694\uccad\ub418\ub294 \uac83\uc774 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uc7a0\uae08\uc778\uc9c0 \uac00\ub9ac\ud0a4\uae30 \uc704\ud574 \uc0ac\uc6a9\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 \uc778\ud150\uc158 \uc7a0\uae08\uc744 \uba3c\uc800 \ud68d\ub4dd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc778\ud150\uc158 \ub77d\uc740 \uae30\ubcf8\uc801\uc73c\ub85c \ucda9\ub3cc\uc744 \ubc29\uc9c0\ud558\uace0 \ub370\ub4dc\ub77d\uc744 \ubc29\uc9c0\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uc778\ud150\uc158 \uacf5\uc720 \uc7a0\uae08(IS, intention shared lock)"})}),"\n",(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \uacf5\uc720 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uc778\ud150\uc158 \ubc30\ud0c0\uc801 \uc7a0\uae08(IX, intention exclusive lock)"})}),"\n",(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:"** \uc7a0\uae08\uac04\uc758 \ud638\ud658\uc131 **"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{}),(0,r.jsx)(n.th,{children:"X"}),(0,r.jsx)(n.th,{children:"IX"}),(0,r.jsx)(n.th,{children:"S"}),(0,r.jsx)(n.th,{children:"IS"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"X"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"IX"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"S"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"IS"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"record-locks",children:"Record Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc \uc790\uccb4\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc740 \ub808\ucf54\ub4dc \uc790\uccb4\uac00 \uc544\ub2c8\ub77c \uc778\ub371\uc2a4\uc758 \ub808\ucf54\ub4dc\ub97c \uc7a0\uadfc\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"gap-locks",children:"Gap Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub808\ucf54\ub4dc\uc640 \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\uc5d0 \uc0c8\ub85c\uc6b4 \ub808\ucf54\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \uc81c\uc5b4\ud558\uace0, \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc758 \uc77c\ubd80\ub85c \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"next-key-locks",children:"Next-Key Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ud32c\ud140 \ub9ac\ub4dc\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uc7a0\uae08\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"auto-inc-locks",children:"AUTO-INC Locks"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"AUTO_INCREMENT"})," \uce7c\ub9bc\uc774 \uc0ac\uc6a9\ub41c \ud14c\uc774\ube14\uc5d0 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \ub808\ucf54\ub4dc\uac00 ",(0,r.jsx)(n.code,{children:"INSERT"}),"\ub418\ub294 \uacbd\uc6b0, \uac01 \ub808\ucf54\ub4dc\ub294 \uc911\ubcf5\ub418\uc9c0 \uc54a\uace0 \uc800\uc7a5\ub41c \uc21c\uc11c\ub300\ub85c \uc99d\uac00\ud558\ub294 \uc77c\ub828\ubc88\ud638 \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB \ub294 \ub0b4\ubd80\uc801\uc73c\ub85c AUTO-INC \ub77d\uc774\ub77c\uace0 \ud558\ub294 \ud14c\uc774\ube14 \uc218\uc900\uc758 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uacfc \uad00\uacc4 \uc5c6\uc774 ",(0,r.jsx)(n.code,{children:"INSERT"}),"\ub098 ",(0,r.jsx)(n.code,{children:"REPLACE"})," \ubb38\uc7a5\uc5d0\uc11c ",(0,r.jsx)(n.code,{children:"AUTO_INCREMENT"})," \uac12\uc744 \uac00\uc838\uc624\ub294 \uc21c\uac04\ub9cc \ub77d\uc774 \uac78\ub838\ub2e4\uac00 \ud574\uc81c\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc7a0\uae08-\uc608\uc2dc",children:"\uc7a0\uae08 \uc608\uc2dc"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-sql",children:"-- \ub808\ucf54\ub4dc\ub294 id \uae30\uc900 10, 20, 30, 40, 50\uc774 \uc788\ub2e4\uace0 \uac00\uc815\n-- Record Locks: 10\uc5d0 \ub300\ud574 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id = 10 for update;\n\n-- Gap Locks: 51\ubd80\ud130 PositiveInfinity\uae4c\uc9c0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id > 100 for update;\n\n-- Next-Key Locks: 21\ubd80\ud130 30, 31\ubd80\ud130 40\uc5d0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id BETWEEN 25 AND 35 for update;\n"})}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.ibm.com/docs/en/rational-clearquest/9.0.0?topic=clearquest-optimistic-pessimistic-record-locking",children:"Optimistic and Pessimistic record locking, IBM"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://cecil1018.wordpress.com/2016/06/18/mysql-innodb-locks/",children:"MySQL Innodb Locks, cecil1018"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html",children:"MySQL 8.0 InnoDB Locks, MySQL"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html",children:"Locks Set by Different SQL Statements in InnoDB, MySQL"})]})]})}function h(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var r=t(67294);function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(c[t]=e[t]);return c}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(c[t]=e[t])}return c}var o=r.createContext({}),d=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},a={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},h=r.forwardRef((function(e,n){var t=e.components,c=e.mdxType,i=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),x=d(t),j=c,p=x["".concat(o,".").concat(j)]||x[j]||a[j]||i;return t?r.createElement(p,s(s({ref:n},h),{},{components:t})):r.createElement(p,s({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/14dc1923.1aa6fe97.js b/assets/js/14dc1923.1659bee8.js similarity index 94% rename from assets/js/14dc1923.1aa6fe97.js rename to assets/js/14dc1923.1659bee8.js index fe625f2ba..debb04d4b 100644 --- a/assets/js/14dc1923.1aa6fe97.js +++ b/assets/js/14dc1923.1659bee8.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7403],{40742:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var r=n(85893),i=n(3905);const l={title:"IntelliJ \uc124\uc815",slug:"intellij-settings",tags:["IntelliJ"]},a=void 0,o={permalink:"/intellij-settings",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",source:"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",title:"IntelliJ \uc124\uc815",description:"Import \uc790\ub3d9 \uc801\uc6a9",date:"2023-01-30T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 30\uc77c",tags:[{label:"IntelliJ",permalink:"/tags/intelli-j"}],readingTime:.465,hasTruncateMarker:!1,authors:[],frontMatter:{title:"IntelliJ \uc124\uc815",slug:"intellij-settings",tags:["IntelliJ"]},unlisted:!1,prevItem:{title:"Parameterized Tests",permalink:"/parameterized-tests"},nextItem:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",permalink:"/kotlin-null"}},s={authorsImageUrls:[]},c=[{value:"Import \uc790\ub3d9 \uc801\uc6a9",id:"import-\uc790\ub3d9-\uc801\uc6a9",level:3},{value:"\uc800\uc7a5\uc2dc \ub3d9\uc791",id:"\uc800\uc7a5\uc2dc-\ub3d9\uc791",level:3},{value:"\uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9",id:"\uba54\uc18c\ub4dc-\ucd94\ucd9c-\ubcc0\uc218-\ucd94\ucd9c\uc2dc-final-\uc801\uc6a9",level:3}];function p(e){const t={h3:"h3",img:"img",p:"p",...(0,i.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"import-\uc790\ub3d9-\uc801\uc6a9",children:"Import \uc790\ub3d9 \uc801\uc6a9"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"auto-import",src:n(41394).Z+"",width:"2558",height:"1656"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc800\uc7a5\uc2dc-\ub3d9\uc791",children:"\uc800\uc7a5\uc2dc \ub3d9\uc791"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Tools > Actions on Save"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"actions-on-save",src:n(24927).Z+"",width:"2558",height:"1656"})}),"\n",(0,r.jsx)(t.p,{children:"Reformat Code: Code Reformmating"}),"\n",(0,r.jsx)(t.p,{children:"Optimize imports: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 Import \uc81c\uac70"}),"\n",(0,r.jsx)(t.p,{children:"Rearrange: Code Style > Arrangement \uc124\uc815 \uae30\ubc18 \ucf54\ub4dc \uc7ac\uc815\ub82c"}),"\n",(0,r.jsx)(t.h3,{id:"\uba54\uc18c\ub4dc-\ucd94\ucd9c-\ubcc0\uc218-\ucd94\ucd9c\uc2dc-final-\uc801\uc6a9",children:"\uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"final-modifier",src:n(21796).Z+"",width:"2558",height:"1656"})})]})}function d(e={}){const{wrapper:t}={...(0,i.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,l=e.originalType,s=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),m=c(n),u=i,f=m["".concat(s,".").concat(u)]||m[u]||p[u]||l;return n?r.createElement(f,a(a({ref:t},d),{},{components:n})):r.createElement(f,a({ref:t},d))}));d.displayName="MDXCreateElement"},24927:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/actions-on-save-6c1203027c28ff08919e045812c7d456.png"},41394:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/auto-import-3dbe46f0109af17296039d52d498225e.png"},21796:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/final-modifier-1dd2aea35979423a30869a7b0ebe501a.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7403],{40742:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var r=n(85893),i=n(3905);const l={title:"IntelliJ \uc124\uc815",slug:"intellij-settings",tags:["IntelliJ"]},a=void 0,o={permalink:"/intellij-settings",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",source:"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",title:"IntelliJ \uc124\uc815",description:"Import \uc790\ub3d9 \uc801\uc6a9",date:"2023-01-30T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 30\uc77c",tags:[{label:"IntelliJ",permalink:"/tags/intelli-j"}],readingTime:.465,hasTruncateMarker:!1,authors:[],frontMatter:{title:"IntelliJ \uc124\uc815",slug:"intellij-settings",tags:["IntelliJ"]},unlisted:!1,prevItem:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",permalink:"/kotlin-null"},nextItem:{title:"Parameterized Tests",permalink:"/parameterized-tests"}},s={authorsImageUrls:[]},c=[{value:"Import \uc790\ub3d9 \uc801\uc6a9",id:"import-\uc790\ub3d9-\uc801\uc6a9",level:3},{value:"\uc800\uc7a5\uc2dc \ub3d9\uc791",id:"\uc800\uc7a5\uc2dc-\ub3d9\uc791",level:3},{value:"\uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9",id:"\uba54\uc18c\ub4dc-\ucd94\ucd9c-\ubcc0\uc218-\ucd94\ucd9c\uc2dc-final-\uc801\uc6a9",level:3}];function p(e){const t={h3:"h3",img:"img",p:"p",...(0,i.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"import-\uc790\ub3d9-\uc801\uc6a9",children:"Import \uc790\ub3d9 \uc801\uc6a9"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"auto-import",src:n(41394).Z+"",width:"2558",height:"1656"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc800\uc7a5\uc2dc-\ub3d9\uc791",children:"\uc800\uc7a5\uc2dc \ub3d9\uc791"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Tools > Actions on Save"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"actions-on-save",src:n(24927).Z+"",width:"2558",height:"1656"})}),"\n",(0,r.jsx)(t.p,{children:"Reformat Code: Code Reformmating"}),"\n",(0,r.jsx)(t.p,{children:"Optimize imports: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 Import \uc81c\uac70"}),"\n",(0,r.jsx)(t.p,{children:"Rearrange: Code Style > Arrangement \uc124\uc815 \uae30\ubc18 \ucf54\ub4dc \uc7ac\uc815\ub82c"}),"\n",(0,r.jsx)(t.h3,{id:"\uba54\uc18c\ub4dc-\ucd94\ucd9c-\ubcc0\uc218-\ucd94\ucd9c\uc2dc-final-\uc801\uc6a9",children:"\uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"final-modifier",src:n(21796).Z+"",width:"2558",height:"1656"})})]})}function d(e={}){const{wrapper:t}={...(0,i.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,l=e.originalType,s=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),m=c(n),u=i,f=m["".concat(s,".").concat(u)]||m[u]||p[u]||l;return n?r.createElement(f,a(a({ref:t},d),{},{components:n})):r.createElement(f,a({ref:t},d))}));d.displayName="MDXCreateElement"},24927:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/actions-on-save-6c1203027c28ff08919e045812c7d456.png"},41394:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/auto-import-3dbe46f0109af17296039d52d498225e.png"},21796:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/final-modifier-1dd2aea35979423a30869a7b0ebe501a.png"}}]); \ No newline at end of file diff --git a/assets/js/1664646a.eba2ca7c.js b/assets/js/1664646a.965e02af.js similarity index 98% rename from assets/js/1664646a.eba2ca7c.js rename to assets/js/1664646a.965e02af.js index 069eaa5c8..a3383c414 100644 --- a/assets/js/1664646a.eba2ca7c.js +++ b/assets/js/1664646a.965e02af.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8036],{60367:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>a,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=n(85893),i=n(3905);const l={title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",slug:"web-application-evolution",tags:["web application"]},o=void 0,s={permalink:"/web-application-evolution",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",source:"@site/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",description:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",date:"2023-09-30T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 30\uc77c",tags:[{label:"web application",permalink:"/tags/web-application"}],readingTime:7.5,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",slug:"web-application-evolution",tags:["web application"]},unlisted:!1,prevItem:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",permalink:"/spring-test-isolation"},nextItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"}},a={authorsImageUrls:[]},c=[{value:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",level:3},{value:"WWW(1989)",id:"www1989",level:3},{value:"CGI(1993)",id:"cgi1993",level:3},{value:"Servlet(1996)",id:"servlet1996",level:3},{value:"JSP(1999)",id:"jsp1999",level:3},{value:"MVC(2000)",id:"mvc2000",level:3},{value:"Spring Framework(2003)",id:"spring-framework2003",level:3},{value:"WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)",id:"webflux-\uc774\uc804-servlet-302009-312013",level:3},{value:"Spring WebFlux(2017)",id:"spring-webflux2017",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const r={a:"a",blockquote:"blockquote",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",...(0,i.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h3,{id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",children:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815"}),"\n",(0,t.jsxs)(r.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6d0\ub798 \ud68c\uace0\uc5d0 \uc791\uc131\ud558\ub824\uace0 \ud588\uc9c0\ub9cc, \uc815\ub9ac\ud558\ub2e4 \ubcf4\ub2c8 \uc870\uae08 \uae38\uc5b4\uc838\uc11c \ub530\ub85c \ubd84\ub9ac\ud588\ub2e4."]}),"\n",(0,t.jsx)(r.mermaid,{value:"graph LR\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking"}),"\n",(0,t.jsx)(r.h3,{id:"www1989",children:"WWW(1989)"}),"\n",(0,t.jsx)(r.p,{children:"\uc815\uc801 \ud398\uc774\uc9c0\ub97c \uc81c\uacf5\ud558\ub294 \uc6f9 \uc11c\ubc84\ub97c \uc2dc\uc791\uc73c\ub85c \ub3d9\uc801 \ud398\uc774\uc9c0\uac00 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 CGI\uac00 \ub4f1\uc7a5\ud588\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"cgi1993",children:"CGI(1993)"}),"\n",(0,t.jsx)(r.p,{children:"CGI\ub294 \ub3d9\uc801 \ucf58\ud150\uce20\ub97c \uc81c\uacf5\ud558\uae30 \uc704\ud55c \uaddc\uc57d\uc73c\ub85c, \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc774\uc6a9\ud574\uc11c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ucf1c \uc815\ubcf4\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ub9ce\uc740 \ubd80\ud558\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc774\ub7ec\ud55c \ub2e8\uc810\uc744 \uadf9\ubcf5\ud558\uae30 \uc704\ud574 \ub098\uc628 \uac83\uc774 Servlet\uc774\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"servlet1996",children:"Servlet(1996)"}),"\n",(0,t.jsxs)(r.p,{children:["Servlet\uc740 \uc6f9 \uc11c\ubc84\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uc790\ubc14 \ud504\ub85c\uadf8\ub7a8\uc73c\ub85c HTTP\ub97c \uc774\uc6a9\ud558\uc5ec \uc6f9 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc744 \uc218\uc2e0\ud558\uace0 \uc751\ub2f5\ud55c\ub2e4. CGI\uc640 \ub2e4\ub974\uac8c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\uac00 \uc544\ub2cc \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uc5ec \uc751\ub2f5\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc View \uc601\uc5ed\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uae30 \uc704\ud574 Servlet\uc758 \uc18c\uc2a4 \ucf54\ub4dc\ub97c \uc54c\uc544\uc57c \ud558\ub294 \ub4f1 \ubcf5\uc7a1\ub3c4\uac00 \ub108\ubb34 \ub192\uc558\ub2e4. \ub530\ub77c\uc11c \ud574\ub2f9 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 JSP\uac00 \ub4f1\uc7a5\ud588\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"jsp1999",children:"JSP(1999)"}),"\n",(0,t.jsxs)(r.p,{children:["JSP\ub294 HTML\uc5d0 \uc790\ubc14 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ub3d9\uc801 \uc6f9 \ud398\uc774\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\uc220\ub85c, \uc720\uc0ac\ud55c \uae30\uc220\ub85c\ub294 ASP, PHP\uac00 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","JSP\ub9cc \uc0ac\uc6a9\ud558\uc5ec \ud504\ub85c\uadf8\ub798\ubc0d\ud55c\ub2e4\uba74 Model 1, \uc544\ub798 \uad6c\uc131\ub3c4\uc640 \uac19\uc774 JSP\uac00 View \uc601\uc5ed\ub9cc \ub2f4\ub2f9\ud55c\ub2e4\uba74 Model 2\ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.mermaid,{value:"---\ntitle: JSP Model 2\n---\ngraph LR\n Client -- Request --\x3e Servlet <-- JDBC --\x3e Database\n\tServlet --\x3e Bean\n\tServlet --\x3e JSP\n\tBean <--\x3e JSP\n\tJSP -- Response --\x3e Client"}),"\n",(0,t.jsx)(r.h3,{id:"mvc2000",children:"MVC(2000)"}),"\n",(0,t.jsx)(r.p,{children:"\uc704 JSP\uc758 \uad6c\uc131\ub3c4\ub97c \ubcf4\uba74 \ud604\uc7ac MVC\uc640 \ub9e4\uc6b0 \uc720\uc0ac\ud55c\ub370, Govind Seshadri\ub77c\ub294 \uc0ac\ub78c\uc774 JSP Model 2\ub97c MVC \ud328\ud134\uc73c\ub85c \uacf5\uc2dd\ud654\ub97c \uc81c\uc548\ud588\ub2e4."}),"\n",(0,t.jsxs)(r.blockquote,{children:["\n",(0,t.jsxs)(r.p,{children:["I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern.",(0,t.jsx)(r.br,{}),"\n","Govind Seshadri"]}),"\n"]}),"\n",(0,t.jsxs)(r.p,{children:["\uc774\ub54c MVC \ud328\ud134\uc774 \ucc98\uc74c \ud0c4\uc0dd\ud55c \uac83\uc740 \uc544\ub2c8\uace0, \uc11c\ubc84 \uce21 \uad6c\ud604\uc774\ub77c\uace0 \ud558\ub294 \uac83\uc744 \ubcf4\ub2c8 MVC\uac00 \ucc98\uc74c \ub4f1\uc7a5\ud55c \uac74 \uc544\ub2cc \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html",children:"\ud574\ub2f9 \ubb38\uc11c"}),"\ub97c \ubcf4\uba74 MVC\ub77c\ub294 \uc6a9\uc5b4\uc758 \ub4f1\uc7a5\uc740 1978\ub144\uc5d0 \ub4f1\uc7a5\ud55c \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"spring-framework2003",children:"Spring Framework(2003)"}),"\n",(0,t.jsxs)(r.p,{children:["Spring\uc740 \ubcf5\uc7a1\ud588\ub358 J2EE\uc744 \ub300\uccb4\ud558\uae30 \uc704\ud574 2003\ub144\uc5d0 \ub4f1\uc7a5\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","J2EE\ub294 \uc6f9 \uae30\ubc18\uc758 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\uae30 \uc704\ud55c \ud50c\ub7ab\ud3fc\uc73c\ub85c \uc704\uc5d0\uc11c \uc124\uba85\ud55c Servlet, JSP, EJB \ub4f1\uc758 \uae30\uc220\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \uc774\uc911 EJB\ub77c\ub294 \uae30\uc220\uc774 J2EE\uc758 \ud575\uc2ec \uae30\uc220\uc774\uc5c8\ub294\ub370, \ud574\ub2f9 \uae30\uc220\uc774 \ub9e4\uc6b0 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub9ce\uc558\ub2e4\uace0 \ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","2002\ub144\uc5d0 Rod Johnson\uc774 EJB\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 J2EE \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc800\uc220\ud55c ",(0,t.jsx)(r.code,{children:"Expert One-to-One J2EE Development"}),"\ub77c\ub294 \ucc45\uc744 \ubc1c\ud589\ud588\uace0, \ucd9c\uac04 \ud6c4 Juergen Hoeller, Yann Caroff\uac00 Rod Johnson\uc5d0\uac8c \uc624\ud508\uc18c\uc2a4 \uc81c\uc548\uc744 \ud558\uc5ec \uc2a4\ud504\ub9c1\uc774 \ud0c4\uc0dd\ud588\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\uc2a4\ud504\ub9c1\uc740 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc11c\ube44\uc2a4 \uae30\ub2a5\uc744 POJO\uc5d0 \uc81c\uacf5\ud558\uba70, \uc774 \ub355\ubd84\uc5d0 \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"webflux-\uc774\uc804-servlet-302009-312013",children:"WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)"}),"\n",(0,t.jsxs)(r.p,{children:["Tomcat\uc758 NIO \ub3d9\uc791 \ubc29\uc2dd\uc744 \ubcf4\uba74 Poller\uac00 \uc18c\ucf13 \ucee4\ub125\uc158\uc744 \ub4e4\uace0 \uc788\ub2e4\uac00 \ucc98\ub9ac\uac00 \uac00\ub2a5\ud560 \ub54c \uc2a4\ub808\ub4dc\ub97c \ud560\ub2f9\ud558\ub294 \uc2dd\uc73c\ub85c \ucc98\ub9ac\ub97c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ud560\ub2f9 \ud6c4 Servlet\uacfc \ud1b5\uc2e0\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \uc694\uccad\uc774 \ub05d\ub0a0 \ub54c\uae4c\uc9c0 \uc2a4\ub808\ub4dc\ub97c \uc810\uc720\ud558\uace0 \uc788\uc5c8\uace0, \uc2a4\ub808\ub4dc \uc810\uc720\ub85c \uc778\ud574 \uc694\uccad\uc774 max thread\uc5d0 \ub3c4\ub2ec\ud558\uba74 \uc694\uccad\uc744 \ucc98\ub9ac\ud560 \uc218 \uc5c6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\uc11c \ube44\ub3d9\uae30 \ubc29\uc2dd\uc758 Servlet\uc774 Servlet 3.0\uc5d0 \ub4f1\uc7a5\ud588\ub2e4. \ud558\uc9c0\ub9cc \uc804\ud1b5\uc801\uc778 I/O \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \ub3d9\uc791\ud588\ub2e4. Servlet 3.1\uc5d0\uc11c \ub17c\ube14\ub85c\ud0b9 I/O\uac00 \ucd94\uac00\ub418\uc5c8\uc9c0\ub9cc, \ub9ce\uc774 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc558\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"spring-webflux2017",children:"Spring WebFlux(2017)"}),"\n",(0,t.jsxs)(r.p,{children:["\uc801\uc740 \uc218\uc758 \uc2a4\ub808\ub4dc\ub85c \ub3d9\uc2dc\uc131\uc744 \ucc98\ub9ac\ud558\uace0, \uc801\uc740 \ub9ac\uc18c\uc2a4\ub85c \ud655\uc7a5\uc774 \uac00\ub2a5\ud55c \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd\uc758 \uc6f9 \uae30\uc220\uc774 \ud544\uc694\ud588\uace0, \uae30\uc874\uc758 Servlet\uc758 \uacbd\uc6b0 \ube44\ub3d9\uae30\ub97c \uc9c0\uc6d0\ud55c\ub2e4 \ud574\ub3c4 \ub3d9\uae30\uc2dd API\ub4e4\uc774 \ub9ce\uc774 \ub0a8\uc544\uc788\uc5c8\uae30 \ub54c\ubb38\uc5d0 \uc774\ub7ec\ud55c Servlet\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294 \uae30\uc220\uc774 \ud544\uc694\ud588\ub2e4. \ub610\ud55c \uae30\uc874\uc5d0 Netty\uc640 \uac19\uc774 \ube44\ub3d9\uae30, \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd \uc11c\ubc84\ub85c \uc790\ub9ac\ub97c \uc798 \uc7a1\uc740 \uc11c\ubc84\ub97c \uc704\ud574 Spring WebFlux\uac00 \ub4f1\uc7a5\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucd94\uac00\ub85c \ub370\uc774\ud130 \uc811\uadfc\uc744 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 JDBC\uc758 \uacbd\uc6b0 Blocking API\ub77c, Spring Webflux\uc5d0\uc11c\ub294 R2DBC\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,t.jsxs)(r.p,{children:["\ud574\ub2f9 \uc815\ub9ac \ub0b4\uc6a9\uc758 \uacbd\uc6b0 Async, Non Blocking \uad00\ub828\ub41c \ub0b4\uc6a9\uc744 \uae4a\uac8c \uacf5\ubd80\ud55c \uc801\uc774 \uc5c6\uc5b4\uc11c \uc815\ud655\ud558\uc9c0 \uc54a\uc744 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\ub3c4 \uae30\uc220\uc758 \ub4f1\uc7a5 \ubc30\uacbd\uc774\ub098 \uacfc\uc815\uc744 \uc54c\uace0 \uc788\ub2e4\uba74 \uc870\uae08 \ub354 \uae4a\uc774 \uc788\ub294 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(r.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815, \uad6c\uad6c \uac15\uc758",(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://httpd.apache.org/docs/trunk/en/howto/cgi.html",children:"Dynamic Content with CGI, Apache Tutorial"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://docs.spring.io/spring-framework/reference/overview.html#overview-history",children:"History of Spring and the Spring Framework, Spring"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.infoworld.com/article/2076557/understanding-javaserver-pages-model-2-architecture.html",children:"Understanding JavaServer Pages Model 2 architecture, Govind Seshadri"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html",children:"MVC, XEROX PARC"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.amazon.com/Expert-One-One-Development-without/dp/0764558315",children:"Expert One-to-One J2EE Development, Rod Johnson"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://techblog.woowahan.com/2667/",children:"\ubc30\ub2ec\uc758\ubbfc\uc871 \ucd5c\uc804\ubc29 \uc2dc\uc2a4\ud15c! \u2018\uac00\uac8c\ub178\ucd9c \uc2dc\uc2a4\ud15c\u2019\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4, \ubc30\ub2ec\uc758\ubbfc\uc871"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.infoworld.com/article/2077995/java-concurrency-asynchronous-processing-support-in-servlet-3-0.html",children:"Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu"}),"\n",(0,t.jsx)(r.a,{href:"https://docs.spring.io/spring-framework/reference/web/webflux/new-framework.html",children:"WebFlux Overview, Spring"}),"\n",(0,t.jsx)(r.a,{href:"https://d2.naver.com/helloworld/6080222",children:"Spring WebFlux\uc640 Armeria\ub97c \uc774\uc6a9\ud558\uc5ec Microservice\uc5d0 \ud544\uc694\ud55c Reactive + RPC \ub3d9\uc2dc\uc5d0 \uc7a1\uae30, Naver D2"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://tweety1121.tistory.com/entry/Spring-WebFlux-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C",children:"Spring WebFlux\ub780 \ubb34\uc5c7\uc77c\uae4c"})]})]})}function d(e={}){const{wrapper:r}={...(0,i.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>c});var t=n(67294);function i(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function l(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(i[n]=e[n]);return i}(e,r);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var a=t.createContext({}),c=function(e){var r=t.useContext(a),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},d=t.forwardRef((function(e,r){var n=e.components,i=e.mdxType,l=e.originalType,a=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),h=c(n),u=i,x=h["".concat(a,".").concat(u)]||h[u]||p[u]||l;return n?t.createElement(x,o(o({ref:r},d),{},{components:n})):t.createElement(x,o({ref:r},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8036],{60367:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>a,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=n(85893),i=n(3905);const l={title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",slug:"web-application-evolution",tags:["web application"]},o=void 0,s={permalink:"/web-application-evolution",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",source:"@site/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",description:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",date:"2023-09-30T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 30\uc77c",tags:[{label:"web application",permalink:"/tags/web-application"}],readingTime:7.5,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",slug:"web-application-evolution",tags:["web application"]},unlisted:!1,prevItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"},nextItem:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",permalink:"/spring-test-isolation"}},a={authorsImageUrls:[]},c=[{value:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",level:3},{value:"WWW(1989)",id:"www1989",level:3},{value:"CGI(1993)",id:"cgi1993",level:3},{value:"Servlet(1996)",id:"servlet1996",level:3},{value:"JSP(1999)",id:"jsp1999",level:3},{value:"MVC(2000)",id:"mvc2000",level:3},{value:"Spring Framework(2003)",id:"spring-framework2003",level:3},{value:"WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)",id:"webflux-\uc774\uc804-servlet-302009-312013",level:3},{value:"Spring WebFlux(2017)",id:"spring-webflux2017",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const r={a:"a",blockquote:"blockquote",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",...(0,i.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h3,{id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",children:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815"}),"\n",(0,t.jsxs)(r.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6d0\ub798 \ud68c\uace0\uc5d0 \uc791\uc131\ud558\ub824\uace0 \ud588\uc9c0\ub9cc, \uc815\ub9ac\ud558\ub2e4 \ubcf4\ub2c8 \uc870\uae08 \uae38\uc5b4\uc838\uc11c \ub530\ub85c \ubd84\ub9ac\ud588\ub2e4."]}),"\n",(0,t.jsx)(r.mermaid,{value:"graph LR\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking"}),"\n",(0,t.jsx)(r.h3,{id:"www1989",children:"WWW(1989)"}),"\n",(0,t.jsx)(r.p,{children:"\uc815\uc801 \ud398\uc774\uc9c0\ub97c \uc81c\uacf5\ud558\ub294 \uc6f9 \uc11c\ubc84\ub97c \uc2dc\uc791\uc73c\ub85c \ub3d9\uc801 \ud398\uc774\uc9c0\uac00 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 CGI\uac00 \ub4f1\uc7a5\ud588\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"cgi1993",children:"CGI(1993)"}),"\n",(0,t.jsx)(r.p,{children:"CGI\ub294 \ub3d9\uc801 \ucf58\ud150\uce20\ub97c \uc81c\uacf5\ud558\uae30 \uc704\ud55c \uaddc\uc57d\uc73c\ub85c, \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc774\uc6a9\ud574\uc11c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ucf1c \uc815\ubcf4\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ub9ce\uc740 \ubd80\ud558\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc774\ub7ec\ud55c \ub2e8\uc810\uc744 \uadf9\ubcf5\ud558\uae30 \uc704\ud574 \ub098\uc628 \uac83\uc774 Servlet\uc774\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"servlet1996",children:"Servlet(1996)"}),"\n",(0,t.jsxs)(r.p,{children:["Servlet\uc740 \uc6f9 \uc11c\ubc84\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uc790\ubc14 \ud504\ub85c\uadf8\ub7a8\uc73c\ub85c HTTP\ub97c \uc774\uc6a9\ud558\uc5ec \uc6f9 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc744 \uc218\uc2e0\ud558\uace0 \uc751\ub2f5\ud55c\ub2e4. CGI\uc640 \ub2e4\ub974\uac8c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\uac00 \uc544\ub2cc \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uc5ec \uc751\ub2f5\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc View \uc601\uc5ed\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uae30 \uc704\ud574 Servlet\uc758 \uc18c\uc2a4 \ucf54\ub4dc\ub97c \uc54c\uc544\uc57c \ud558\ub294 \ub4f1 \ubcf5\uc7a1\ub3c4\uac00 \ub108\ubb34 \ub192\uc558\ub2e4. \ub530\ub77c\uc11c \ud574\ub2f9 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 JSP\uac00 \ub4f1\uc7a5\ud588\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"jsp1999",children:"JSP(1999)"}),"\n",(0,t.jsxs)(r.p,{children:["JSP\ub294 HTML\uc5d0 \uc790\ubc14 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ub3d9\uc801 \uc6f9 \ud398\uc774\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\uc220\ub85c, \uc720\uc0ac\ud55c \uae30\uc220\ub85c\ub294 ASP, PHP\uac00 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","JSP\ub9cc \uc0ac\uc6a9\ud558\uc5ec \ud504\ub85c\uadf8\ub798\ubc0d\ud55c\ub2e4\uba74 Model 1, \uc544\ub798 \uad6c\uc131\ub3c4\uc640 \uac19\uc774 JSP\uac00 View \uc601\uc5ed\ub9cc \ub2f4\ub2f9\ud55c\ub2e4\uba74 Model 2\ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.mermaid,{value:"---\ntitle: JSP Model 2\n---\ngraph LR\n Client -- Request --\x3e Servlet <-- JDBC --\x3e Database\n\tServlet --\x3e Bean\n\tServlet --\x3e JSP\n\tBean <--\x3e JSP\n\tJSP -- Response --\x3e Client"}),"\n",(0,t.jsx)(r.h3,{id:"mvc2000",children:"MVC(2000)"}),"\n",(0,t.jsx)(r.p,{children:"\uc704 JSP\uc758 \uad6c\uc131\ub3c4\ub97c \ubcf4\uba74 \ud604\uc7ac MVC\uc640 \ub9e4\uc6b0 \uc720\uc0ac\ud55c\ub370, Govind Seshadri\ub77c\ub294 \uc0ac\ub78c\uc774 JSP Model 2\ub97c MVC \ud328\ud134\uc73c\ub85c \uacf5\uc2dd\ud654\ub97c \uc81c\uc548\ud588\ub2e4."}),"\n",(0,t.jsxs)(r.blockquote,{children:["\n",(0,t.jsxs)(r.p,{children:["I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern.",(0,t.jsx)(r.br,{}),"\n","Govind Seshadri"]}),"\n"]}),"\n",(0,t.jsxs)(r.p,{children:["\uc774\ub54c MVC \ud328\ud134\uc774 \ucc98\uc74c \ud0c4\uc0dd\ud55c \uac83\uc740 \uc544\ub2c8\uace0, \uc11c\ubc84 \uce21 \uad6c\ud604\uc774\ub77c\uace0 \ud558\ub294 \uac83\uc744 \ubcf4\ub2c8 MVC\uac00 \ucc98\uc74c \ub4f1\uc7a5\ud55c \uac74 \uc544\ub2cc \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html",children:"\ud574\ub2f9 \ubb38\uc11c"}),"\ub97c \ubcf4\uba74 MVC\ub77c\ub294 \uc6a9\uc5b4\uc758 \ub4f1\uc7a5\uc740 1978\ub144\uc5d0 \ub4f1\uc7a5\ud55c \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"spring-framework2003",children:"Spring Framework(2003)"}),"\n",(0,t.jsxs)(r.p,{children:["Spring\uc740 \ubcf5\uc7a1\ud588\ub358 J2EE\uc744 \ub300\uccb4\ud558\uae30 \uc704\ud574 2003\ub144\uc5d0 \ub4f1\uc7a5\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","J2EE\ub294 \uc6f9 \uae30\ubc18\uc758 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\uae30 \uc704\ud55c \ud50c\ub7ab\ud3fc\uc73c\ub85c \uc704\uc5d0\uc11c \uc124\uba85\ud55c Servlet, JSP, EJB \ub4f1\uc758 \uae30\uc220\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \uc774\uc911 EJB\ub77c\ub294 \uae30\uc220\uc774 J2EE\uc758 \ud575\uc2ec \uae30\uc220\uc774\uc5c8\ub294\ub370, \ud574\ub2f9 \uae30\uc220\uc774 \ub9e4\uc6b0 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub9ce\uc558\ub2e4\uace0 \ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","2002\ub144\uc5d0 Rod Johnson\uc774 EJB\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 J2EE \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc800\uc220\ud55c ",(0,t.jsx)(r.code,{children:"Expert One-to-One J2EE Development"}),"\ub77c\ub294 \ucc45\uc744 \ubc1c\ud589\ud588\uace0, \ucd9c\uac04 \ud6c4 Juergen Hoeller, Yann Caroff\uac00 Rod Johnson\uc5d0\uac8c \uc624\ud508\uc18c\uc2a4 \uc81c\uc548\uc744 \ud558\uc5ec \uc2a4\ud504\ub9c1\uc774 \ud0c4\uc0dd\ud588\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\uc2a4\ud504\ub9c1\uc740 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc11c\ube44\uc2a4 \uae30\ub2a5\uc744 POJO\uc5d0 \uc81c\uacf5\ud558\uba70, \uc774 \ub355\ubd84\uc5d0 \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"webflux-\uc774\uc804-servlet-302009-312013",children:"WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)"}),"\n",(0,t.jsxs)(r.p,{children:["Tomcat\uc758 NIO \ub3d9\uc791 \ubc29\uc2dd\uc744 \ubcf4\uba74 Poller\uac00 \uc18c\ucf13 \ucee4\ub125\uc158\uc744 \ub4e4\uace0 \uc788\ub2e4\uac00 \ucc98\ub9ac\uac00 \uac00\ub2a5\ud560 \ub54c \uc2a4\ub808\ub4dc\ub97c \ud560\ub2f9\ud558\ub294 \uc2dd\uc73c\ub85c \ucc98\ub9ac\ub97c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ud560\ub2f9 \ud6c4 Servlet\uacfc \ud1b5\uc2e0\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \uc694\uccad\uc774 \ub05d\ub0a0 \ub54c\uae4c\uc9c0 \uc2a4\ub808\ub4dc\ub97c \uc810\uc720\ud558\uace0 \uc788\uc5c8\uace0, \uc2a4\ub808\ub4dc \uc810\uc720\ub85c \uc778\ud574 \uc694\uccad\uc774 max thread\uc5d0 \ub3c4\ub2ec\ud558\uba74 \uc694\uccad\uc744 \ucc98\ub9ac\ud560 \uc218 \uc5c6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\uc11c \ube44\ub3d9\uae30 \ubc29\uc2dd\uc758 Servlet\uc774 Servlet 3.0\uc5d0 \ub4f1\uc7a5\ud588\ub2e4. \ud558\uc9c0\ub9cc \uc804\ud1b5\uc801\uc778 I/O \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \ub3d9\uc791\ud588\ub2e4. Servlet 3.1\uc5d0\uc11c \ub17c\ube14\ub85c\ud0b9 I/O\uac00 \ucd94\uac00\ub418\uc5c8\uc9c0\ub9cc, \ub9ce\uc774 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc558\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"spring-webflux2017",children:"Spring WebFlux(2017)"}),"\n",(0,t.jsxs)(r.p,{children:["\uc801\uc740 \uc218\uc758 \uc2a4\ub808\ub4dc\ub85c \ub3d9\uc2dc\uc131\uc744 \ucc98\ub9ac\ud558\uace0, \uc801\uc740 \ub9ac\uc18c\uc2a4\ub85c \ud655\uc7a5\uc774 \uac00\ub2a5\ud55c \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd\uc758 \uc6f9 \uae30\uc220\uc774 \ud544\uc694\ud588\uace0, \uae30\uc874\uc758 Servlet\uc758 \uacbd\uc6b0 \ube44\ub3d9\uae30\ub97c \uc9c0\uc6d0\ud55c\ub2e4 \ud574\ub3c4 \ub3d9\uae30\uc2dd API\ub4e4\uc774 \ub9ce\uc774 \ub0a8\uc544\uc788\uc5c8\uae30 \ub54c\ubb38\uc5d0 \uc774\ub7ec\ud55c Servlet\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294 \uae30\uc220\uc774 \ud544\uc694\ud588\ub2e4. \ub610\ud55c \uae30\uc874\uc5d0 Netty\uc640 \uac19\uc774 \ube44\ub3d9\uae30, \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd \uc11c\ubc84\ub85c \uc790\ub9ac\ub97c \uc798 \uc7a1\uc740 \uc11c\ubc84\ub97c \uc704\ud574 Spring WebFlux\uac00 \ub4f1\uc7a5\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucd94\uac00\ub85c \ub370\uc774\ud130 \uc811\uadfc\uc744 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 JDBC\uc758 \uacbd\uc6b0 Blocking API\ub77c, Spring Webflux\uc5d0\uc11c\ub294 R2DBC\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,t.jsxs)(r.p,{children:["\ud574\ub2f9 \uc815\ub9ac \ub0b4\uc6a9\uc758 \uacbd\uc6b0 Async, Non Blocking \uad00\ub828\ub41c \ub0b4\uc6a9\uc744 \uae4a\uac8c \uacf5\ubd80\ud55c \uc801\uc774 \uc5c6\uc5b4\uc11c \uc815\ud655\ud558\uc9c0 \uc54a\uc744 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\ub3c4 \uae30\uc220\uc758 \ub4f1\uc7a5 \ubc30\uacbd\uc774\ub098 \uacfc\uc815\uc744 \uc54c\uace0 \uc788\ub2e4\uba74 \uc870\uae08 \ub354 \uae4a\uc774 \uc788\ub294 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(r.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815, \uad6c\uad6c \uac15\uc758",(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://httpd.apache.org/docs/trunk/en/howto/cgi.html",children:"Dynamic Content with CGI, Apache Tutorial"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://docs.spring.io/spring-framework/reference/overview.html#overview-history",children:"History of Spring and the Spring Framework, Spring"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.infoworld.com/article/2076557/understanding-javaserver-pages-model-2-architecture.html",children:"Understanding JavaServer Pages Model 2 architecture, Govind Seshadri"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html",children:"MVC, XEROX PARC"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.amazon.com/Expert-One-One-Development-without/dp/0764558315",children:"Expert One-to-One J2EE Development, Rod Johnson"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://techblog.woowahan.com/2667/",children:"\ubc30\ub2ec\uc758\ubbfc\uc871 \ucd5c\uc804\ubc29 \uc2dc\uc2a4\ud15c! \u2018\uac00\uac8c\ub178\ucd9c \uc2dc\uc2a4\ud15c\u2019\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4, \ubc30\ub2ec\uc758\ubbfc\uc871"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.infoworld.com/article/2077995/java-concurrency-asynchronous-processing-support-in-servlet-3-0.html",children:"Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu"}),"\n",(0,t.jsx)(r.a,{href:"https://docs.spring.io/spring-framework/reference/web/webflux/new-framework.html",children:"WebFlux Overview, Spring"}),"\n",(0,t.jsx)(r.a,{href:"https://d2.naver.com/helloworld/6080222",children:"Spring WebFlux\uc640 Armeria\ub97c \uc774\uc6a9\ud558\uc5ec Microservice\uc5d0 \ud544\uc694\ud55c Reactive + RPC \ub3d9\uc2dc\uc5d0 \uc7a1\uae30, Naver D2"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://tweety1121.tistory.com/entry/Spring-WebFlux-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C",children:"Spring WebFlux\ub780 \ubb34\uc5c7\uc77c\uae4c"})]})]})}function d(e={}){const{wrapper:r}={...(0,i.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>c});var t=n(67294);function i(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function l(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(i[n]=e[n]);return i}(e,r);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var a=t.createContext({}),c=function(e){var r=t.useContext(a),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},d=t.forwardRef((function(e,r){var n=e.components,i=e.mdxType,l=e.originalType,a=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),h=c(n),u=i,x=h["".concat(a,".").concat(u)]||h[u]||p[u]||l;return n?t.createElement(x,o(o({ref:r},d),{},{components:n})):t.createElement(x,o({ref:r},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/16f719ab.0a2e8f52.js b/assets/js/16f719ab.b3631b89.js similarity index 98% rename from assets/js/16f719ab.0a2e8f52.js rename to assets/js/16f719ab.b3631b89.js index 8057140e9..867e62342 100644 --- a/assets/js/16f719ab.0a2e8f52.js +++ b/assets/js/16f719ab.b3631b89.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9875],{3081:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var t=r(85893),s=r(3905);const i={title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",slug:"subway-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,c={permalink:"/subway-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-subway-path/pull/16",date:"2023-05-25T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 25\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.98,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",slug:"subway-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",permalink:"/composite"},nextItem:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",permalink:"/accidental-duplication"}},l={authorsImageUrls:[]},a=[{value:"\uc9c0\ud558\ucca0 \ubbf8\uc158",id:"\uc9c0\ud558\ucca0-\ubbf8\uc158",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-subway-path/pull/16",children:"https://github.com/woowacourse/jwp-subway-path/pull/16"}),(0,t.jsx)(n.br,{}),"\n","2, 3\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-subway-path/pull/126",children:"https://github.com/woowacourse/jwp-subway-path/pull/126"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc9c0\ud558\ucca0-\ubbf8\uc158",children:"\uc9c0\ud558\ucca0 \ubbf8\uc158"}),"\n",(0,t.jsxs)(n.p,{children:["\uc810\uc810 \uc77c\uc815\uc774 \ub9ce\uc544\uc9c0\ub294 \ub290\ub08c\uc774 \ub4e4\uba74\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc9c4\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc9c0\ud558\ucca0 \ubbf8\uc158\uc740 \ubc00\ub9ac\ub791 \ud398\uc5b4\ub97c \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud55c CRUD\ub9cc \uc788\ub358 \uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac, \uc870\uae08 \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c API, \ud14c\uc774\ube14, \ub3c4\uba54\uc778 \uc124\uacc4\ub97c \ud574\uc57c \ud588\ub294\ub370 \uc5b4\ub5a4 \uac83\ubd80\ud130 \ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","API\uc640 \ud14c\uc774\ube14 \uad6c\uc870\ub97c \uc6b0\ub9ac\uac00 \uc815\ud560 \uc218 \uc788\ub294 \uc0c1\ud669\uc774\uc5c8\uace0, \ub3c4\uba54\uc778 \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \ub3c4\uba54\uc778\uc744 \uba3c\uc800 \uad6c\ud604\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ub178\uc120\uc758 \uad6c\uac04 \ucd94\uac00 \ubc0f \uc0ad\uc81c"})}),"\n",(0,t.jsx)(n.p,{children:"\ub178\uc120\uc744 \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \ubc00\ub9ac\uc640 \uc774\uc57c\uae30\ub97c \ub098\ub234\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"\uad6c\uac04\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc804\ubd80 \uc81c\uac70\ud558\uace0 \uc804\ubd80 \ucd94\uac00\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.li,{children:"\ubcc0\uacbd\ub41c \uc694\uc18c\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ubc18\uc601\ud558\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud398\uc5b4 \uc2dc\uac04\uc774 \uc9e7\uc544\uc11c \ub354\uc6b1 \uac04\ub2e8\ud55c 1\ubc88\uc744 \uc120\ud0dd\ud588\uace0, \uc2dc\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0a4\uae30 \uc704\ud574 \ub354 \uac04\ub2e8\ud558\uac8c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud558\ub294 \uac83\ub3c4 \uc88b\uc740 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\uc600\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\ud6c4 \ud398\uc5b4\uac00 \ub05d\ub098\uace0 \ub9ac\ubdf0\uc5b4\uc778 \uc11c\ube0c\uc6e8\uc774\uac00 \uc77c\ubd80\ubd84\ub9cc \ubc18\uc601\ud558\ub294 \uac83\uc73c\ub85c \uac1c\uc120\ud574 \ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4\uace0 \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c \uc694\uc18c\ub9cc \ubc18\uc601\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:["\ubbf8\uc158\uc758 \ub09c\uc774\ub3c4\uac00 \uc62c\ub77c\uac04 \ub9cc\ud07c, \ud398\uc5b4 \ud560 \ub550 \ucee8\ub514\uc158 \uad00\ub9ac\ub3c4 \uc798\ud558\ub824\uace0 \ub178\ub825\ud558\uace0 \ubbf8\uc158 \ud560 \ub54c\ub3c4 \uc9d1\uc911\ud574\uc11c \uc798 \ub05d\ub0b8 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc54c\uc544\uc57c \ud558\ub294 \uac8c \ub9ce\uc544\uc9c0\uba74\uc11c \uac00\ub054 \uc870\ubc14\uc2ec\uc744 \uac00\uc9c8 \ub54c\uac00 \uc788\ub294 \uac83 \uac19\uc740\ub370, \uc870\ubc14\uc2ec\uc744 \uacbd\uacc4\ud560 \ud544\uc694\uac00 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubd80\uc871\ud55c \ubd80\ubd84\uc740 \uc778\uc815\ud558\uace0, \uc55e\uc73c\ub85c \ub098\uc544\uac00\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc694\uae08 \uc815\ucc45\uc740 \uae30\ubcf8\uc694\uae08 \uc815\ucc45, \uac70\ub9ac\ubcc4 \uc694\uae08 \uc815\ucc45, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uae08\uc744 \ub354\ud558\ub294 \ubd80\ubd84\uacfc, \ud560\uc778\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5b4\uc11c \uc774 \ub458\uc744 \ubd84\ub9ac\ud560\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc, \uc774 \uc815\ub3c4 \ud06c\uae30\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc624\ud788\ub824 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uace0 \ud558\ub098\ub85c \ud569\uce58\ub294 \uac8c \ub354 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ubd84\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \uc815\ucc45\uc758 \uc21c\uc11c\uac00 \uc911\uc694\ud55c\ub370, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc744 \ub9c8\uc9c0\ub9c9\uc5d0 \ub450\uc5b4\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ucc45\uc784 \uc5f0\uc1c4 \ud328\ud134\ub3c4 \uace0\ub824\ub97c \ud588\uc9c0\ub9cc \uc870\uae08 \ub354 \uac04\uacb0\ud574 \ubcf4\uc774\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \uc120\ud0dd\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ub3c4\uba54\uc778\uc5d0 \ud2b9\uc815 \uae30\uc220\uc758 \uc758\uc874\uc131\uc744 \ubd84\ub9ac"})}),"\n",(0,t.jsxs)(n.p,{children:["\ucc98\uc74c\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uc5d0 jgrapht \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc758\uc874\ud558\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \ub450\uc5b4\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uac00 jgrapht\uc640 \uac15\uacb0\ud569\uc774 \ub418\uc5b4\ubc84\ub838\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\uc5d0\ub294 \uacbd\ub85c \uac80\uc0c9\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0, \uc138\ubd80 \uad6c\ud604\uc740 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \uc678\ubd80\ub85c \ubd84\ub9ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd5c\ub300\ud55c \uac04\uacb0\ud558\uac8c \uad6c\ud604\ud55c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud574\ub3c4, \uc774\ub7f0 \ubd80\ubd84\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uc5b4 \uacb0\ud569\uc744 \ud53c\ud558\ub294 \uac83\uc774 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.admonition,{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134",type:"note",children:(0,t.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc778\uc218 \ud14c\uc2a4\ud2b8 \uc791\uc131"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc778\uc218 \ud14c\uc2a4\ud2b8\ub294 \uc0ac\uc6a9\uc790 \uc2a4\ud1a0\ub9ac \uc2dc\ub098\ub9ac\uc624 \uae30\ubc18 \ud14c\uc2a4\ud2b8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ube0c\ub77c\uc6b4\uc774 \ud574\uc8fc\uc2e0 \uac15\uc758 + \uc720\ud29c\ube0c\uc5d0 \uc788\ub294 \ube0c\ub77c\uc6b4\uc758 \uac15\uc758\ub97c \ubcf4\uace0 \uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0 \uc778\uc218 \ud14c\uc2a4\ud2b8\ub97c \uc801\uc6a9\ud574 \ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc, \ubcc0\uc218\uba85\uc744 \uc804\ubd80 \ud55c\uae00\ub85c \uc791\uc131\ud588\ub294\ub370 \uc804\uccb4\uc801\uc778 \ud750\ub984\uc744 \uc54c\uae30 \ud3b8\ud558\uace0 \uc77d\uae30\ub3c4 \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc778\uc218 \ud14c\uc2a4\ud2b8\uc5d0 \ud544\uc694\ud55c Steps\ub97c \ub9cc\ub4dc\ub294 \uacfc\uc815\uc774 \ub108\ubb34 \uc7ac\ubc0c\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@Nested\npublic class \ub178\uc120\uc744_\uc804\uccb4_\uc870\ud68c\ud560_\ub54c {\n\n @Test\n void \uc0c1\ud589\uc885\uc810\uc5ed_\ubd80\ud130_\ud558\ud589\uc885\uc810\uc5ed\uc73c\ub85c_\uc815\ub82c\ub41c_\uacb0\uacfc\ub97c_\ubc18\ud658\ud55c\ub2e4() {\n // given\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\ucd08\ub85d", 0);\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\uc7a0\uc2e4", "\uc7a0\uc2e4\uc0c8\ub0b4", 5);\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\uc7a0\uc2e4\uc0c8\ub0b4", "\uc885\ud569\uc6b4\ub3d9\uc7a5", \uc624\ub978\ucabd, 5);\n\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\uace0\ub3d9", 0);\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\ubd09\uc740\uc0ac", "\uc885\ud569\uc6b4\ub3d9\uc7a5", 3);\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\uc885\ud569\uc6b4\ub3d9\uc7a5", "\uc0bc\uc804", \uc624\ub978\ucabd, 7);\n\n // when\n final var \uc870\ud68c_\uacb0\uacfc = \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uc694\uccad();\n\n // then\n \uc694\uccad_\uacb0\uacfc\uc758_\uc0c1\ud0dc\ub97c_\uac80\uc99d\ud55c\ub2e4(\uc870\ud68c_\uacb0\uacfc, \uc815\uc0c1_\uc694\uccad);\n \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uacb0\uacfc\ub97c_\ud655\uc778\ud55c\ub2e4(\n \uc870\ud68c_\uacb0\uacfc,\n \ub178\uc120_\uc815\ubcf4("2\ud638\uc120", "\ucd08\ub85d", 0, "\uc7a0\uc2e4", "\uc7a0\uc2e4\uc0c8\ub0b4", "\uc885\ud569\uc6b4\ub3d9\uc7a5"),\n \ub178\uc120_\uc815\ubcf4("9\ud638\uc120", "\uace0\ub3d9", 0, "\ubd09\uc740\uc0ac", "\uc885\ud569\uc6b4\ub3d9\uc7a5", "\uc0bc\uc804")\n );\n }\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc758\uacac \uc870\uc728\ud558\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc00\ub9ac\uac00 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\uc11c \uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \uc9c4\ud589\uc774 \uc218\uc6d4\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc758\uc0ac\uc18c\ud1b5\uc774 \ub9e4\uc6b0 \uc798 \ub3fc\uc11c \uc88b\uc558\uace0 \ub355\ubd84\uc5d0 \uc2dc\uac04 \ub0b4\uc5d0 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574 \ubbf8\uc158\uc744 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\ud558\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc00\ub9ac\ub294 \ucf54\ub529\uc744 \uc5c4\uccad \uaf3c\uaf3c\ud558\uac8c \ud558\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubcc0\uc218\uba85, \uba54\uc11c\ub4dc\uba85\uc744 \uc911\uc694\ud558\uac8c \uc0dd\uac01\ud588\uace0, \uc88b\uc740 \ubcc0\uc218\uba85\uc744 \uc798 \uc9d3\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ucf54\ub529\ud560 \ub54c \ub0b4\uac00 \ud3c9\uc18c\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub529 \ucee8\ubca4\uc158\uc5d0 \ub9de\ucdb0\uc8fc\ub294 \uac83 \uac19\uc544\uc11c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud588\ub2e4!"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ud3b8\ud55c \ubd84\uc704\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc804\uccb4\uc801\uc73c\ub85c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud558\uac8c \uc9c4\ud589\ud588\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc77c\uc815\ub3c4 \uadf8\ub807\uace0, \ud398\uc5b4 \uc9c4\ud589\ud560 \ub54c\ub3c4 \uadf8\ub807\uace0 \ud070 \ubb38\uc81c\uac00 \uc5c6\uc5c8\ub358 \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub098\ub294 \uacfc\uc5f0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \ud3b8\ud55c \uc0ac\ub78c\uc77c\uae4c?"]})]})}function h(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var l=t.createContext({}),a=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},h=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,h=c(e,["components","mdxType","originalType","parentName"]),j=a(r),d=s,u=j["".concat(l,".").concat(d)]||j[d]||p[d]||i;return r?t.createElement(u,o(o({ref:n},h),{},{components:r})):t.createElement(u,o({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9875],{3081:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var t=r(85893),s=r(3905);const i={title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",slug:"subway-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,c={permalink:"/subway-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-subway-path/pull/16",date:"2023-05-25T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 25\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.98,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",slug:"subway-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",permalink:"/accidental-duplication"},nextItem:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",permalink:"/composite"}},l={authorsImageUrls:[]},a=[{value:"\uc9c0\ud558\ucca0 \ubbf8\uc158",id:"\uc9c0\ud558\ucca0-\ubbf8\uc158",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-subway-path/pull/16",children:"https://github.com/woowacourse/jwp-subway-path/pull/16"}),(0,t.jsx)(n.br,{}),"\n","2, 3\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-subway-path/pull/126",children:"https://github.com/woowacourse/jwp-subway-path/pull/126"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc9c0\ud558\ucca0-\ubbf8\uc158",children:"\uc9c0\ud558\ucca0 \ubbf8\uc158"}),"\n",(0,t.jsxs)(n.p,{children:["\uc810\uc810 \uc77c\uc815\uc774 \ub9ce\uc544\uc9c0\ub294 \ub290\ub08c\uc774 \ub4e4\uba74\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc9c4\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc9c0\ud558\ucca0 \ubbf8\uc158\uc740 \ubc00\ub9ac\ub791 \ud398\uc5b4\ub97c \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud55c CRUD\ub9cc \uc788\ub358 \uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac, \uc870\uae08 \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c API, \ud14c\uc774\ube14, \ub3c4\uba54\uc778 \uc124\uacc4\ub97c \ud574\uc57c \ud588\ub294\ub370 \uc5b4\ub5a4 \uac83\ubd80\ud130 \ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","API\uc640 \ud14c\uc774\ube14 \uad6c\uc870\ub97c \uc6b0\ub9ac\uac00 \uc815\ud560 \uc218 \uc788\ub294 \uc0c1\ud669\uc774\uc5c8\uace0, \ub3c4\uba54\uc778 \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \ub3c4\uba54\uc778\uc744 \uba3c\uc800 \uad6c\ud604\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ub178\uc120\uc758 \uad6c\uac04 \ucd94\uac00 \ubc0f \uc0ad\uc81c"})}),"\n",(0,t.jsx)(n.p,{children:"\ub178\uc120\uc744 \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \ubc00\ub9ac\uc640 \uc774\uc57c\uae30\ub97c \ub098\ub234\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"\uad6c\uac04\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc804\ubd80 \uc81c\uac70\ud558\uace0 \uc804\ubd80 \ucd94\uac00\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.li,{children:"\ubcc0\uacbd\ub41c \uc694\uc18c\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ubc18\uc601\ud558\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud398\uc5b4 \uc2dc\uac04\uc774 \uc9e7\uc544\uc11c \ub354\uc6b1 \uac04\ub2e8\ud55c 1\ubc88\uc744 \uc120\ud0dd\ud588\uace0, \uc2dc\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0a4\uae30 \uc704\ud574 \ub354 \uac04\ub2e8\ud558\uac8c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud558\ub294 \uac83\ub3c4 \uc88b\uc740 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\uc600\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\ud6c4 \ud398\uc5b4\uac00 \ub05d\ub098\uace0 \ub9ac\ubdf0\uc5b4\uc778 \uc11c\ube0c\uc6e8\uc774\uac00 \uc77c\ubd80\ubd84\ub9cc \ubc18\uc601\ud558\ub294 \uac83\uc73c\ub85c \uac1c\uc120\ud574 \ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4\uace0 \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c \uc694\uc18c\ub9cc \ubc18\uc601\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:["\ubbf8\uc158\uc758 \ub09c\uc774\ub3c4\uac00 \uc62c\ub77c\uac04 \ub9cc\ud07c, \ud398\uc5b4 \ud560 \ub550 \ucee8\ub514\uc158 \uad00\ub9ac\ub3c4 \uc798\ud558\ub824\uace0 \ub178\ub825\ud558\uace0 \ubbf8\uc158 \ud560 \ub54c\ub3c4 \uc9d1\uc911\ud574\uc11c \uc798 \ub05d\ub0b8 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc54c\uc544\uc57c \ud558\ub294 \uac8c \ub9ce\uc544\uc9c0\uba74\uc11c \uac00\ub054 \uc870\ubc14\uc2ec\uc744 \uac00\uc9c8 \ub54c\uac00 \uc788\ub294 \uac83 \uac19\uc740\ub370, \uc870\ubc14\uc2ec\uc744 \uacbd\uacc4\ud560 \ud544\uc694\uac00 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubd80\uc871\ud55c \ubd80\ubd84\uc740 \uc778\uc815\ud558\uace0, \uc55e\uc73c\ub85c \ub098\uc544\uac00\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc694\uae08 \uc815\ucc45\uc740 \uae30\ubcf8\uc694\uae08 \uc815\ucc45, \uac70\ub9ac\ubcc4 \uc694\uae08 \uc815\ucc45, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uae08\uc744 \ub354\ud558\ub294 \ubd80\ubd84\uacfc, \ud560\uc778\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5b4\uc11c \uc774 \ub458\uc744 \ubd84\ub9ac\ud560\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc, \uc774 \uc815\ub3c4 \ud06c\uae30\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc624\ud788\ub824 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uace0 \ud558\ub098\ub85c \ud569\uce58\ub294 \uac8c \ub354 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ubd84\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \uc815\ucc45\uc758 \uc21c\uc11c\uac00 \uc911\uc694\ud55c\ub370, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc744 \ub9c8\uc9c0\ub9c9\uc5d0 \ub450\uc5b4\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ucc45\uc784 \uc5f0\uc1c4 \ud328\ud134\ub3c4 \uace0\ub824\ub97c \ud588\uc9c0\ub9cc \uc870\uae08 \ub354 \uac04\uacb0\ud574 \ubcf4\uc774\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \uc120\ud0dd\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ub3c4\uba54\uc778\uc5d0 \ud2b9\uc815 \uae30\uc220\uc758 \uc758\uc874\uc131\uc744 \ubd84\ub9ac"})}),"\n",(0,t.jsxs)(n.p,{children:["\ucc98\uc74c\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uc5d0 jgrapht \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc758\uc874\ud558\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \ub450\uc5b4\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uac00 jgrapht\uc640 \uac15\uacb0\ud569\uc774 \ub418\uc5b4\ubc84\ub838\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\uc5d0\ub294 \uacbd\ub85c \uac80\uc0c9\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0, \uc138\ubd80 \uad6c\ud604\uc740 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \uc678\ubd80\ub85c \ubd84\ub9ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd5c\ub300\ud55c \uac04\uacb0\ud558\uac8c \uad6c\ud604\ud55c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud574\ub3c4, \uc774\ub7f0 \ubd80\ubd84\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uc5b4 \uacb0\ud569\uc744 \ud53c\ud558\ub294 \uac83\uc774 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.admonition,{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134",type:"note",children:(0,t.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc778\uc218 \ud14c\uc2a4\ud2b8 \uc791\uc131"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc778\uc218 \ud14c\uc2a4\ud2b8\ub294 \uc0ac\uc6a9\uc790 \uc2a4\ud1a0\ub9ac \uc2dc\ub098\ub9ac\uc624 \uae30\ubc18 \ud14c\uc2a4\ud2b8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ube0c\ub77c\uc6b4\uc774 \ud574\uc8fc\uc2e0 \uac15\uc758 + \uc720\ud29c\ube0c\uc5d0 \uc788\ub294 \ube0c\ub77c\uc6b4\uc758 \uac15\uc758\ub97c \ubcf4\uace0 \uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0 \uc778\uc218 \ud14c\uc2a4\ud2b8\ub97c \uc801\uc6a9\ud574 \ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc, \ubcc0\uc218\uba85\uc744 \uc804\ubd80 \ud55c\uae00\ub85c \uc791\uc131\ud588\ub294\ub370 \uc804\uccb4\uc801\uc778 \ud750\ub984\uc744 \uc54c\uae30 \ud3b8\ud558\uace0 \uc77d\uae30\ub3c4 \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc778\uc218 \ud14c\uc2a4\ud2b8\uc5d0 \ud544\uc694\ud55c Steps\ub97c \ub9cc\ub4dc\ub294 \uacfc\uc815\uc774 \ub108\ubb34 \uc7ac\ubc0c\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@Nested\npublic class \ub178\uc120\uc744_\uc804\uccb4_\uc870\ud68c\ud560_\ub54c {\n\n @Test\n void \uc0c1\ud589\uc885\uc810\uc5ed_\ubd80\ud130_\ud558\ud589\uc885\uc810\uc5ed\uc73c\ub85c_\uc815\ub82c\ub41c_\uacb0\uacfc\ub97c_\ubc18\ud658\ud55c\ub2e4() {\n // given\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\ucd08\ub85d", 0);\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\uc7a0\uc2e4", "\uc7a0\uc2e4\uc0c8\ub0b4", 5);\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\uc7a0\uc2e4\uc0c8\ub0b4", "\uc885\ud569\uc6b4\ub3d9\uc7a5", \uc624\ub978\ucabd, 5);\n\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\uace0\ub3d9", 0);\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\ubd09\uc740\uc0ac", "\uc885\ud569\uc6b4\ub3d9\uc7a5", 3);\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\uc885\ud569\uc6b4\ub3d9\uc7a5", "\uc0bc\uc804", \uc624\ub978\ucabd, 7);\n\n // when\n final var \uc870\ud68c_\uacb0\uacfc = \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uc694\uccad();\n\n // then\n \uc694\uccad_\uacb0\uacfc\uc758_\uc0c1\ud0dc\ub97c_\uac80\uc99d\ud55c\ub2e4(\uc870\ud68c_\uacb0\uacfc, \uc815\uc0c1_\uc694\uccad);\n \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uacb0\uacfc\ub97c_\ud655\uc778\ud55c\ub2e4(\n \uc870\ud68c_\uacb0\uacfc,\n \ub178\uc120_\uc815\ubcf4("2\ud638\uc120", "\ucd08\ub85d", 0, "\uc7a0\uc2e4", "\uc7a0\uc2e4\uc0c8\ub0b4", "\uc885\ud569\uc6b4\ub3d9\uc7a5"),\n \ub178\uc120_\uc815\ubcf4("9\ud638\uc120", "\uace0\ub3d9", 0, "\ubd09\uc740\uc0ac", "\uc885\ud569\uc6b4\ub3d9\uc7a5", "\uc0bc\uc804")\n );\n }\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc758\uacac \uc870\uc728\ud558\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc00\ub9ac\uac00 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\uc11c \uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \uc9c4\ud589\uc774 \uc218\uc6d4\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc758\uc0ac\uc18c\ud1b5\uc774 \ub9e4\uc6b0 \uc798 \ub3fc\uc11c \uc88b\uc558\uace0 \ub355\ubd84\uc5d0 \uc2dc\uac04 \ub0b4\uc5d0 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574 \ubbf8\uc158\uc744 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\ud558\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc00\ub9ac\ub294 \ucf54\ub529\uc744 \uc5c4\uccad \uaf3c\uaf3c\ud558\uac8c \ud558\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubcc0\uc218\uba85, \uba54\uc11c\ub4dc\uba85\uc744 \uc911\uc694\ud558\uac8c \uc0dd\uac01\ud588\uace0, \uc88b\uc740 \ubcc0\uc218\uba85\uc744 \uc798 \uc9d3\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ucf54\ub529\ud560 \ub54c \ub0b4\uac00 \ud3c9\uc18c\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub529 \ucee8\ubca4\uc158\uc5d0 \ub9de\ucdb0\uc8fc\ub294 \uac83 \uac19\uc544\uc11c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud588\ub2e4!"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ud3b8\ud55c \ubd84\uc704\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc804\uccb4\uc801\uc73c\ub85c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud558\uac8c \uc9c4\ud589\ud588\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc77c\uc815\ub3c4 \uadf8\ub807\uace0, \ud398\uc5b4 \uc9c4\ud589\ud560 \ub54c\ub3c4 \uadf8\ub807\uace0 \ud070 \ubb38\uc81c\uac00 \uc5c6\uc5c8\ub358 \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub098\ub294 \uacfc\uc5f0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \ud3b8\ud55c \uc0ac\ub78c\uc77c\uae4c?"]})]})}function h(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var l=t.createContext({}),a=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},h=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,h=c(e,["components","mdxType","originalType","parentName"]),j=a(r),d=s,u=j["".concat(l,".").concat(d)]||j[d]||p[d]||i;return r?t.createElement(u,o(o({ref:n},h),{},{components:r})):t.createElement(u,o({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/1781b1c4.511d5aa4.js b/assets/js/1781b1c4.21e20787.js similarity index 98% rename from assets/js/1781b1c4.511d5aa4.js rename to assets/js/1781b1c4.21e20787.js index da085d8cb..43533f10c 100644 --- a/assets/js/1781b1c4.511d5aa4.js +++ b/assets/js/1781b1c4.21e20787.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5785],{16865:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var t=r(85893),s=r(3905);const i={title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",slug:"subway-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,c={permalink:"/subway-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-subway-path/pull/16",date:"2023-05-25T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 25\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.98,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",slug:"subway-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",permalink:"/composite"},nextItem:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",permalink:"/accidental-duplication"}},l={authorsImageUrls:[]},a=[{value:"\uc9c0\ud558\ucca0 \ubbf8\uc158",id:"\uc9c0\ud558\ucca0-\ubbf8\uc158",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-subway-path/pull/16",children:"https://github.com/woowacourse/jwp-subway-path/pull/16"}),(0,t.jsx)(n.br,{}),"\n","2, 3\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-subway-path/pull/126",children:"https://github.com/woowacourse/jwp-subway-path/pull/126"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc9c0\ud558\ucca0-\ubbf8\uc158",children:"\uc9c0\ud558\ucca0 \ubbf8\uc158"}),"\n",(0,t.jsxs)(n.p,{children:["\uc810\uc810 \uc77c\uc815\uc774 \ub9ce\uc544\uc9c0\ub294 \ub290\ub08c\uc774 \ub4e4\uba74\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc9c4\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc9c0\ud558\ucca0 \ubbf8\uc158\uc740 \ubc00\ub9ac\ub791 \ud398\uc5b4\ub97c \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud55c CRUD\ub9cc \uc788\ub358 \uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac, \uc870\uae08 \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c API, \ud14c\uc774\ube14, \ub3c4\uba54\uc778 \uc124\uacc4\ub97c \ud574\uc57c \ud588\ub294\ub370 \uc5b4\ub5a4 \uac83\ubd80\ud130 \ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","API\uc640 \ud14c\uc774\ube14 \uad6c\uc870\ub97c \uc6b0\ub9ac\uac00 \uc815\ud560 \uc218 \uc788\ub294 \uc0c1\ud669\uc774\uc5c8\uace0, \ub3c4\uba54\uc778 \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \ub3c4\uba54\uc778\uc744 \uba3c\uc800 \uad6c\ud604\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ub178\uc120\uc758 \uad6c\uac04 \ucd94\uac00 \ubc0f \uc0ad\uc81c"})}),"\n",(0,t.jsx)(n.p,{children:"\ub178\uc120\uc744 \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \ubc00\ub9ac\uc640 \uc774\uc57c\uae30\ub97c \ub098\ub234\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"\uad6c\uac04\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc804\ubd80 \uc81c\uac70\ud558\uace0 \uc804\ubd80 \ucd94\uac00\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.li,{children:"\ubcc0\uacbd\ub41c \uc694\uc18c\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ubc18\uc601\ud558\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud398\uc5b4 \uc2dc\uac04\uc774 \uc9e7\uc544\uc11c \ub354\uc6b1 \uac04\ub2e8\ud55c 1\ubc88\uc744 \uc120\ud0dd\ud588\uace0, \uc2dc\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0a4\uae30 \uc704\ud574 \ub354 \uac04\ub2e8\ud558\uac8c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud558\ub294 \uac83\ub3c4 \uc88b\uc740 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\uc600\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\ud6c4 \ud398\uc5b4\uac00 \ub05d\ub098\uace0 \ub9ac\ubdf0\uc5b4\uc778 \uc11c\ube0c\uc6e8\uc774\uac00 \uc77c\ubd80\ubd84\ub9cc \ubc18\uc601\ud558\ub294 \uac83\uc73c\ub85c \uac1c\uc120\ud574 \ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4\uace0 \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c \uc694\uc18c\ub9cc \ubc18\uc601\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:["\ubbf8\uc158\uc758 \ub09c\uc774\ub3c4\uac00 \uc62c\ub77c\uac04 \ub9cc\ud07c, \ud398\uc5b4 \ud560 \ub550 \ucee8\ub514\uc158 \uad00\ub9ac\ub3c4 \uc798\ud558\ub824\uace0 \ub178\ub825\ud558\uace0 \ubbf8\uc158 \ud560 \ub54c\ub3c4 \uc9d1\uc911\ud574\uc11c \uc798 \ub05d\ub0b8 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc54c\uc544\uc57c \ud558\ub294 \uac8c \ub9ce\uc544\uc9c0\uba74\uc11c \uac00\ub054 \uc870\ubc14\uc2ec\uc744 \uac00\uc9c8 \ub54c\uac00 \uc788\ub294 \uac83 \uac19\uc740\ub370, \uc870\ubc14\uc2ec\uc744 \uacbd\uacc4\ud560 \ud544\uc694\uac00 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubd80\uc871\ud55c \ubd80\ubd84\uc740 \uc778\uc815\ud558\uace0, \uc55e\uc73c\ub85c \ub098\uc544\uac00\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc694\uae08 \uc815\ucc45\uc740 \uae30\ubcf8\uc694\uae08 \uc815\ucc45, \uac70\ub9ac\ubcc4 \uc694\uae08 \uc815\ucc45, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uae08\uc744 \ub354\ud558\ub294 \ubd80\ubd84\uacfc, \ud560\uc778\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5b4\uc11c \uc774 \ub458\uc744 \ubd84\ub9ac\ud560\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc, \uc774 \uc815\ub3c4 \ud06c\uae30\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc624\ud788\ub824 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uace0 \ud558\ub098\ub85c \ud569\uce58\ub294 \uac8c \ub354 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ubd84\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \uc815\ucc45\uc758 \uc21c\uc11c\uac00 \uc911\uc694\ud55c\ub370, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc744 \ub9c8\uc9c0\ub9c9\uc5d0 \ub450\uc5b4\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ucc45\uc784 \uc5f0\uc1c4 \ud328\ud134\ub3c4 \uace0\ub824\ub97c \ud588\uc9c0\ub9cc \uc870\uae08 \ub354 \uac04\uacb0\ud574 \ubcf4\uc774\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \uc120\ud0dd\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ub3c4\uba54\uc778\uc5d0 \ud2b9\uc815 \uae30\uc220\uc758 \uc758\uc874\uc131\uc744 \ubd84\ub9ac"})}),"\n",(0,t.jsxs)(n.p,{children:["\ucc98\uc74c\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uc5d0 jgrapht \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc758\uc874\ud558\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \ub450\uc5b4\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uac00 jgrapht\uc640 \uac15\uacb0\ud569\uc774 \ub418\uc5b4\ubc84\ub838\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\uc5d0\ub294 \uacbd\ub85c \uac80\uc0c9\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0, \uc138\ubd80 \uad6c\ud604\uc740 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \uc678\ubd80\ub85c \ubd84\ub9ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd5c\ub300\ud55c \uac04\uacb0\ud558\uac8c \uad6c\ud604\ud55c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud574\ub3c4, \uc774\ub7f0 \ubd80\ubd84\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uc5b4 \uacb0\ud569\uc744 \ud53c\ud558\ub294 \uac83\uc774 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.admonition,{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134",type:"note",children:(0,t.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc778\uc218 \ud14c\uc2a4\ud2b8 \uc791\uc131"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc778\uc218 \ud14c\uc2a4\ud2b8\ub294 \uc0ac\uc6a9\uc790 \uc2a4\ud1a0\ub9ac \uc2dc\ub098\ub9ac\uc624 \uae30\ubc18 \ud14c\uc2a4\ud2b8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ube0c\ub77c\uc6b4\uc774 \ud574\uc8fc\uc2e0 \uac15\uc758 + \uc720\ud29c\ube0c\uc5d0 \uc788\ub294 \ube0c\ub77c\uc6b4\uc758 \uac15\uc758\ub97c \ubcf4\uace0 \uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0 \uc778\uc218 \ud14c\uc2a4\ud2b8\ub97c \uc801\uc6a9\ud574 \ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc, \ubcc0\uc218\uba85\uc744 \uc804\ubd80 \ud55c\uae00\ub85c \uc791\uc131\ud588\ub294\ub370 \uc804\uccb4\uc801\uc778 \ud750\ub984\uc744 \uc54c\uae30 \ud3b8\ud558\uace0 \uc77d\uae30\ub3c4 \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc778\uc218 \ud14c\uc2a4\ud2b8\uc5d0 \ud544\uc694\ud55c Steps\ub97c \ub9cc\ub4dc\ub294 \uacfc\uc815\uc774 \ub108\ubb34 \uc7ac\ubc0c\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@Nested\npublic class \ub178\uc120\uc744_\uc804\uccb4_\uc870\ud68c\ud560_\ub54c {\n\n @Test\n void \uc0c1\ud589\uc885\uc810\uc5ed_\ubd80\ud130_\ud558\ud589\uc885\uc810\uc5ed\uc73c\ub85c_\uc815\ub82c\ub41c_\uacb0\uacfc\ub97c_\ubc18\ud658\ud55c\ub2e4() {\n // given\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\ucd08\ub85d", 0);\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\uc7a0\uc2e4", "\uc7a0\uc2e4\uc0c8\ub0b4", 5);\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\uc7a0\uc2e4\uc0c8\ub0b4", "\uc885\ud569\uc6b4\ub3d9\uc7a5", \uc624\ub978\ucabd, 5);\n\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\uace0\ub3d9", 0);\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\ubd09\uc740\uc0ac", "\uc885\ud569\uc6b4\ub3d9\uc7a5", 3);\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\uc885\ud569\uc6b4\ub3d9\uc7a5", "\uc0bc\uc804", \uc624\ub978\ucabd, 7);\n\n // when\n final var \uc870\ud68c_\uacb0\uacfc = \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uc694\uccad();\n\n // then\n \uc694\uccad_\uacb0\uacfc\uc758_\uc0c1\ud0dc\ub97c_\uac80\uc99d\ud55c\ub2e4(\uc870\ud68c_\uacb0\uacfc, \uc815\uc0c1_\uc694\uccad);\n \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uacb0\uacfc\ub97c_\ud655\uc778\ud55c\ub2e4(\n \uc870\ud68c_\uacb0\uacfc,\n \ub178\uc120_\uc815\ubcf4("2\ud638\uc120", "\ucd08\ub85d", 0, "\uc7a0\uc2e4", "\uc7a0\uc2e4\uc0c8\ub0b4", "\uc885\ud569\uc6b4\ub3d9\uc7a5"),\n \ub178\uc120_\uc815\ubcf4("9\ud638\uc120", "\uace0\ub3d9", 0, "\ubd09\uc740\uc0ac", "\uc885\ud569\uc6b4\ub3d9\uc7a5", "\uc0bc\uc804")\n );\n }\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc758\uacac \uc870\uc728\ud558\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc00\ub9ac\uac00 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\uc11c \uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \uc9c4\ud589\uc774 \uc218\uc6d4\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc758\uc0ac\uc18c\ud1b5\uc774 \ub9e4\uc6b0 \uc798 \ub3fc\uc11c \uc88b\uc558\uace0 \ub355\ubd84\uc5d0 \uc2dc\uac04 \ub0b4\uc5d0 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574 \ubbf8\uc158\uc744 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\ud558\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc00\ub9ac\ub294 \ucf54\ub529\uc744 \uc5c4\uccad \uaf3c\uaf3c\ud558\uac8c \ud558\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubcc0\uc218\uba85, \uba54\uc11c\ub4dc\uba85\uc744 \uc911\uc694\ud558\uac8c \uc0dd\uac01\ud588\uace0, \uc88b\uc740 \ubcc0\uc218\uba85\uc744 \uc798 \uc9d3\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ucf54\ub529\ud560 \ub54c \ub0b4\uac00 \ud3c9\uc18c\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub529 \ucee8\ubca4\uc158\uc5d0 \ub9de\ucdb0\uc8fc\ub294 \uac83 \uac19\uc544\uc11c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud588\ub2e4!"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ud3b8\ud55c \ubd84\uc704\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc804\uccb4\uc801\uc73c\ub85c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud558\uac8c \uc9c4\ud589\ud588\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc77c\uc815\ub3c4 \uadf8\ub807\uace0, \ud398\uc5b4 \uc9c4\ud589\ud560 \ub54c\ub3c4 \uadf8\ub807\uace0 \ud070 \ubb38\uc81c\uac00 \uc5c6\uc5c8\ub358 \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub098\ub294 \uacfc\uc5f0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \ud3b8\ud55c \uc0ac\ub78c\uc77c\uae4c?"]})]})}function h(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var l=t.createContext({}),a=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},h=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,h=c(e,["components","mdxType","originalType","parentName"]),j=a(r),d=s,u=j["".concat(l,".").concat(d)]||j[d]||p[d]||i;return r?t.createElement(u,o(o({ref:n},h),{},{components:r})):t.createElement(u,o({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5785],{16865:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var t=r(85893),s=r(3905);const i={title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",slug:"subway-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,c={permalink:"/subway-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-subway-path/pull/16",date:"2023-05-25T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 25\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.98,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",slug:"subway-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",permalink:"/accidental-duplication"},nextItem:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",permalink:"/composite"}},l={authorsImageUrls:[]},a=[{value:"\uc9c0\ud558\ucca0 \ubbf8\uc158",id:"\uc9c0\ud558\ucca0-\ubbf8\uc158",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-subway-path/pull/16",children:"https://github.com/woowacourse/jwp-subway-path/pull/16"}),(0,t.jsx)(n.br,{}),"\n","2, 3\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-subway-path/pull/126",children:"https://github.com/woowacourse/jwp-subway-path/pull/126"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc9c0\ud558\ucca0-\ubbf8\uc158",children:"\uc9c0\ud558\ucca0 \ubbf8\uc158"}),"\n",(0,t.jsxs)(n.p,{children:["\uc810\uc810 \uc77c\uc815\uc774 \ub9ce\uc544\uc9c0\ub294 \ub290\ub08c\uc774 \ub4e4\uba74\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc9c4\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc9c0\ud558\ucca0 \ubbf8\uc158\uc740 \ubc00\ub9ac\ub791 \ud398\uc5b4\ub97c \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud55c CRUD\ub9cc \uc788\ub358 \uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac, \uc870\uae08 \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c API, \ud14c\uc774\ube14, \ub3c4\uba54\uc778 \uc124\uacc4\ub97c \ud574\uc57c \ud588\ub294\ub370 \uc5b4\ub5a4 \uac83\ubd80\ud130 \ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","API\uc640 \ud14c\uc774\ube14 \uad6c\uc870\ub97c \uc6b0\ub9ac\uac00 \uc815\ud560 \uc218 \uc788\ub294 \uc0c1\ud669\uc774\uc5c8\uace0, \ub3c4\uba54\uc778 \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \ub3c4\uba54\uc778\uc744 \uba3c\uc800 \uad6c\ud604\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ub178\uc120\uc758 \uad6c\uac04 \ucd94\uac00 \ubc0f \uc0ad\uc81c"})}),"\n",(0,t.jsx)(n.p,{children:"\ub178\uc120\uc744 \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \ubc00\ub9ac\uc640 \uc774\uc57c\uae30\ub97c \ub098\ub234\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"\uad6c\uac04\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc804\ubd80 \uc81c\uac70\ud558\uace0 \uc804\ubd80 \ucd94\uac00\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.li,{children:"\ubcc0\uacbd\ub41c \uc694\uc18c\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ubc18\uc601\ud558\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud398\uc5b4 \uc2dc\uac04\uc774 \uc9e7\uc544\uc11c \ub354\uc6b1 \uac04\ub2e8\ud55c 1\ubc88\uc744 \uc120\ud0dd\ud588\uace0, \uc2dc\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0a4\uae30 \uc704\ud574 \ub354 \uac04\ub2e8\ud558\uac8c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud558\ub294 \uac83\ub3c4 \uc88b\uc740 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\uc600\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\ud6c4 \ud398\uc5b4\uac00 \ub05d\ub098\uace0 \ub9ac\ubdf0\uc5b4\uc778 \uc11c\ube0c\uc6e8\uc774\uac00 \uc77c\ubd80\ubd84\ub9cc \ubc18\uc601\ud558\ub294 \uac83\uc73c\ub85c \uac1c\uc120\ud574 \ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4\uace0 \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c \uc694\uc18c\ub9cc \ubc18\uc601\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:["\ubbf8\uc158\uc758 \ub09c\uc774\ub3c4\uac00 \uc62c\ub77c\uac04 \ub9cc\ud07c, \ud398\uc5b4 \ud560 \ub550 \ucee8\ub514\uc158 \uad00\ub9ac\ub3c4 \uc798\ud558\ub824\uace0 \ub178\ub825\ud558\uace0 \ubbf8\uc158 \ud560 \ub54c\ub3c4 \uc9d1\uc911\ud574\uc11c \uc798 \ub05d\ub0b8 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc54c\uc544\uc57c \ud558\ub294 \uac8c \ub9ce\uc544\uc9c0\uba74\uc11c \uac00\ub054 \uc870\ubc14\uc2ec\uc744 \uac00\uc9c8 \ub54c\uac00 \uc788\ub294 \uac83 \uac19\uc740\ub370, \uc870\ubc14\uc2ec\uc744 \uacbd\uacc4\ud560 \ud544\uc694\uac00 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubd80\uc871\ud55c \ubd80\ubd84\uc740 \uc778\uc815\ud558\uace0, \uc55e\uc73c\ub85c \ub098\uc544\uac00\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc694\uae08 \uc815\ucc45\uc740 \uae30\ubcf8\uc694\uae08 \uc815\ucc45, \uac70\ub9ac\ubcc4 \uc694\uae08 \uc815\ucc45, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uae08\uc744 \ub354\ud558\ub294 \ubd80\ubd84\uacfc, \ud560\uc778\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5b4\uc11c \uc774 \ub458\uc744 \ubd84\ub9ac\ud560\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc, \uc774 \uc815\ub3c4 \ud06c\uae30\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc624\ud788\ub824 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uace0 \ud558\ub098\ub85c \ud569\uce58\ub294 \uac8c \ub354 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ubd84\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \uc815\ucc45\uc758 \uc21c\uc11c\uac00 \uc911\uc694\ud55c\ub370, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc744 \ub9c8\uc9c0\ub9c9\uc5d0 \ub450\uc5b4\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ucc45\uc784 \uc5f0\uc1c4 \ud328\ud134\ub3c4 \uace0\ub824\ub97c \ud588\uc9c0\ub9cc \uc870\uae08 \ub354 \uac04\uacb0\ud574 \ubcf4\uc774\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \uc120\ud0dd\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ub3c4\uba54\uc778\uc5d0 \ud2b9\uc815 \uae30\uc220\uc758 \uc758\uc874\uc131\uc744 \ubd84\ub9ac"})}),"\n",(0,t.jsxs)(n.p,{children:["\ucc98\uc74c\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uc5d0 jgrapht \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc758\uc874\ud558\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \ub450\uc5b4\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uac00 jgrapht\uc640 \uac15\uacb0\ud569\uc774 \ub418\uc5b4\ubc84\ub838\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\uc5d0\ub294 \uacbd\ub85c \uac80\uc0c9\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0, \uc138\ubd80 \uad6c\ud604\uc740 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \uc678\ubd80\ub85c \ubd84\ub9ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd5c\ub300\ud55c \uac04\uacb0\ud558\uac8c \uad6c\ud604\ud55c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud574\ub3c4, \uc774\ub7f0 \ubd80\ubd84\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uc5b4 \uacb0\ud569\uc744 \ud53c\ud558\ub294 \uac83\uc774 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.admonition,{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134",type:"note",children:(0,t.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc778\uc218 \ud14c\uc2a4\ud2b8 \uc791\uc131"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc778\uc218 \ud14c\uc2a4\ud2b8\ub294 \uc0ac\uc6a9\uc790 \uc2a4\ud1a0\ub9ac \uc2dc\ub098\ub9ac\uc624 \uae30\ubc18 \ud14c\uc2a4\ud2b8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ube0c\ub77c\uc6b4\uc774 \ud574\uc8fc\uc2e0 \uac15\uc758 + \uc720\ud29c\ube0c\uc5d0 \uc788\ub294 \ube0c\ub77c\uc6b4\uc758 \uac15\uc758\ub97c \ubcf4\uace0 \uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0 \uc778\uc218 \ud14c\uc2a4\ud2b8\ub97c \uc801\uc6a9\ud574 \ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc, \ubcc0\uc218\uba85\uc744 \uc804\ubd80 \ud55c\uae00\ub85c \uc791\uc131\ud588\ub294\ub370 \uc804\uccb4\uc801\uc778 \ud750\ub984\uc744 \uc54c\uae30 \ud3b8\ud558\uace0 \uc77d\uae30\ub3c4 \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc778\uc218 \ud14c\uc2a4\ud2b8\uc5d0 \ud544\uc694\ud55c Steps\ub97c \ub9cc\ub4dc\ub294 \uacfc\uc815\uc774 \ub108\ubb34 \uc7ac\ubc0c\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@Nested\npublic class \ub178\uc120\uc744_\uc804\uccb4_\uc870\ud68c\ud560_\ub54c {\n\n @Test\n void \uc0c1\ud589\uc885\uc810\uc5ed_\ubd80\ud130_\ud558\ud589\uc885\uc810\uc5ed\uc73c\ub85c_\uc815\ub82c\ub41c_\uacb0\uacfc\ub97c_\ubc18\ud658\ud55c\ub2e4() {\n // given\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\ucd08\ub85d", 0);\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\uc7a0\uc2e4", "\uc7a0\uc2e4\uc0c8\ub0b4", 5);\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad("2\ud638\uc120", "\uc7a0\uc2e4\uc0c8\ub0b4", "\uc885\ud569\uc6b4\ub3d9\uc7a5", \uc624\ub978\ucabd, 5);\n\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\uace0\ub3d9", 0);\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\ubd09\uc740\uc0ac", "\uc885\ud569\uc6b4\ub3d9\uc7a5", 3);\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad("9\ud638\uc120", "\uc885\ud569\uc6b4\ub3d9\uc7a5", "\uc0bc\uc804", \uc624\ub978\ucabd, 7);\n\n // when\n final var \uc870\ud68c_\uacb0\uacfc = \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uc694\uccad();\n\n // then\n \uc694\uccad_\uacb0\uacfc\uc758_\uc0c1\ud0dc\ub97c_\uac80\uc99d\ud55c\ub2e4(\uc870\ud68c_\uacb0\uacfc, \uc815\uc0c1_\uc694\uccad);\n \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uacb0\uacfc\ub97c_\ud655\uc778\ud55c\ub2e4(\n \uc870\ud68c_\uacb0\uacfc,\n \ub178\uc120_\uc815\ubcf4("2\ud638\uc120", "\ucd08\ub85d", 0, "\uc7a0\uc2e4", "\uc7a0\uc2e4\uc0c8\ub0b4", "\uc885\ud569\uc6b4\ub3d9\uc7a5"),\n \ub178\uc120_\uc815\ubcf4("9\ud638\uc120", "\uace0\ub3d9", 0, "\ubd09\uc740\uc0ac", "\uc885\ud569\uc6b4\ub3d9\uc7a5", "\uc0bc\uc804")\n );\n }\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc758\uacac \uc870\uc728\ud558\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc00\ub9ac\uac00 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\uc11c \uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \uc9c4\ud589\uc774 \uc218\uc6d4\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc758\uc0ac\uc18c\ud1b5\uc774 \ub9e4\uc6b0 \uc798 \ub3fc\uc11c \uc88b\uc558\uace0 \ub355\ubd84\uc5d0 \uc2dc\uac04 \ub0b4\uc5d0 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574 \ubbf8\uc158\uc744 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\ud558\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc00\ub9ac\ub294 \ucf54\ub529\uc744 \uc5c4\uccad \uaf3c\uaf3c\ud558\uac8c \ud558\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubcc0\uc218\uba85, \uba54\uc11c\ub4dc\uba85\uc744 \uc911\uc694\ud558\uac8c \uc0dd\uac01\ud588\uace0, \uc88b\uc740 \ubcc0\uc218\uba85\uc744 \uc798 \uc9d3\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ucf54\ub529\ud560 \ub54c \ub0b4\uac00 \ud3c9\uc18c\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub529 \ucee8\ubca4\uc158\uc5d0 \ub9de\ucdb0\uc8fc\ub294 \uac83 \uac19\uc544\uc11c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud588\ub2e4!"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\ud3b8\ud55c \ubd84\uc704\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc804\uccb4\uc801\uc73c\ub85c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud558\uac8c \uc9c4\ud589\ud588\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc77c\uc815\ub3c4 \uadf8\ub807\uace0, \ud398\uc5b4 \uc9c4\ud589\ud560 \ub54c\ub3c4 \uadf8\ub807\uace0 \ud070 \ubb38\uc81c\uac00 \uc5c6\uc5c8\ub358 \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub098\ub294 \uacfc\uc5f0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \ud3b8\ud55c \uc0ac\ub78c\uc77c\uae4c?"]})]})}function h(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var l=t.createContext({}),a=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},h=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,h=c(e,["components","mdxType","originalType","parentName"]),j=a(r),d=s,u=j["".concat(l,".").concat(d)]||j[d]||p[d]||i;return r?t.createElement(u,o(o({ref:n},h),{},{components:r})):t.createElement(u,o({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/1e8ecffe.de94e202.js b/assets/js/1e8ecffe.564d76f3.js similarity index 99% rename from assets/js/1e8ecffe.de94e202.js rename to assets/js/1e8ecffe.564d76f3.js index 085d63f10..1a184aa75 100644 --- a/assets/js/1e8ecffe.de94e202.js +++ b/assets/js/1e8ecffe.564d76f3.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3333],{58307:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>a});var n=t(85893),s=t(3905);const i={title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",slug:"refactoring-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,o={permalink:"/refactoring-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-refactoring/pull/465",date:"2023-10-31T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 31\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:8.095,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",slug:"refactoring-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,nextItem:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/jdbc-retrospective"}},l={authorsImageUrls:[]},a=[{value:"\ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158",id:"\ub9ac\ud329\ud130\ub9c1-\ubbf8\uc158",level:3},{value:"1, 2\ub2e8\uacc4",id:"1-2\ub2e8\uacc4",level:3},{value:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c",id:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758-\ubcf5\uc7a1\uc131\uc744-\ub2e4\ub8e8\ub294-\uc9c0\ud61c",level:3},{value:"3, 4\ub2e8\uacc4",id:"3-4\ub2e8\uacc4",level:3},{value:"\ub9c8\ubb34\ub9ac",id:"\ub9c8\ubb34\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,n.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/465",children:"https://github.com/woowacourse/jwp-refactoring/pull/465"}),(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/547",children:"https://github.com/woowacourse/jwp-refactoring/pull/547"}),(0,n.jsx)(r.br,{}),"\n","3\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/610",children:"https://github.com/woowacourse/jwp-refactoring/pull/610"}),(0,n.jsx)(r.br,{}),"\n","4\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/721",children:"https://github.com/woowacourse/jwp-refactoring/pull/721"})]})}),"\n",(0,n.jsx)(r.h3,{id:"\ub9ac\ud329\ud130\ub9c1-\ubbf8\uc158",children:"\ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["\uc694\uad6c\uc0ac\ud56d \uc791\uc131 \u2192 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud55c \ucf54\ub4dc \ubcf4\ud638 \u2192 \ub9ac\ud329\ud130\ub9c1 \u2192 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1 \u2192 \uba40\ud2f0\ubaa8\ub4c8 \uc21c\uc11c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc5d0 \uc628\uc804\ud788 \uc9d1\uc911\ud558\uace0 \uc2f6\uc5c8\uc9c0\ub9cc, \ud504\ub85c\uc81d\ud2b8\uc640 \ubcd1\ud589\ud558\uba74\uc11c \uc9c4\ud589\ud588\uae30\uc5d0 \uc5b4\ub290\uc815\ub3c4 \ud0c0\ud611\ubcf4\uace0 \uc9c4\ud589\ud55c \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c \uc544\uc26c\uc6e0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"1-2\ub2e8\uacc4",children:"1, 2\ub2e8\uacc4"}),"\n",(0,n.jsx)(r.p,{children:"1\ub2e8\uacc4\ub294 \uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud558\uace0, \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ucd94\ud6c4\uc5d0 \ub9ac\ud329\ud130\ub9c1 \ud560 \ub54c \uc548\uc815\uac10 \uc788\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\ub3c4\ub85d \uc900\ube44\ud558\ub294 \uacfc\uc815\uc774\uc5c8\ub2e4.\n\uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud560 \ub54c \uc81c\uacf5\ub41c \uc6a9\uc5b4 \uc0ac\uc804\uc744 \ucd5c\ub300\ud55c \ud65c\uc6a9\ud558\uba74\uc11c \uae30\uc874\uc758 \ucf54\ub4dc\ub97c \ubcf4\uba74\uc11c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud588\ub2e4.\n\ud14c\uc2a4\ud2b8\ub294 \uc2dc\uac04 \uad00\uacc4\uc0c1 API, \uc11c\ube44\uc2a4 \ub458 \uc911 \ud558\ub098\ub9cc \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4."}),"\n",(0,n.jsxs)(r.p,{children:["\ucd5c\uc885\uc801\uc73c\ub85c \uc11c\ube44\uc2a4 \uae30\uc900\uc73c\ub85c \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud588\ub294\ub370 \uc57d\uac04 \ud6c4\ud68c\ub418\ub294 \uacb0\uc815\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub9ac\ud329\ud130\ub9c1 \uacfc\uc815\uc5d0\uc11c API \uba85\uc138\uac00 \ubc14\ub00c\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4\ub294 \uac83\uc744 \uae30\uc900\uc744 \uc7a1\uace0 \uc774\ubc88 \ubbf8\uc158\uc744 \ud55c\ub2e4\uace0 \uac00\uc815\ud588\uc744 \ub54c API \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\uace0, \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ub354 \uc548\uc815\uac10 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["2\ub2e8\uacc4\ub294 \uc791\uc131\ub41c \ud14c\uc2a4\ud2b8 \uae30\ubc18\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc11c\ube44\uc2a4\uc5d0\uc11c \ub3c4\uba54\uc778\uc744 \uc9c1\uc811 \ubc18\ud658\ud558\ub294 \uad6c\uc870\uc600\ub294\ub370, \ub3c4\uba54\uc778\uc5d0 JPA\ub97c \uc801\uc6a9\ud558\uba74 \uae30\uc874 \uba85\uc138\uc640 \ub2ec\ub77c\uc9c8 \uac83\uc744 \uc6b0\ub824\ud574\uc11c DTO\ub85c \uc218\uc815\ud558\ub294 \uc791\uc5c5\uc744 \uba3c\uc800 \uc9c4\ud589\ud588\ub2e4.\nDTO \uc774\ud6c4\uc5d0 \uc11c\ube44\uc2a4\uc5d0 \uc788\ub294 \ub85c\uc9c1\uc744 \ub3c4\uba54\uc778\uc73c\ub85c \uc774\ub3d9\uc2dc\ud0a4\uace0, \ucd5c\uc885\uc801\uc73c\ub85c JPA\ub97c \uc801\uc6a9\ud558\ub294 \uc21c\uc11c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud588\ub2e4.\n\uc774 \uacfc\uc815\uc5d0\uc11c \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \uc591\ubc29\ud5a5\uc778 \ubd80\ubd84\ub3c4 \uc0dd\uaca8\ub0ac\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758-\ubcf5\uc7a1\uc131\uc744-\ub2e4\ub8e8\ub294-\uc9c0\ud61c",children:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c"}),"\n",(0,n.jsxs)(r.p,{children:["\uc911\uac04\uc5d0 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\uc5d0 \uad00\ud55c \uc81c\uc774\uc2a8\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\ub294 \uc5d0\ub9ad \uc5d0\ubc18\uc2a4\uc758 \uc800\uc11c ",(0,n.jsx)(r.code,{children:"\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4"}),"\uc758 \ubd80\uc81c\uc774\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\ub294 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4, \uc804\uc220\uc801 \uc124\uacc4\uac00 \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4\uac00 \uc804\uccb4\uc758 90%\uc5d0 \ud574\ub2f9\ud560 \uc815\ub3c4\ub85c \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4. \ub610\ud55c \uc804\uc220\uc801 \uc124\uacc4\ub9cc \ud558\ub294 \uacbd\uc6b0\ub97c DDD Lite \ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\uac04\ub2e8\ud788 \ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\uc5d0\uc11c \ub098\uc624\ub294 \ub2e8\uc5b4\ub97c \uc815\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,n.jsxs)(r.table,{children:[(0,n.jsx)(r.thead,{children:(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.th,{children:"\ub2e8\uc5b4"}),(0,n.jsx)(r.th,{children:"\uc124\uba85"})]})}),(0,n.jsxs)(r.tbody,{children:[(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\ub3c4\uba54\uc778"}),(0,n.jsx)(r.td,{children:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\ub85c \ud574\uacb0\ud558\uace0\uc790 \ud558\ub294 \ubb38\uc81c \uc601\uc5ed"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8"}),(0,n.jsx)(r.td,{children:"\ud574\uacb0 \uc601\uc5ed, \uad00\uc2ec\uc0ac\ub97c \ubd84\ub9ac\ud558\uace0 \uaca9\ub9ac\ud558\uc5ec \ubb38\uc81c \ud574\uacb0\uc5d0 \uc9d1\uc911\ud560 \ubc94\uc704"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4"}),(0,n.jsx)(r.td,{children:"\ud504\ub85c\uc81d\ud2b8\uc5d0 \uc774\ud574\uad00\uacc4\uc790\ub4e4\uc758 \uacf5\ud1b5\ub41c \uc5b8\uc5b4\ub85c, \uc11c\ub85c\uc758 \uc758\uc0ac\uc18c\ud1b5 \ube44\uc6a9\uc744 \uc904\uc774\uae30 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 \uc5b8\uc5b4"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc804\ub7b5\uc801 \uc124\uacc4"}),(0,n.jsx)(r.td,{children:"\ub3c4\uba54\uc778 \uc804\ubb38\uac00\uc640 \uac1c\ubc1c\uc790\uac00 \ud568\uaed8 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec \ub3c4\uba54\uc778\uacfc \uad00\ub828\ub41c \uc9c0\uc2dd\uc744 \uc774\ud574\ud558\uace0 \uc774\ub97c \ubc14\ud0d5\uc73c\ub85c \uacbd\uacc4\ub97c \ub098\ub220 \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc815\uc758\ud558\uace0, \ucee8\ud14d\uc2a4\ud2b8 \ub9f5\uc744 \uc0dd\uc131\ud558\ub294 \uac83\uc744 \ud3ec\ud568\ud558\ub294 \uacfc\uc815"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc804\uc220\uc801 \uc124\uacc4"}),(0,n.jsx)(r.td,{children:"\uc804\ub7b5\uc801 \uc124\uacc4\uc5d0\uc11c \uc815\uc758\ud55c \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\uc640 \ub3c4\uba54\uc778\uc744 \uc774\uc6a9\ud558\uc5ec \uc560\uadf8\ub9ac\uac70\ud2b8, Entity\uc640 VO, Repository \ub4f1\uc744 \uad6c\ud604\ud558\ub294 \uacfc\uc815"})]})]})]}),"\n",(0,n.jsx)(r.p,{children:"\uc774 \uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ub0b4\uc6a9\ub4e4\uc774 \ub098\uc654\uc9c0\ub9cc, \uc9c0\uc2dd\uc744 \uc81c\ub300\ub85c \ud761\uc218\ud558\uc9c0\ub294 \ubabb\ud588\ub2e4."}),"\n",(0,n.jsx)(r.h3,{id:"3-4\ub2e8\uacc4",children:"3, 4\ub2e8\uacc4"}),"\n",(0,n.jsx)(r.p,{children:"\uc81c\uc774\uc2a8\uc758 \uac15\uc758\ub97c \ub4e3\uace0, \uc870\uc601\ud638\ub2d8\uc758 \uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5 \uc720\ud29c\ube0c \uc601\uc0c1\uc744 \ubcf8 \ub2e4\uc74c 3, 4\ub2e8\uacc4\ub97c \uc9c4\ud589\ud588\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:"3\ub2e8\uacc4\ub294 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1\uc5d0 \uad00\ud55c \ub0b4\uc6a9\uc774\uc5c8\ub2e4. \ud074\ub798\uc2a4 \uac04 \ubc29\ud5a5, \ud328\ud0a4\uc9c0 \uac04 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc774 \ub418\ub3c4\ub85d \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud574\uc57c \ud588\uc5c8\ub2e4.\n\ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4\ub4e4\uc744 \ubb36\uace0, \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uae30 \uc704\ud574 \uc0dd\uba85\uc8fc\uae30\uac00 \ub2e4\ub974\ub2e4\uba74 id\ub97c \uc774\uc6a9\ud558\uc5ec \ucc38\uc870\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:"\uc758\uc874\uc131\uc744 \ubd84\ub9ac\ud558\uae30 \uc704\ud574 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4. \uc774\ubca4\ud2b8\ub294 \ud604\uc7ac \uae30\uc900\uc73c\ub85c \uacfc\uac70\uc5d0 \ubc8c\uc5b4\uc9c4 \uac83\uc744 \ud45c\ud604\ud558\uae30 \ub54c\ubb38\uc5d0 \uc774\ubca4\ud2b8\uba85\uc740 \uacfc\uac70 \uc2dc\uc81c\uac00 \ub418\uc5b4\uc57c\ud558\ub294 \uac83\uc744 \uc54c\uc558\ub2e4.\n\ucc98\uc74c\uc5d0\ub294 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud588\uc9c0\ub9cc, \uc11c\ube44\uc2a4 \ub85c\uc9c1\uc744 \ucd5c\ub300\ud55c \uac04\ub2e8\ud558\uac8c \ud558\uae30 \uc704\ud574 \ub3c4\uba54\uc778 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4."}),"\n",(0,n.jsxs)(r.p,{children:["4\ub2e8\uacc4\ub294 \uba40\ud2f0\ubaa8\ub4c8\ub85c \ubd84\ub9ac\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub294\ub370 3\ub2e8\uacc4\uc5d0\uc11c \ubd84\ub9ac\ud574\ub454 \ud328\ud0a4\uc9c0 \uadf8\ub300\ub85c \ubd84\ub9ac\ud558\uc9c0\ub294 \uc54a\uc558\ub2e4.",(0,n.jsx)(r.br,{}),"\n","3\ub2e8\uacc4\uc5d0\uc11c\ub294 \ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4 \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ud588\ub2e4. 4\ub2e8\uacc4\uc5d0\uc11c\ub294 \ub0b4\uac00 \uc778\uc2dd\ud558\uae30 \ud3b8\ud55c \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ub97c \ud588\ub2e4.\n\uc544\uc9c1 \ubd84\ub9ac\ud55c \uae30\uc900\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \ubaa8\ud638\ud588\uace0, \uc774\uc5d0 \ub300\ud55c \uacf5\ubd80\ub97c \uc870\uae08 \ub354 \ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.mermaid,{value:"graph LR\n\tsubgraph Table\n\t\tOrderTable --\x3e TableGroup\n\tend\n\tsubgraph Order\n\t\tO\n\tend\n O[Order] --\x3e OrderTable\n\tsubgraph Menu\n\t\tM[Menu] --\x3e MenuGroup\n\t\tM --\x3e Product\n\tend\n\tO --\x3e M"}),"\n",(0,n.jsxs)(r.p,{children:["\ucd94\uac00\ub85c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc704\ud55c \uc9c1\uc811 \uc791\uc131\ud55c ",(0,n.jsx)(r.code,{children:"@ServiceTest"})," \ucee4\uc2a4\ud140 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc788\uc5c8\ub294\ub370, \uc0c1\uc704 \ubaa8\ub4c8\uc758 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \ub9cc\ub4e0 \ud074\ub798\uc2a4\ub97c \ud558\uc704 \ubaa8\ub4c8\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4.\n\ub530\ub77c\uc11c TestFixtures\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\uacb0\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ub9c8\ubb34\ub9ac",children:"\ub9c8\ubb34\ub9ac"}),"\n",(0,n.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc758 \ub9c8\uc9c0\ub9c9 \ubbf8\uc158\uc774\ub2c8 \ub9cc\ud07c, \uac00\uc7a5 \ud765\ubbf8\ub85c\uc6b4 \ubbf8\uc158\uc774\uc5c8\uace0 \ubc30\uc6b8\uc810\ub3c4 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc14\uc05c \uae30\uac04\uc774\ub77c \ub9ce\uc740 \ub9ac\ubdf0\ub97c \ub0a8\uae30\uc9c0 \ubabb\ud588\ub358 \ub9ac\ubdf0\uc774 \ud638\uc774\uc5d0\uac8c \ubbf8\uc548\ud558\uace0, \ucf54\uba58\ud2b8 \uaf3c\uaf3c\ud558\uac8c \ub2ec\uc544\uc8fc\uace0 \ubbf8\uc158\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub3c4 \uc624\ud504\ub77c\uc778\uc73c\ub85c \ub9ce\uc774 \ub098\ub208 \ub9ac\ubdf0\uc5b4 \ud14c\uc624\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,n.jsxs)(r.p,{children:[(0,n.jsx)(r.a,{href:"https://www.youtube.com/watch?v=kmUneexSxk0",children:"\ub3c4\uba54\uc778 \uc6d0\uc815\ub300, \uc6b0\uc544\ucf58 2021"}),(0,n.jsx)(r.br,{}),"\n",(0,n.jsx)(r.a,{href:"https://www.youtube.com/watch?v=dJ5C4qRqAgA",children:"\uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5, \uc6b0\uc544\ud55c\ud14c\ud06c\uc138\ubbf8\ub098"}),(0,n.jsx)(r.br,{}),"\n",(0,n.jsx)(r.a,{href:"https://kwonnam.pe.kr/wiki/gradle/testfixtures",children:"TestFixtures, \uad8c\ub0a8\ub2d8"})]})]})}function h(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>a});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=n.createContext({}),a=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},d={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},h=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,h=o(e,["components","mdxType","originalType","parentName"]),p=a(t),u=s,j=p["".concat(l,".").concat(u)]||p[u]||d[u]||i;return t?n.createElement(j,c(c({ref:r},h),{},{components:t})):n.createElement(j,c({ref:r},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3333],{58307:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>a});var n=t(85893),s=t(3905);const i={title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",slug:"refactoring-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,o={permalink:"/refactoring-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-refactoring/pull/465",date:"2023-10-31T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 31\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:8.095,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",slug:"refactoring-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/jdbc-retrospective"}},l={authorsImageUrls:[]},a=[{value:"\ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158",id:"\ub9ac\ud329\ud130\ub9c1-\ubbf8\uc158",level:3},{value:"1, 2\ub2e8\uacc4",id:"1-2\ub2e8\uacc4",level:3},{value:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c",id:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758-\ubcf5\uc7a1\uc131\uc744-\ub2e4\ub8e8\ub294-\uc9c0\ud61c",level:3},{value:"3, 4\ub2e8\uacc4",id:"3-4\ub2e8\uacc4",level:3},{value:"\ub9c8\ubb34\ub9ac",id:"\ub9c8\ubb34\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,n.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/465",children:"https://github.com/woowacourse/jwp-refactoring/pull/465"}),(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/547",children:"https://github.com/woowacourse/jwp-refactoring/pull/547"}),(0,n.jsx)(r.br,{}),"\n","3\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/610",children:"https://github.com/woowacourse/jwp-refactoring/pull/610"}),(0,n.jsx)(r.br,{}),"\n","4\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/721",children:"https://github.com/woowacourse/jwp-refactoring/pull/721"})]})}),"\n",(0,n.jsx)(r.h3,{id:"\ub9ac\ud329\ud130\ub9c1-\ubbf8\uc158",children:"\ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["\uc694\uad6c\uc0ac\ud56d \uc791\uc131 \u2192 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud55c \ucf54\ub4dc \ubcf4\ud638 \u2192 \ub9ac\ud329\ud130\ub9c1 \u2192 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1 \u2192 \uba40\ud2f0\ubaa8\ub4c8 \uc21c\uc11c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc5d0 \uc628\uc804\ud788 \uc9d1\uc911\ud558\uace0 \uc2f6\uc5c8\uc9c0\ub9cc, \ud504\ub85c\uc81d\ud2b8\uc640 \ubcd1\ud589\ud558\uba74\uc11c \uc9c4\ud589\ud588\uae30\uc5d0 \uc5b4\ub290\uc815\ub3c4 \ud0c0\ud611\ubcf4\uace0 \uc9c4\ud589\ud55c \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c \uc544\uc26c\uc6e0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"1-2\ub2e8\uacc4",children:"1, 2\ub2e8\uacc4"}),"\n",(0,n.jsx)(r.p,{children:"1\ub2e8\uacc4\ub294 \uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud558\uace0, \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ucd94\ud6c4\uc5d0 \ub9ac\ud329\ud130\ub9c1 \ud560 \ub54c \uc548\uc815\uac10 \uc788\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\ub3c4\ub85d \uc900\ube44\ud558\ub294 \uacfc\uc815\uc774\uc5c8\ub2e4.\n\uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud560 \ub54c \uc81c\uacf5\ub41c \uc6a9\uc5b4 \uc0ac\uc804\uc744 \ucd5c\ub300\ud55c \ud65c\uc6a9\ud558\uba74\uc11c \uae30\uc874\uc758 \ucf54\ub4dc\ub97c \ubcf4\uba74\uc11c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud588\ub2e4.\n\ud14c\uc2a4\ud2b8\ub294 \uc2dc\uac04 \uad00\uacc4\uc0c1 API, \uc11c\ube44\uc2a4 \ub458 \uc911 \ud558\ub098\ub9cc \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4."}),"\n",(0,n.jsxs)(r.p,{children:["\ucd5c\uc885\uc801\uc73c\ub85c \uc11c\ube44\uc2a4 \uae30\uc900\uc73c\ub85c \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud588\ub294\ub370 \uc57d\uac04 \ud6c4\ud68c\ub418\ub294 \uacb0\uc815\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub9ac\ud329\ud130\ub9c1 \uacfc\uc815\uc5d0\uc11c API \uba85\uc138\uac00 \ubc14\ub00c\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4\ub294 \uac83\uc744 \uae30\uc900\uc744 \uc7a1\uace0 \uc774\ubc88 \ubbf8\uc158\uc744 \ud55c\ub2e4\uace0 \uac00\uc815\ud588\uc744 \ub54c API \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\uace0, \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ub354 \uc548\uc815\uac10 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["2\ub2e8\uacc4\ub294 \uc791\uc131\ub41c \ud14c\uc2a4\ud2b8 \uae30\ubc18\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc11c\ube44\uc2a4\uc5d0\uc11c \ub3c4\uba54\uc778\uc744 \uc9c1\uc811 \ubc18\ud658\ud558\ub294 \uad6c\uc870\uc600\ub294\ub370, \ub3c4\uba54\uc778\uc5d0 JPA\ub97c \uc801\uc6a9\ud558\uba74 \uae30\uc874 \uba85\uc138\uc640 \ub2ec\ub77c\uc9c8 \uac83\uc744 \uc6b0\ub824\ud574\uc11c DTO\ub85c \uc218\uc815\ud558\ub294 \uc791\uc5c5\uc744 \uba3c\uc800 \uc9c4\ud589\ud588\ub2e4.\nDTO \uc774\ud6c4\uc5d0 \uc11c\ube44\uc2a4\uc5d0 \uc788\ub294 \ub85c\uc9c1\uc744 \ub3c4\uba54\uc778\uc73c\ub85c \uc774\ub3d9\uc2dc\ud0a4\uace0, \ucd5c\uc885\uc801\uc73c\ub85c JPA\ub97c \uc801\uc6a9\ud558\ub294 \uc21c\uc11c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud588\ub2e4.\n\uc774 \uacfc\uc815\uc5d0\uc11c \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \uc591\ubc29\ud5a5\uc778 \ubd80\ubd84\ub3c4 \uc0dd\uaca8\ub0ac\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758-\ubcf5\uc7a1\uc131\uc744-\ub2e4\ub8e8\ub294-\uc9c0\ud61c",children:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c"}),"\n",(0,n.jsxs)(r.p,{children:["\uc911\uac04\uc5d0 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\uc5d0 \uad00\ud55c \uc81c\uc774\uc2a8\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\ub294 \uc5d0\ub9ad \uc5d0\ubc18\uc2a4\uc758 \uc800\uc11c ",(0,n.jsx)(r.code,{children:"\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4"}),"\uc758 \ubd80\uc81c\uc774\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\ub294 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4, \uc804\uc220\uc801 \uc124\uacc4\uac00 \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4\uac00 \uc804\uccb4\uc758 90%\uc5d0 \ud574\ub2f9\ud560 \uc815\ub3c4\ub85c \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4. \ub610\ud55c \uc804\uc220\uc801 \uc124\uacc4\ub9cc \ud558\ub294 \uacbd\uc6b0\ub97c DDD Lite \ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\uac04\ub2e8\ud788 \ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\uc5d0\uc11c \ub098\uc624\ub294 \ub2e8\uc5b4\ub97c \uc815\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,n.jsxs)(r.table,{children:[(0,n.jsx)(r.thead,{children:(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.th,{children:"\ub2e8\uc5b4"}),(0,n.jsx)(r.th,{children:"\uc124\uba85"})]})}),(0,n.jsxs)(r.tbody,{children:[(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\ub3c4\uba54\uc778"}),(0,n.jsx)(r.td,{children:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\ub85c \ud574\uacb0\ud558\uace0\uc790 \ud558\ub294 \ubb38\uc81c \uc601\uc5ed"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8"}),(0,n.jsx)(r.td,{children:"\ud574\uacb0 \uc601\uc5ed, \uad00\uc2ec\uc0ac\ub97c \ubd84\ub9ac\ud558\uace0 \uaca9\ub9ac\ud558\uc5ec \ubb38\uc81c \ud574\uacb0\uc5d0 \uc9d1\uc911\ud560 \ubc94\uc704"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4"}),(0,n.jsx)(r.td,{children:"\ud504\ub85c\uc81d\ud2b8\uc5d0 \uc774\ud574\uad00\uacc4\uc790\ub4e4\uc758 \uacf5\ud1b5\ub41c \uc5b8\uc5b4\ub85c, \uc11c\ub85c\uc758 \uc758\uc0ac\uc18c\ud1b5 \ube44\uc6a9\uc744 \uc904\uc774\uae30 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 \uc5b8\uc5b4"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc804\ub7b5\uc801 \uc124\uacc4"}),(0,n.jsx)(r.td,{children:"\ub3c4\uba54\uc778 \uc804\ubb38\uac00\uc640 \uac1c\ubc1c\uc790\uac00 \ud568\uaed8 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec \ub3c4\uba54\uc778\uacfc \uad00\ub828\ub41c \uc9c0\uc2dd\uc744 \uc774\ud574\ud558\uace0 \uc774\ub97c \ubc14\ud0d5\uc73c\ub85c \uacbd\uacc4\ub97c \ub098\ub220 \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc815\uc758\ud558\uace0, \ucee8\ud14d\uc2a4\ud2b8 \ub9f5\uc744 \uc0dd\uc131\ud558\ub294 \uac83\uc744 \ud3ec\ud568\ud558\ub294 \uacfc\uc815"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc804\uc220\uc801 \uc124\uacc4"}),(0,n.jsx)(r.td,{children:"\uc804\ub7b5\uc801 \uc124\uacc4\uc5d0\uc11c \uc815\uc758\ud55c \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\uc640 \ub3c4\uba54\uc778\uc744 \uc774\uc6a9\ud558\uc5ec \uc560\uadf8\ub9ac\uac70\ud2b8, Entity\uc640 VO, Repository \ub4f1\uc744 \uad6c\ud604\ud558\ub294 \uacfc\uc815"})]})]})]}),"\n",(0,n.jsx)(r.p,{children:"\uc774 \uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ub0b4\uc6a9\ub4e4\uc774 \ub098\uc654\uc9c0\ub9cc, \uc9c0\uc2dd\uc744 \uc81c\ub300\ub85c \ud761\uc218\ud558\uc9c0\ub294 \ubabb\ud588\ub2e4."}),"\n",(0,n.jsx)(r.h3,{id:"3-4\ub2e8\uacc4",children:"3, 4\ub2e8\uacc4"}),"\n",(0,n.jsx)(r.p,{children:"\uc81c\uc774\uc2a8\uc758 \uac15\uc758\ub97c \ub4e3\uace0, \uc870\uc601\ud638\ub2d8\uc758 \uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5 \uc720\ud29c\ube0c \uc601\uc0c1\uc744 \ubcf8 \ub2e4\uc74c 3, 4\ub2e8\uacc4\ub97c \uc9c4\ud589\ud588\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:"3\ub2e8\uacc4\ub294 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1\uc5d0 \uad00\ud55c \ub0b4\uc6a9\uc774\uc5c8\ub2e4. \ud074\ub798\uc2a4 \uac04 \ubc29\ud5a5, \ud328\ud0a4\uc9c0 \uac04 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc774 \ub418\ub3c4\ub85d \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud574\uc57c \ud588\uc5c8\ub2e4.\n\ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4\ub4e4\uc744 \ubb36\uace0, \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uae30 \uc704\ud574 \uc0dd\uba85\uc8fc\uae30\uac00 \ub2e4\ub974\ub2e4\uba74 id\ub97c \uc774\uc6a9\ud558\uc5ec \ucc38\uc870\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:"\uc758\uc874\uc131\uc744 \ubd84\ub9ac\ud558\uae30 \uc704\ud574 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4. \uc774\ubca4\ud2b8\ub294 \ud604\uc7ac \uae30\uc900\uc73c\ub85c \uacfc\uac70\uc5d0 \ubc8c\uc5b4\uc9c4 \uac83\uc744 \ud45c\ud604\ud558\uae30 \ub54c\ubb38\uc5d0 \uc774\ubca4\ud2b8\uba85\uc740 \uacfc\uac70 \uc2dc\uc81c\uac00 \ub418\uc5b4\uc57c\ud558\ub294 \uac83\uc744 \uc54c\uc558\ub2e4.\n\ucc98\uc74c\uc5d0\ub294 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud588\uc9c0\ub9cc, \uc11c\ube44\uc2a4 \ub85c\uc9c1\uc744 \ucd5c\ub300\ud55c \uac04\ub2e8\ud558\uac8c \ud558\uae30 \uc704\ud574 \ub3c4\uba54\uc778 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4."}),"\n",(0,n.jsxs)(r.p,{children:["4\ub2e8\uacc4\ub294 \uba40\ud2f0\ubaa8\ub4c8\ub85c \ubd84\ub9ac\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub294\ub370 3\ub2e8\uacc4\uc5d0\uc11c \ubd84\ub9ac\ud574\ub454 \ud328\ud0a4\uc9c0 \uadf8\ub300\ub85c \ubd84\ub9ac\ud558\uc9c0\ub294 \uc54a\uc558\ub2e4.",(0,n.jsx)(r.br,{}),"\n","3\ub2e8\uacc4\uc5d0\uc11c\ub294 \ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4 \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ud588\ub2e4. 4\ub2e8\uacc4\uc5d0\uc11c\ub294 \ub0b4\uac00 \uc778\uc2dd\ud558\uae30 \ud3b8\ud55c \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ub97c \ud588\ub2e4.\n\uc544\uc9c1 \ubd84\ub9ac\ud55c \uae30\uc900\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \ubaa8\ud638\ud588\uace0, \uc774\uc5d0 \ub300\ud55c \uacf5\ubd80\ub97c \uc870\uae08 \ub354 \ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.mermaid,{value:"graph LR\n\tsubgraph Table\n\t\tOrderTable --\x3e TableGroup\n\tend\n\tsubgraph Order\n\t\tO\n\tend\n O[Order] --\x3e OrderTable\n\tsubgraph Menu\n\t\tM[Menu] --\x3e MenuGroup\n\t\tM --\x3e Product\n\tend\n\tO --\x3e M"}),"\n",(0,n.jsxs)(r.p,{children:["\ucd94\uac00\ub85c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc704\ud55c \uc9c1\uc811 \uc791\uc131\ud55c ",(0,n.jsx)(r.code,{children:"@ServiceTest"})," \ucee4\uc2a4\ud140 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc788\uc5c8\ub294\ub370, \uc0c1\uc704 \ubaa8\ub4c8\uc758 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \ub9cc\ub4e0 \ud074\ub798\uc2a4\ub97c \ud558\uc704 \ubaa8\ub4c8\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4.\n\ub530\ub77c\uc11c TestFixtures\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\uacb0\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ub9c8\ubb34\ub9ac",children:"\ub9c8\ubb34\ub9ac"}),"\n",(0,n.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc758 \ub9c8\uc9c0\ub9c9 \ubbf8\uc158\uc774\ub2c8 \ub9cc\ud07c, \uac00\uc7a5 \ud765\ubbf8\ub85c\uc6b4 \ubbf8\uc158\uc774\uc5c8\uace0 \ubc30\uc6b8\uc810\ub3c4 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc14\uc05c \uae30\uac04\uc774\ub77c \ub9ce\uc740 \ub9ac\ubdf0\ub97c \ub0a8\uae30\uc9c0 \ubabb\ud588\ub358 \ub9ac\ubdf0\uc774 \ud638\uc774\uc5d0\uac8c \ubbf8\uc548\ud558\uace0, \ucf54\uba58\ud2b8 \uaf3c\uaf3c\ud558\uac8c \ub2ec\uc544\uc8fc\uace0 \ubbf8\uc158\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub3c4 \uc624\ud504\ub77c\uc778\uc73c\ub85c \ub9ce\uc774 \ub098\ub208 \ub9ac\ubdf0\uc5b4 \ud14c\uc624\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,n.jsxs)(r.p,{children:[(0,n.jsx)(r.a,{href:"https://www.youtube.com/watch?v=kmUneexSxk0",children:"\ub3c4\uba54\uc778 \uc6d0\uc815\ub300, \uc6b0\uc544\ucf58 2021"}),(0,n.jsx)(r.br,{}),"\n",(0,n.jsx)(r.a,{href:"https://www.youtube.com/watch?v=dJ5C4qRqAgA",children:"\uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5, \uc6b0\uc544\ud55c\ud14c\ud06c\uc138\ubbf8\ub098"}),(0,n.jsx)(r.br,{}),"\n",(0,n.jsx)(r.a,{href:"https://kwonnam.pe.kr/wiki/gradle/testfixtures",children:"TestFixtures, \uad8c\ub0a8\ub2d8"})]})]})}function h(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>a});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=n.createContext({}),a=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},d={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},h=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,h=o(e,["components","mdxType","originalType","parentName"]),p=a(t),u=s,j=p["".concat(l,".").concat(u)]||p[u]||d[u]||i;return t?n.createElement(j,c(c({ref:r},h),{},{components:t})):n.createElement(j,c({ref:r},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/1f05d14a.da3635f1.js b/assets/js/1f05d14a.f5451368.js similarity index 99% rename from assets/js/1f05d14a.da3635f1.js rename to assets/js/1f05d14a.f5451368.js index b89ba1072..50088cc94 100644 --- a/assets/js/1f05d14a.da3635f1.js +++ b/assets/js/1f05d14a.f5451368.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[656],{9938:(e,n,l)=>{l.r(n),l.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>u,toc:()=>d});var r=l(85893),t=l(3905),a=l(74866),s=l(85162);const i={title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",slug:"kotlin-null",tags:["Kotlin"]},o=void 0,u={permalink:"/kotlin-null",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",source:"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",description:"nullable \ud0c0\uc785",date:"2023-01-16T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 16\uc77c",tags:[{label:"Kotlin",permalink:"/tags/kotlin"}],readingTime:4.225,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",slug:"kotlin-null",tags:["Kotlin"]},unlisted:!1,prevItem:{title:"IntelliJ \uc124\uc815",permalink:"/intellij-settings"},nextItem:{title:"JSR-310",permalink:"/jsr-310"}},c={authorsImageUrls:[]},d=[{value:"nullable \ud0c0\uc785",id:"nullable-\ud0c0\uc785",level:3},{value:"?. Safe Calls \uc5f0\uc0b0\uc790",id:"-safe-calls-\uc5f0\uc0b0\uc790",level:3},{value:"?: \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790",id:"-\uc5d8\ube44\uc2a4-\uc5f0\uc0b0\uc790",level:3},{value:"!! \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790",id:"-\ub110-\uc544\ub2d8-\ub2e8\uc5b8-\uc5f0\uc0b0\uc790",level:3},{value:"as? \uc548\uc804\ud55c \uce90\uc2a4\ud305",id:"as-\uc548\uc804\ud55c-\uce90\uc2a4\ud305",level:3},{value:"List\uc5d0\uc11c\uc758 null \ucc98\ub9ac",id:"list\uc5d0\uc11c\uc758-null-\ucc98\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function h(e){const n={a:"a",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"nullable-\ud0c0\uc785",children:"nullable \ud0c0\uc785"}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc740 ",(0,r.jsx)(n.code,{children:"NullPointerException"})," \uc608\uc678\ub97c \ucd5c\ub300\ud55c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 \ud0c0\uc785 \uc2dc\uc2a4\ud15c\uc774 \uc124\uacc4\ub418\uc5b4 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ub294 \uc2e4\ud589 \uc2dc\uc810\uc774 \uc544\ub2cc \ucef4\ud30c\uc77c \uc2dc \ubbf8\ub9ac \uc624\ub958\uac00 \ubc1c\uc0dd\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub294 \ubd80\ubd84\uc744 \ubbf8\ub9ac \uac10\uc9c0\ud558\uc5ec NPE \ubc1c\uc0dd\uc758 \uac00\ub2a5\uc131\uc744 \uc904\uc5ec\uc900\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\ucf54\ud2c0\ub9b0\uc758 \uacbd\uc6b0 nullable \ud0c0\uc785\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val number: Int?\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc785 \ub4a4\uc5d0 ",(0,r.jsx)(n.code,{children:"?"}),"\ub97c \ubd99\uc5ec \ud574\ub2f9 \uac12\uc774 null\uc774 \ub420 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9cc\uc57d ",(0,r.jsx)(n.code,{children:"?"}),"\ub97c \ubd99\uc774\uc9c0 \uc54a\uc744 \ub54c null\uc744 \ubc1b\ub294 \uacbd\uc6b0 \ucef4\ud30c\uc77c \uc2dc \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(n.h3,{id:"-safe-calls-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"?."})," Safe Calls \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsx)(n.p,{children:"\uc790\ubc14\uc5d0\uc11c NPE\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 null\uc744 \ucc98\ub9ac\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c\ub294 \ubd84\uae30\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4."}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc740 \uc548\uc804\ud55c \ud638\ucd9c \uc5f0\uc0b0\uc790\uc778 ",(0,r.jsx)(n.code,{children:"?."})," \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ucc38\uc870 \uac12\uc774 null\uc774 \uc544\ub2d0 \uacbd\uc6b0\uc5d0\ub9cc \uba54\uc11c\ub4dc \ud638\ucd9c\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucc38\uc870 \uac12\uc774 null\uc778 \uacbd\uc6b0 \uba54\uc11c\ub4dc \ud638\ucd9c\uc774 \ubb34\uc2dc\ub418\uace0, null\uc744 \ubc18\ud658\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(s.Z,{value:"Java",label:"Java",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public String repeat(String word) {\n if (word == null) {\n return null;\n }\n return word.repeat(2);\n}\n"})})}),(0,r.jsx)(s.Z,{value:"Kotlin",label:"Kotlin",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"fun repeat(word: String?): String? {\n return word?.repeat(2)\n}\n"})})})]}),"\n",(0,r.jsxs)(n.h3,{id:"-\uc5d8\ube44\uc2a4-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"?:"})," \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsxs)(n.p,{children:["\ucc38\uc870\ud558\ub824\ub294 \uac12\uc774 null\uc77c \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud558\uace0 \uc2f6\uc744 \ub54c\ub294 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?",(0,r.jsx)(n.br,{}),"\n","\ucf54\ud2c0\ub9b0\uc740 null\uc774 \uc544\ub2cc \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \ub54c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(s.Z,{value:"Java",label:"Java",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public String stringSafe(String word) {\n if (word == null) {\n return "";\n }\n return word;\n}\n'})})}),(0,r.jsx)(s.Z,{value:"Kotlin",label:"Kotlin",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:'fun stringSafe(word: String?): String {\n return word ?: ""\n}\n'})})})]}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 throw\ub3c4 \uc2dd\uc774\uae30 \ub54c\ubb38\uc5d0 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 \uc0ac\uc6a9\uc790 \uc815\ubcf4\uac00 \uc788\ub294 \uc800\uc7a5\uc18c\uc5d0 \ucc3e\ub294 \uc0ac\uc6a9\uc790\uac00 \uc5c6\ub294 \uacbd\uc6b0 \uc544\ub798\uc640 \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"userRepository.findByName(name) ?: throw IllegalArgumentException()\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"-\ub110-\uc544\ub2d8-\ub2e8\uc5b8-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"!!"})," \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsxs)(n.p,{children:["!! \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud55c\ub2e4\uba74 \uac15\uc81c\ub85c \uc5b4\ub5a4 \uac12\uc774\ub4e0 non-nullable \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc null\uc778 \uac12\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4\uba74 NPE\uac00 \ubc1c\uc0dd\ud558\uac8c \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc77c\ubc18\uc801\uc778 \uacbd\uc6b0\uc5d0\ub294 !! \uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc704\ud5d8\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc0ac\uc6a9\ud558\uae30 \uc27d\uc9c0\ub9cc, \ub9ac\uc2a4\ud06c\uac00 \ud06c\uace0 \ud639\uc2dc\ub098 \ud574\ub2f9 \uac12\uc774 \ucd94\ud6c4\uc5d0\ub294 null\uc774 \ub420 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc591\ud574\uc57c \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val length: Int = word!!.length\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"as-\uc548\uc804\ud55c-\uce90\uc2a4\ud305",children:[(0,r.jsx)(n.code,{children:"as?"})," \uc548\uc804\ud55c \uce90\uc2a4\ud305"]}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \ub54c \uc9c0\uc815\ud55c \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc5c6\ub2e4\uba74 ",(0,r.jsx)(n.code,{children:"ClassCastException"}),"\uc774 \ubc1c\uc0dd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 as \ub4a4\uc5d0 ?\ub97c \ubd99\uc5ec \uc548\uc804\ud558\uac8c \ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ubbf8\ub9ac \ubcc0\ud658 \uac00\ub2a5\ud55c \ud0c0\uc785\uc778\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uace0, \uc548\uc804\ud558\uac8c \ud0c0\uc785\uc744 \ubcc0\ud658 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\ud0c0\uc785 \ubcc0\ud658\uc774 \ubd88\uac00\ub2a5 \ud560 \uacbd\uc6b0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uace0 null\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val value: Int? = something as? Int\n"})}),"\n",(0,r.jsx)(n.h3,{id:"list\uc5d0\uc11c\uc758-null-\ucc98\ub9ac",children:"List\uc5d0\uc11c\uc758 null \ucc98\ub9ac"}),"\n",(0,r.jsxs)(n.p,{children:["List\uc5d0\ub294 null\uc774 \uc544\ub2cc \uac12\ub9cc \ubc18\ud658\ud558\ub294 ",(0,r.jsx)(n.code,{children:"filterNotNull"})," \uc720\ud2f8\ub9ac\ud2f0 \uba54\uc11c\ub4dc\ub97c \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:'val foodsWithNull: List = listOf("Pizza", "Cheese", null, "Potato")\nval foods = foodsWithNull.filterNotNull()\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://product.kyobobook.co.kr/detail/S000001804588",children:"Kotlin in Action"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://product.kyobobook.co.kr/detail/S000001033129",children:"Effective Kotlin Item 8"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://www.baeldung.com/kotlin/null-safety",children:"Comprehensive Guide to Null Safety in Kotlin"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://kotlinlang.org/docs/null-safety.html",children:"Kotlin NullSafety"})}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,n,l)=>{l.d(n,{ah:()=>u});var r=l(67294);function t(e,n,l){return n in e?Object.defineProperty(e,n,{value:l,enumerable:!0,configurable:!0,writable:!0}):e[n]=l,e}function a(e,n){var l=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),l.push.apply(l,r)}return l}function s(e){for(var n=1;n=0||(t[l]=e[l]);return t}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,l)&&(t[l]=e[l])}return t}var o=r.createContext({}),u=function(e){var n=r.useContext(o),l=n;return e&&(l="function"==typeof e?e(n):s(s({},n),e)),l},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var l=e.components,t=e.mdxType,a=e.originalType,o=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),h=u(l),p=t,f=h["".concat(o,".").concat(p)]||h[p]||c[p]||a;return l?r.createElement(f,s(s({ref:n},d),{},{components:l})):r.createElement(f,s({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,l)=>{l.d(n,{Z:()=>s});l(67294);var r=l(86010);const t={tabItem:"tabItem_Ymn6"};var a=l(85893);function s(e){let{children:n,hidden:l,className:s}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.Z)(t.tabItem,s),hidden:l,children:n})}},74866:(e,n,l)=>{l.d(n,{Z:()=>w});var r=l(67294),t=l(86010),a=l(12466),s=l(16550),i=l(20469),o=l(91980),u=l(67392),c=l(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function h(e){const{values:n,children:l}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:l,attributes:r,default:t}}=e;return{value:n,label:l,attributes:r,default:t}}))}(l);return function(e){const n=(0,u.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,l])}function p(e){let{value:n,tabValues:l}=e;return l.some((e=>e.value===n))}function f(e){let{queryString:n=!1,groupId:l}=e;const t=(0,s.k6)(),a=function(e){let{queryString:n=!1,groupId:l}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!l)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return l??null}({queryString:n,groupId:l});return[(0,o._X)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(t.location.search);n.set(a,e),t.replace({...t.location,search:n.toString()})}),[a,t])]}function b(e){const{defaultValue:n,queryString:l=!1,groupId:t}=e,a=h(e),[s,o]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:l}=e;if(0===l.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:l}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${l.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=l.find((e=>e.default))??l[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[u,d]=f({queryString:l,groupId:t}),[b,j]=function(e){let{groupId:n}=e;const l=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,a]=(0,c.Nk)(l);return[t,(0,r.useCallback)((e=>{l&&a.set(e)}),[l,a])]}({groupId:t}),m=(()=>{const e=u??b;return p({value:e,tabValues:a})?e:null})();(0,i.Z)((()=>{m&&o(m)}),[m]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!p({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);o(e),d(e),j(e)}),[d,j,a]),tabValues:a}}var j=l(72389);const m={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=l(85893);function g(e){let{className:n,block:l,selectedValue:r,selectValue:s,tabValues:i}=e;const o=[],{blockElementScrollPositionUntilNextRender:u}=(0,a.o5)(),c=e=>{const n=e.currentTarget,l=o.indexOf(n),t=i[l].value;t!==r&&(u(n),s(t))},d=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const l=o.indexOf(e.currentTarget)+1;n=o[l]??o[0];break}case"ArrowLeft":{const l=o.indexOf(e.currentTarget)-1;n=o[l]??o[o.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.Z)("tabs",{"tabs--block":l},n),children:i.map((e=>{let{value:n,label:l,attributes:a}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>o.push(e),onKeyDown:d,onClick:c,...a,className:(0,t.Z)("tabs__item",m.tabItem,a?.className,{"tabs__item--active":r===n}),children:l??n},n)}))})}function v(e){let{lazy:n,children:l,selectedValue:t}=e;const a=(Array.isArray(l)?l:[l]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===t));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function y(e){const n=b(e);return(0,x.jsxs)("div",{className:(0,t.Z)("tabs-container",m.tabList),children:[(0,x.jsx)(g,{...e,...n}),(0,x.jsx)(v,{...e,...n})]})}function w(e){const n=(0,j.Z)();return(0,x.jsx)(y,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[656],{9938:(e,n,l)=>{l.r(n),l.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>u,toc:()=>d});var r=l(85893),t=l(3905),a=l(74866),s=l(85162);const i={title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",slug:"kotlin-null",tags:["Kotlin"]},o=void 0,u={permalink:"/kotlin-null",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",source:"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",description:"nullable \ud0c0\uc785",date:"2023-01-16T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 16\uc77c",tags:[{label:"Kotlin",permalink:"/tags/kotlin"}],readingTime:4.225,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",slug:"kotlin-null",tags:["Kotlin"]},unlisted:!1,prevItem:{title:"JSR-310",permalink:"/jsr-310"},nextItem:{title:"IntelliJ \uc124\uc815",permalink:"/intellij-settings"}},c={authorsImageUrls:[]},d=[{value:"nullable \ud0c0\uc785",id:"nullable-\ud0c0\uc785",level:3},{value:"?. Safe Calls \uc5f0\uc0b0\uc790",id:"-safe-calls-\uc5f0\uc0b0\uc790",level:3},{value:"?: \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790",id:"-\uc5d8\ube44\uc2a4-\uc5f0\uc0b0\uc790",level:3},{value:"!! \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790",id:"-\ub110-\uc544\ub2d8-\ub2e8\uc5b8-\uc5f0\uc0b0\uc790",level:3},{value:"as? \uc548\uc804\ud55c \uce90\uc2a4\ud305",id:"as-\uc548\uc804\ud55c-\uce90\uc2a4\ud305",level:3},{value:"List\uc5d0\uc11c\uc758 null \ucc98\ub9ac",id:"list\uc5d0\uc11c\uc758-null-\ucc98\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function h(e){const n={a:"a",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"nullable-\ud0c0\uc785",children:"nullable \ud0c0\uc785"}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc740 ",(0,r.jsx)(n.code,{children:"NullPointerException"})," \uc608\uc678\ub97c \ucd5c\ub300\ud55c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 \ud0c0\uc785 \uc2dc\uc2a4\ud15c\uc774 \uc124\uacc4\ub418\uc5b4 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ub294 \uc2e4\ud589 \uc2dc\uc810\uc774 \uc544\ub2cc \ucef4\ud30c\uc77c \uc2dc \ubbf8\ub9ac \uc624\ub958\uac00 \ubc1c\uc0dd\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub294 \ubd80\ubd84\uc744 \ubbf8\ub9ac \uac10\uc9c0\ud558\uc5ec NPE \ubc1c\uc0dd\uc758 \uac00\ub2a5\uc131\uc744 \uc904\uc5ec\uc900\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\ucf54\ud2c0\ub9b0\uc758 \uacbd\uc6b0 nullable \ud0c0\uc785\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val number: Int?\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc785 \ub4a4\uc5d0 ",(0,r.jsx)(n.code,{children:"?"}),"\ub97c \ubd99\uc5ec \ud574\ub2f9 \uac12\uc774 null\uc774 \ub420 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9cc\uc57d ",(0,r.jsx)(n.code,{children:"?"}),"\ub97c \ubd99\uc774\uc9c0 \uc54a\uc744 \ub54c null\uc744 \ubc1b\ub294 \uacbd\uc6b0 \ucef4\ud30c\uc77c \uc2dc \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(n.h3,{id:"-safe-calls-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"?."})," Safe Calls \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsx)(n.p,{children:"\uc790\ubc14\uc5d0\uc11c NPE\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 null\uc744 \ucc98\ub9ac\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c\ub294 \ubd84\uae30\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4."}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc740 \uc548\uc804\ud55c \ud638\ucd9c \uc5f0\uc0b0\uc790\uc778 ",(0,r.jsx)(n.code,{children:"?."})," \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ucc38\uc870 \uac12\uc774 null\uc774 \uc544\ub2d0 \uacbd\uc6b0\uc5d0\ub9cc \uba54\uc11c\ub4dc \ud638\ucd9c\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucc38\uc870 \uac12\uc774 null\uc778 \uacbd\uc6b0 \uba54\uc11c\ub4dc \ud638\ucd9c\uc774 \ubb34\uc2dc\ub418\uace0, null\uc744 \ubc18\ud658\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(s.Z,{value:"Java",label:"Java",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public String repeat(String word) {\n if (word == null) {\n return null;\n }\n return word.repeat(2);\n}\n"})})}),(0,r.jsx)(s.Z,{value:"Kotlin",label:"Kotlin",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"fun repeat(word: String?): String? {\n return word?.repeat(2)\n}\n"})})})]}),"\n",(0,r.jsxs)(n.h3,{id:"-\uc5d8\ube44\uc2a4-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"?:"})," \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsxs)(n.p,{children:["\ucc38\uc870\ud558\ub824\ub294 \uac12\uc774 null\uc77c \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud558\uace0 \uc2f6\uc744 \ub54c\ub294 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?",(0,r.jsx)(n.br,{}),"\n","\ucf54\ud2c0\ub9b0\uc740 null\uc774 \uc544\ub2cc \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \ub54c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(s.Z,{value:"Java",label:"Java",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public String stringSafe(String word) {\n if (word == null) {\n return "";\n }\n return word;\n}\n'})})}),(0,r.jsx)(s.Z,{value:"Kotlin",label:"Kotlin",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:'fun stringSafe(word: String?): String {\n return word ?: ""\n}\n'})})})]}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 throw\ub3c4 \uc2dd\uc774\uae30 \ub54c\ubb38\uc5d0 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 \uc0ac\uc6a9\uc790 \uc815\ubcf4\uac00 \uc788\ub294 \uc800\uc7a5\uc18c\uc5d0 \ucc3e\ub294 \uc0ac\uc6a9\uc790\uac00 \uc5c6\ub294 \uacbd\uc6b0 \uc544\ub798\uc640 \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"userRepository.findByName(name) ?: throw IllegalArgumentException()\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"-\ub110-\uc544\ub2d8-\ub2e8\uc5b8-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"!!"})," \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsxs)(n.p,{children:["!! \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud55c\ub2e4\uba74 \uac15\uc81c\ub85c \uc5b4\ub5a4 \uac12\uc774\ub4e0 non-nullable \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc null\uc778 \uac12\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4\uba74 NPE\uac00 \ubc1c\uc0dd\ud558\uac8c \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc77c\ubc18\uc801\uc778 \uacbd\uc6b0\uc5d0\ub294 !! \uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc704\ud5d8\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc0ac\uc6a9\ud558\uae30 \uc27d\uc9c0\ub9cc, \ub9ac\uc2a4\ud06c\uac00 \ud06c\uace0 \ud639\uc2dc\ub098 \ud574\ub2f9 \uac12\uc774 \ucd94\ud6c4\uc5d0\ub294 null\uc774 \ub420 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc591\ud574\uc57c \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val length: Int = word!!.length\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"as-\uc548\uc804\ud55c-\uce90\uc2a4\ud305",children:[(0,r.jsx)(n.code,{children:"as?"})," \uc548\uc804\ud55c \uce90\uc2a4\ud305"]}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \ub54c \uc9c0\uc815\ud55c \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc5c6\ub2e4\uba74 ",(0,r.jsx)(n.code,{children:"ClassCastException"}),"\uc774 \ubc1c\uc0dd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 as \ub4a4\uc5d0 ?\ub97c \ubd99\uc5ec \uc548\uc804\ud558\uac8c \ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ubbf8\ub9ac \ubcc0\ud658 \uac00\ub2a5\ud55c \ud0c0\uc785\uc778\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uace0, \uc548\uc804\ud558\uac8c \ud0c0\uc785\uc744 \ubcc0\ud658 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\ud0c0\uc785 \ubcc0\ud658\uc774 \ubd88\uac00\ub2a5 \ud560 \uacbd\uc6b0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uace0 null\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val value: Int? = something as? Int\n"})}),"\n",(0,r.jsx)(n.h3,{id:"list\uc5d0\uc11c\uc758-null-\ucc98\ub9ac",children:"List\uc5d0\uc11c\uc758 null \ucc98\ub9ac"}),"\n",(0,r.jsxs)(n.p,{children:["List\uc5d0\ub294 null\uc774 \uc544\ub2cc \uac12\ub9cc \ubc18\ud658\ud558\ub294 ",(0,r.jsx)(n.code,{children:"filterNotNull"})," \uc720\ud2f8\ub9ac\ud2f0 \uba54\uc11c\ub4dc\ub97c \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:'val foodsWithNull: List = listOf("Pizza", "Cheese", null, "Potato")\nval foods = foodsWithNull.filterNotNull()\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://product.kyobobook.co.kr/detail/S000001804588",children:"Kotlin in Action"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://product.kyobobook.co.kr/detail/S000001033129",children:"Effective Kotlin Item 8"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://www.baeldung.com/kotlin/null-safety",children:"Comprehensive Guide to Null Safety in Kotlin"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://kotlinlang.org/docs/null-safety.html",children:"Kotlin NullSafety"})}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,n,l)=>{l.d(n,{ah:()=>u});var r=l(67294);function t(e,n,l){return n in e?Object.defineProperty(e,n,{value:l,enumerable:!0,configurable:!0,writable:!0}):e[n]=l,e}function a(e,n){var l=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),l.push.apply(l,r)}return l}function s(e){for(var n=1;n=0||(t[l]=e[l]);return t}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,l)&&(t[l]=e[l])}return t}var o=r.createContext({}),u=function(e){var n=r.useContext(o),l=n;return e&&(l="function"==typeof e?e(n):s(s({},n),e)),l},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var l=e.components,t=e.mdxType,a=e.originalType,o=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),h=u(l),p=t,f=h["".concat(o,".").concat(p)]||h[p]||c[p]||a;return l?r.createElement(f,s(s({ref:n},d),{},{components:l})):r.createElement(f,s({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,l)=>{l.d(n,{Z:()=>s});l(67294);var r=l(86010);const t={tabItem:"tabItem_Ymn6"};var a=l(85893);function s(e){let{children:n,hidden:l,className:s}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.Z)(t.tabItem,s),hidden:l,children:n})}},74866:(e,n,l)=>{l.d(n,{Z:()=>w});var r=l(67294),t=l(86010),a=l(12466),s=l(16550),i=l(20469),o=l(91980),u=l(67392),c=l(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function h(e){const{values:n,children:l}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:l,attributes:r,default:t}}=e;return{value:n,label:l,attributes:r,default:t}}))}(l);return function(e){const n=(0,u.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,l])}function p(e){let{value:n,tabValues:l}=e;return l.some((e=>e.value===n))}function f(e){let{queryString:n=!1,groupId:l}=e;const t=(0,s.k6)(),a=function(e){let{queryString:n=!1,groupId:l}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!l)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return l??null}({queryString:n,groupId:l});return[(0,o._X)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(t.location.search);n.set(a,e),t.replace({...t.location,search:n.toString()})}),[a,t])]}function b(e){const{defaultValue:n,queryString:l=!1,groupId:t}=e,a=h(e),[s,o]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:l}=e;if(0===l.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:l}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${l.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=l.find((e=>e.default))??l[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[u,d]=f({queryString:l,groupId:t}),[b,j]=function(e){let{groupId:n}=e;const l=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,a]=(0,c.Nk)(l);return[t,(0,r.useCallback)((e=>{l&&a.set(e)}),[l,a])]}({groupId:t}),m=(()=>{const e=u??b;return p({value:e,tabValues:a})?e:null})();(0,i.Z)((()=>{m&&o(m)}),[m]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!p({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);o(e),d(e),j(e)}),[d,j,a]),tabValues:a}}var j=l(72389);const m={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=l(85893);function g(e){let{className:n,block:l,selectedValue:r,selectValue:s,tabValues:i}=e;const o=[],{blockElementScrollPositionUntilNextRender:u}=(0,a.o5)(),c=e=>{const n=e.currentTarget,l=o.indexOf(n),t=i[l].value;t!==r&&(u(n),s(t))},d=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const l=o.indexOf(e.currentTarget)+1;n=o[l]??o[0];break}case"ArrowLeft":{const l=o.indexOf(e.currentTarget)-1;n=o[l]??o[o.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.Z)("tabs",{"tabs--block":l},n),children:i.map((e=>{let{value:n,label:l,attributes:a}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>o.push(e),onKeyDown:d,onClick:c,...a,className:(0,t.Z)("tabs__item",m.tabItem,a?.className,{"tabs__item--active":r===n}),children:l??n},n)}))})}function v(e){let{lazy:n,children:l,selectedValue:t}=e;const a=(Array.isArray(l)?l:[l]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===t));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function y(e){const n=b(e);return(0,x.jsxs)("div",{className:(0,t.Z)("tabs-container",m.tabList),children:[(0,x.jsx)(g,{...e,...n}),(0,x.jsx)(v,{...e,...n})]})}function w(e){const n=(0,j.Z)();return(0,x.jsx)(y,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file diff --git a/assets/js/1f61820a.d2fe9ecf.js b/assets/js/1f61820a.6e34d588.js similarity index 97% rename from assets/js/1f61820a.d2fe9ecf.js rename to assets/js/1f61820a.6e34d588.js index eb01871d3..027e98ab2 100644 --- a/assets/js/1f61820a.d2fe9ecf.js +++ b/assets/js/1f61820a.6e34d588.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2233],{74123:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var t=r(85893),s=r(3905);const a={title:"Parameterized Tests",slug:"parameterized-tests",tags:["Java"]},i=void 0,l={permalink:"/parameterized-tests",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-12-Parameterized Tests.mdx",source:"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx",title:"Parameterized Tests",description:"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.",date:"2023-02-12T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 12\uc77c",tags:[{label:"Java",permalink:"/tags/java"}],readingTime:3.17,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Parameterized Tests",slug:"parameterized-tests",tags:["Java"]},unlisted:!1,prevItem:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",permalink:"/racing-car-retrospective"},nextItem:{title:"IntelliJ \uc124\uc815",permalink:"/intellij-settings"}},c={authorsImageUrls:[]},u=[{value:"Argument Sources",id:"argument-sources",level:2},{value:"Value Source",id:"value-source",level:3},{value:"Null & Empty Source",id:"null--empty-source",level:3},{value:"Enum Source",id:"enum-source",level:3},{value:"CSV Source",id:"csv-source",level:3},{value:"Method Source",id:"method-source",level:3},{value:"ETC.",id:"etc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function o(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ub54c ",(0,t.jsx)(n.code,{children:"@ParameterizedTest"}),"\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e8\uc77c \ud14c\uc2a4\ud2b8\ub97c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \ubc88 \ubc18\ubcf5\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.h2,{id:"argument-sources",children:"Argument Sources"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@ParameterizedTest"}),"\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 Source \uc560\ub178\ud14c\uc774\uc158\uc774 \ud544\uc694\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","JUnit\uc774 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c Source\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0, \ud14c\uc2a4\ud2b8\uc5d0 \ub9de\ucdb0 \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"value-source",children:"Value Source"}),"\n",(0,t.jsx)(n.p,{children:"\uac12\uc744 \uc774\uc6a9\ud558\uc5ec \uc81c\uacf5\ud558\ub294 \ud615\ud0dc\ub85c, \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"short, int, long, float, double"}),"\n",(0,t.jsx)(n.li,{children:"byte, char, boolean, String, Class"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@ValueSource(ints = {1, 100, Integer.MAX_VALUE})\nvoid valueTest(final int value) {\n Assertions.assertThat(value).isPositive();\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"null--empty-source",children:"Null & Empty Source"}),"\n",(0,t.jsxs)(n.p,{children:["null \uac12, \ube48 \uac12\uc744 \uc81c\uacf5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Empty Source\uc758 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc5d0 \ud55c\ud574 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"String"}),"\n",(0,t.jsx)(n.li,{children:"java.util.List, java.util.Set, java.util.Map"}),"\n",(0,t.jsx)(n.li,{children:"primitive arrays \u2014 ex) int[]"}),"\n",(0,t.jsx)(n.li,{children:"object arrays \u2014 ex) String[]"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@NullAndEmptySource\nvoid nullAndEmptyTest(final String value) {\n Assertions.assertThat(value).isNullOrEmpty();\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"enum-source",children:"Enum Source"}),"\n",(0,t.jsx)(n.p,{children:"EnumSource\ub97c \uc774\uc6a9\ud558\uc5ec Enum \ub610\ud55c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"enum Day {\n MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n}\n\n@ParameterizedTest\n@EnumSource(Day.class)\nvoid enumTest(final Day day) {\n assertThat(day).isInstanceOf(Day.class);\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 mode \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b9\uc9d5 Enum\uc744 \uc81c\uc678\ud558\uac70\ub098, \ud3ec\ud568\uc2dc\ud0ac \uc218 \uc788\ub2e4. (default: Mode.Include)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@ParameterizedTest\n@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)\nvoid enumTest(final Day day) {\n // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\n assertThat(day).isInstanceOf(Day.class);\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"csv-source",children:"CSV Source"}),"\n",(0,t.jsxs)(n.p,{children:["csv \ud615\uc2dd\uc758 \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uad6c\ubd84\uc790\uc758 \uae30\ubcf8\uac12\uc740 \uc27c\ud45c(,)\ub85c \uad6c\ubd84\uc790\ub97c \ubcc0\uacbd\ud558\uace0 \uc2f6\uc744 \ub550 delimeter \uac12\uc744 \ub530\ub85c \uc804\ub2ec\ud558\uc5ec \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\n\uac1c\uc778\uc801\uc73c\ub85c 2\uac1c \uc815\ub3c4\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ud558\ub294 \uacbd\uc6b0 CsvSource\ub97c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@ParameterizedTest\n@CsvSource({"1,1", "2,4", "3,9", "4,16"})\nvoid csvTest(final int number, final int result) {\n assertThat(number * number).isEqualTo(result);\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"method-source",children:"Method Source"}),"\n",(0,t.jsxs)(n.p,{children:["\ubcf5\uc7a1\ud55c \ud0c0\uc785\uc758 \uac12\uc744 \uc804\ub2ec\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc\uba85\uc744 \uc785\ub825\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc\uba85\uc744 \ub530\ub85c \uc785\ub825\ud558\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uba85\uacfc \ub3d9\uc77c\ud55c static \uba54\uc11c\ub4dc\uac00 \uc9c0\uc815\ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@MethodSource\nvoid methodTest(final List numbers, final int count) {\n assertThat(numbers).hasSize(count);\n}\n\nprivate static Stream methodTest() {\n return Stream.of(\n Arguments.of(List.of(1), 1),\n Arguments.of(List.of(1, 2), 2),\n Arguments.of(List.of(1, 2, 3), 3)\n );\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"etc",children:"ETC."}),"\n",(0,t.jsx)(n.p,{children:"\uc704\uc5d0\uc11c \uc5b8\uae09\ud55c \ubc29\ubc95 \uc774\uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ubc29\ubc95\uc73c\ub85c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"CSV \ud30c\uc77c\uc744 \uc774\uc6a9\ud55c CsvFileSource"}),"\n",(0,t.jsx)(n.li,{children:"ArgumentsProvider \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \uc774\uc6a9\ud558\ub294 ArgumentsSource"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.baeldung.com/parameterized-tests-junit-5",children:"Guide to JUnit 5 Parameterized Tests"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(o,{...e})}):o(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>u});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var c=t.createContext({}),u=function(e){var n=t.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},o={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,a=e.originalType,c=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),m=u(r),h=s,p=m["".concat(c,".").concat(h)]||m[h]||o[h]||a;return r?t.createElement(p,i(i({ref:n},d),{},{components:r})):t.createElement(p,i({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2233],{74123:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var t=r(85893),s=r(3905);const a={title:"Parameterized Tests",slug:"parameterized-tests",tags:["Java"]},i=void 0,l={permalink:"/parameterized-tests",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-12-Parameterized Tests.mdx",source:"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx",title:"Parameterized Tests",description:"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.",date:"2023-02-12T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 12\uc77c",tags:[{label:"Java",permalink:"/tags/java"}],readingTime:3.17,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Parameterized Tests",slug:"parameterized-tests",tags:["Java"]},unlisted:!1,prevItem:{title:"IntelliJ \uc124\uc815",permalink:"/intellij-settings"},nextItem:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",permalink:"/racing-car-retrospective"}},c={authorsImageUrls:[]},u=[{value:"Argument Sources",id:"argument-sources",level:2},{value:"Value Source",id:"value-source",level:3},{value:"Null & Empty Source",id:"null--empty-source",level:3},{value:"Enum Source",id:"enum-source",level:3},{value:"CSV Source",id:"csv-source",level:3},{value:"Method Source",id:"method-source",level:3},{value:"ETC.",id:"etc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function o(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ub54c ",(0,t.jsx)(n.code,{children:"@ParameterizedTest"}),"\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e8\uc77c \ud14c\uc2a4\ud2b8\ub97c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \ubc88 \ubc18\ubcf5\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.h2,{id:"argument-sources",children:"Argument Sources"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@ParameterizedTest"}),"\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 Source \uc560\ub178\ud14c\uc774\uc158\uc774 \ud544\uc694\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","JUnit\uc774 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c Source\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0, \ud14c\uc2a4\ud2b8\uc5d0 \ub9de\ucdb0 \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"value-source",children:"Value Source"}),"\n",(0,t.jsx)(n.p,{children:"\uac12\uc744 \uc774\uc6a9\ud558\uc5ec \uc81c\uacf5\ud558\ub294 \ud615\ud0dc\ub85c, \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"short, int, long, float, double"}),"\n",(0,t.jsx)(n.li,{children:"byte, char, boolean, String, Class"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@ValueSource(ints = {1, 100, Integer.MAX_VALUE})\nvoid valueTest(final int value) {\n Assertions.assertThat(value).isPositive();\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"null--empty-source",children:"Null & Empty Source"}),"\n",(0,t.jsxs)(n.p,{children:["null \uac12, \ube48 \uac12\uc744 \uc81c\uacf5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Empty Source\uc758 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc5d0 \ud55c\ud574 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"String"}),"\n",(0,t.jsx)(n.li,{children:"java.util.List, java.util.Set, java.util.Map"}),"\n",(0,t.jsx)(n.li,{children:"primitive arrays \u2014 ex) int[]"}),"\n",(0,t.jsx)(n.li,{children:"object arrays \u2014 ex) String[]"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@NullAndEmptySource\nvoid nullAndEmptyTest(final String value) {\n Assertions.assertThat(value).isNullOrEmpty();\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"enum-source",children:"Enum Source"}),"\n",(0,t.jsx)(n.p,{children:"EnumSource\ub97c \uc774\uc6a9\ud558\uc5ec Enum \ub610\ud55c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"enum Day {\n MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n}\n\n@ParameterizedTest\n@EnumSource(Day.class)\nvoid enumTest(final Day day) {\n assertThat(day).isInstanceOf(Day.class);\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 mode \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b9\uc9d5 Enum\uc744 \uc81c\uc678\ud558\uac70\ub098, \ud3ec\ud568\uc2dc\ud0ac \uc218 \uc788\ub2e4. (default: Mode.Include)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@ParameterizedTest\n@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)\nvoid enumTest(final Day day) {\n // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\n assertThat(day).isInstanceOf(Day.class);\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"csv-source",children:"CSV Source"}),"\n",(0,t.jsxs)(n.p,{children:["csv \ud615\uc2dd\uc758 \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uad6c\ubd84\uc790\uc758 \uae30\ubcf8\uac12\uc740 \uc27c\ud45c(,)\ub85c \uad6c\ubd84\uc790\ub97c \ubcc0\uacbd\ud558\uace0 \uc2f6\uc744 \ub550 delimeter \uac12\uc744 \ub530\ub85c \uc804\ub2ec\ud558\uc5ec \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\n\uac1c\uc778\uc801\uc73c\ub85c 2\uac1c \uc815\ub3c4\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ud558\ub294 \uacbd\uc6b0 CsvSource\ub97c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@ParameterizedTest\n@CsvSource({"1,1", "2,4", "3,9", "4,16"})\nvoid csvTest(final int number, final int result) {\n assertThat(number * number).isEqualTo(result);\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"method-source",children:"Method Source"}),"\n",(0,t.jsxs)(n.p,{children:["\ubcf5\uc7a1\ud55c \ud0c0\uc785\uc758 \uac12\uc744 \uc804\ub2ec\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc\uba85\uc744 \uc785\ub825\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc\uba85\uc744 \ub530\ub85c \uc785\ub825\ud558\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uba85\uacfc \ub3d9\uc77c\ud55c static \uba54\uc11c\ub4dc\uac00 \uc9c0\uc815\ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@MethodSource\nvoid methodTest(final List numbers, final int count) {\n assertThat(numbers).hasSize(count);\n}\n\nprivate static Stream methodTest() {\n return Stream.of(\n Arguments.of(List.of(1), 1),\n Arguments.of(List.of(1, 2), 2),\n Arguments.of(List.of(1, 2, 3), 3)\n );\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"etc",children:"ETC."}),"\n",(0,t.jsx)(n.p,{children:"\uc704\uc5d0\uc11c \uc5b8\uae09\ud55c \ubc29\ubc95 \uc774\uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ubc29\ubc95\uc73c\ub85c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"CSV \ud30c\uc77c\uc744 \uc774\uc6a9\ud55c CsvFileSource"}),"\n",(0,t.jsx)(n.li,{children:"ArgumentsProvider \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \uc774\uc6a9\ud558\ub294 ArgumentsSource"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.baeldung.com/parameterized-tests-junit-5",children:"Guide to JUnit 5 Parameterized Tests"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(o,{...e})}):o(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>u});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var c=t.createContext({}),u=function(e){var n=t.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},o={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,a=e.originalType,c=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),m=u(r),h=s,p=m["".concat(c,".").concat(h)]||m[h]||o[h]||a;return r?t.createElement(p,i(i({ref:n},d),{},{components:r})):t.createElement(p,i({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/21294bbb.58721559.js b/assets/js/21294bbb.f9fbadbd.js similarity index 97% rename from assets/js/21294bbb.58721559.js rename to assets/js/21294bbb.f9fbadbd.js index 3f7913798..f74923535 100644 --- a/assets/js/21294bbb.58721559.js +++ b/assets/js/21294bbb.f9fbadbd.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9412],{72794:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>o,default:()=>u,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var t=n(85893),s=n(3905);const c={title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",slug:"web-racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,a={permalink:"/web-racing-car-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-racingcar/pull/24",date:"2023-05-02T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 2\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.6,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",slug:"web-racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",permalink:"/shopping-cart-retrospective"},nextItem:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",permalink:"/tecochat-retrospective-2"}},i={authorsImageUrls:[]},l=[{value:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158",id:"\uc6f9-\uc790\ub3d9\ucc28-\ubbf8\uc158",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-racingcar/pull/24",children:"https://github.com/woowacourse/jwp-racingcar/pull/24"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-racingcar/pull/128",children:"https://github.com/woowacourse/jwp-racingcar/pull/128"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\uc6f9-\uc790\ub3d9\ucc28-\ubbf8\uc158",children:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158"}),"\n",(0,t.jsxs)(r.p,{children:["\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud55c\ub2e4\uace0 \uc2dc\uac04\uc774 \ub9ce\uc774 \uc5c6\uc5b4\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc84c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\uc5d0\uc11c\ub294 \ube44\ubc84\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub808\ubca8 2\uc5d0\uc11c \uc9c4\ud589\ud558\ub294 \uccab \ubbf8\uc158\uc774\ub77c \ub9ce\uc774 \uae34\uc7a5\ub418\uc5c8\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ube44\ubc84\ub791 \ucd08\ubc18\uc5d0 \ub9db\uc788\ub294 \uac83\ub3c4 \ub9ce\uc774 \uba39\uc73c\uba74\uc11c \ube68\ub9ac \uce5c\ud574\uc838\uc11c \uc7ac\ubc0c\uac8c \ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc2a4\ud504\ub9c1\uc744 \uc870\uae08 \uc0ac\uc6a9\ud560 \uc904 \uc54c\uc544\uc11c, \ube44\ubc84\ub791 \uac19\uc774 \ud559\uc2b5\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uccab \ubbf8\uc158\uc774\ub77c \uadf8\ub7f0\uc9c0 \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc740 \uc5c6\uc5c8\uace0, \ucd5c\ub300\ud55c \uae54\ub054\ud558\uac8c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub09c\uc774\ub3c4 \ub192\uc740 \ubbf8\uc158\uc774 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ub9ac\ubdf0\uc5b4\uc778 \ub77c\ube48\uc5d0\uac8c \uce6d\ucc2c\uc744 \ub9ce\uc774 \ubc1b\uc544\uc11c \uae30\ubd84\uc774 \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub77c\ube48 \uac10\uc0ac\ud569\ub2c8\ub2e4!"]}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\ucee8\ub514\uc158\ub3c4 \uc88b\uc9c0 \uc54a\uace0 \uc5f4\uc815\ub3c4 \uc2dd\uc740 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc774 \ub2e4\uc18c \uc5ec\uc720\ub86d\ub2e4\uace0 \ub290\uaef4\uc838\uc11c, \uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ubd84\ub3c4 \uc798 \uad00\ub9ac\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud574\uc11c \ud398\uc5b4\uc5d0\uac8c \ub9ce\uc774 \ubbf8\uc548\ud588\uace0, \ub098 \uc790\uc2e0\uc5d0\uac8c \uc544\uc26c\uc6e0\ub358 \ubd80\ubd84\uc774 \ub9ce\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc9c0\ub09c\ubc88 \ud68c\uace0\ub97c \ub2e4\uc2dc \ubcf4\ub294\ub370 \uc9d1\uc911\uc744 \uc798 \ubabb\ud55c \uacbd\uc6b0\uac00 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub3c4\uc804\uc801\uc774\uc9c0 \uc54a\uac70\ub098 \uc2dc\uac04\uc774 \ubd80\uc871\ud558\uc9c0 \uc54a\uc73c\uba74 \uc9d1\uc911\uc744 \uc798 \ubabb\ud558\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uba38\ub9bf\uc18d\uc5d0\uc11c \uc2dc\uac04\uc801 \uc5ec\uc720\uac00 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \ub54c\uac00 \uac00\uc7a5 \uc704\ud5d8\ud55c \uc21c\uac04\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ud568\uaed8 \uc790\ub77c\uae30\uc5d0\uc11c \ub098\uc628 ",(0,t.jsx)(r.code,{children:"\ub09c\uc774\ub3c4 \ub192\uc774\uae30"}),"\uac00 \ud544\uc694\ud574\uc9c0\ub294 \uc21c\uac04\uc774\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc911\uc694\ub3c4\uac00 \uc788\ub294 \uc5b4\ub178\ud14c\uc774\uc158\ubd80\ud130 \ud074\ub798\uc2a4 \uc774\ub984\uc5d0 \uac00\uae5d\uac8c \uba85\uc2dc\ud558\uae30"})}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'@SuppressWarnings("NonAsciiCharacters")\n@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)\n@Transactional\n@AutoConfigureMockMvc\n@SpringBootTest\npublic class RacingGameIntegrationTest {\n'})}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ube44\ubc84\uc758 \uc131\uaca9"}),(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uac00 \uc131\uaca9\uc774 \uc88b\uc544\uc11c \ud3b8\ud558\uac8c \ud398\uc5b4\ub97c \ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc131\uae09\ud558\uc9c0 \uc54a\uace0 \uc5ec\uc720\ub85c\uc6cc\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ubbf8\uc158\uc5d0 \uc9d1\uc911\ud558\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud588\ub294\ub370\ub3c4 \uac19\uc774 \ud398\uc5b4\ub97c \uc798 \uc9c4\ud589\ud55c \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud574\uc11c \uadf8\ub807\uc9c0 \uc54a\uc558\ub098 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadfc\uc721\ub9e8 \ube44\ubc84\ub77c \uadf8\ub7f0\uc9c0 \uccb4\ub825\uc774 \uc88b\uc544\uc11c \uadf8\ub7f0\uac00?",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04\uc5d0 \uc798 \uc548 \uc26c\uace0\ub3c4 \uc9d1\uc911\ud574\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac78 \ubcf4\uace0 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ud559\uc2b5\uc5d0 \ub300\ud55c \uc5f4\uc815"}),(0,t.jsx)(r.br,{}),"\n","\ucd94\uac00\uc801\uc73c\ub85c \uc54c\uace0 \uc2f6\uc740 \ubd80\ubd84\uc744 \ub530\ub85c \ud559\uc2b5\ud558\ub294 \uc5f4\uc815\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uc640 \uc2a4\ud504\ub9c1\uc5d0 \ub300\ud574 \uc54c\uc544\uac00\ub294 \uc2dc\uac04\uc744 \ub9ce\uc774 \uac00\uc9c4 \ubd80\ubd84\uc774 \ub9e4\uc6b0 \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 5\uc6d4\ubd80\ud130 \uc870\uae08 \ub354 \ud654\uc774\ud305 \ud574\uc57c\uaca0\ub2e4."]})]})}function u(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function c(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),l=function(e){var r=t.useContext(i),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},u=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,c=e.originalType,i=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),h=l(n),j=s,d=h["".concat(i,".").concat(j)]||h[j]||p[j]||c;return n?t.createElement(d,o(o({ref:r},u),{},{components:n})):t.createElement(d,o({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9412],{72794:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>o,default:()=>u,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var t=n(85893),s=n(3905);const c={title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",slug:"web-racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,a={permalink:"/web-racing-car-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-racingcar/pull/24",date:"2023-05-02T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 2\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.6,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",slug:"web-racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",permalink:"/tecochat-retrospective-2"},nextItem:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",permalink:"/shopping-cart-retrospective"}},i={authorsImageUrls:[]},l=[{value:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158",id:"\uc6f9-\uc790\ub3d9\ucc28-\ubbf8\uc158",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-racingcar/pull/24",children:"https://github.com/woowacourse/jwp-racingcar/pull/24"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-racingcar/pull/128",children:"https://github.com/woowacourse/jwp-racingcar/pull/128"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\uc6f9-\uc790\ub3d9\ucc28-\ubbf8\uc158",children:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158"}),"\n",(0,t.jsxs)(r.p,{children:["\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud55c\ub2e4\uace0 \uc2dc\uac04\uc774 \ub9ce\uc774 \uc5c6\uc5b4\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc84c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\uc5d0\uc11c\ub294 \ube44\ubc84\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub808\ubca8 2\uc5d0\uc11c \uc9c4\ud589\ud558\ub294 \uccab \ubbf8\uc158\uc774\ub77c \ub9ce\uc774 \uae34\uc7a5\ub418\uc5c8\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ube44\ubc84\ub791 \ucd08\ubc18\uc5d0 \ub9db\uc788\ub294 \uac83\ub3c4 \ub9ce\uc774 \uba39\uc73c\uba74\uc11c \ube68\ub9ac \uce5c\ud574\uc838\uc11c \uc7ac\ubc0c\uac8c \ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc2a4\ud504\ub9c1\uc744 \uc870\uae08 \uc0ac\uc6a9\ud560 \uc904 \uc54c\uc544\uc11c, \ube44\ubc84\ub791 \uac19\uc774 \ud559\uc2b5\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uccab \ubbf8\uc158\uc774\ub77c \uadf8\ub7f0\uc9c0 \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc740 \uc5c6\uc5c8\uace0, \ucd5c\ub300\ud55c \uae54\ub054\ud558\uac8c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub09c\uc774\ub3c4 \ub192\uc740 \ubbf8\uc158\uc774 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ub9ac\ubdf0\uc5b4\uc778 \ub77c\ube48\uc5d0\uac8c \uce6d\ucc2c\uc744 \ub9ce\uc774 \ubc1b\uc544\uc11c \uae30\ubd84\uc774 \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub77c\ube48 \uac10\uc0ac\ud569\ub2c8\ub2e4!"]}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\ucee8\ub514\uc158\ub3c4 \uc88b\uc9c0 \uc54a\uace0 \uc5f4\uc815\ub3c4 \uc2dd\uc740 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc774 \ub2e4\uc18c \uc5ec\uc720\ub86d\ub2e4\uace0 \ub290\uaef4\uc838\uc11c, \uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ubd84\ub3c4 \uc798 \uad00\ub9ac\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud574\uc11c \ud398\uc5b4\uc5d0\uac8c \ub9ce\uc774 \ubbf8\uc548\ud588\uace0, \ub098 \uc790\uc2e0\uc5d0\uac8c \uc544\uc26c\uc6e0\ub358 \ubd80\ubd84\uc774 \ub9ce\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc9c0\ub09c\ubc88 \ud68c\uace0\ub97c \ub2e4\uc2dc \ubcf4\ub294\ub370 \uc9d1\uc911\uc744 \uc798 \ubabb\ud55c \uacbd\uc6b0\uac00 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub3c4\uc804\uc801\uc774\uc9c0 \uc54a\uac70\ub098 \uc2dc\uac04\uc774 \ubd80\uc871\ud558\uc9c0 \uc54a\uc73c\uba74 \uc9d1\uc911\uc744 \uc798 \ubabb\ud558\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uba38\ub9bf\uc18d\uc5d0\uc11c \uc2dc\uac04\uc801 \uc5ec\uc720\uac00 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \ub54c\uac00 \uac00\uc7a5 \uc704\ud5d8\ud55c \uc21c\uac04\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ud568\uaed8 \uc790\ub77c\uae30\uc5d0\uc11c \ub098\uc628 ",(0,t.jsx)(r.code,{children:"\ub09c\uc774\ub3c4 \ub192\uc774\uae30"}),"\uac00 \ud544\uc694\ud574\uc9c0\ub294 \uc21c\uac04\uc774\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc911\uc694\ub3c4\uac00 \uc788\ub294 \uc5b4\ub178\ud14c\uc774\uc158\ubd80\ud130 \ud074\ub798\uc2a4 \uc774\ub984\uc5d0 \uac00\uae5d\uac8c \uba85\uc2dc\ud558\uae30"})}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'@SuppressWarnings("NonAsciiCharacters")\n@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)\n@Transactional\n@AutoConfigureMockMvc\n@SpringBootTest\npublic class RacingGameIntegrationTest {\n'})}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ube44\ubc84\uc758 \uc131\uaca9"}),(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uac00 \uc131\uaca9\uc774 \uc88b\uc544\uc11c \ud3b8\ud558\uac8c \ud398\uc5b4\ub97c \ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc131\uae09\ud558\uc9c0 \uc54a\uace0 \uc5ec\uc720\ub85c\uc6cc\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ubbf8\uc158\uc5d0 \uc9d1\uc911\ud558\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud588\ub294\ub370\ub3c4 \uac19\uc774 \ud398\uc5b4\ub97c \uc798 \uc9c4\ud589\ud55c \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud574\uc11c \uadf8\ub807\uc9c0 \uc54a\uc558\ub098 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadfc\uc721\ub9e8 \ube44\ubc84\ub77c \uadf8\ub7f0\uc9c0 \uccb4\ub825\uc774 \uc88b\uc544\uc11c \uadf8\ub7f0\uac00?",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04\uc5d0 \uc798 \uc548 \uc26c\uace0\ub3c4 \uc9d1\uc911\ud574\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac78 \ubcf4\uace0 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ud559\uc2b5\uc5d0 \ub300\ud55c \uc5f4\uc815"}),(0,t.jsx)(r.br,{}),"\n","\ucd94\uac00\uc801\uc73c\ub85c \uc54c\uace0 \uc2f6\uc740 \ubd80\ubd84\uc744 \ub530\ub85c \ud559\uc2b5\ud558\ub294 \uc5f4\uc815\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uc640 \uc2a4\ud504\ub9c1\uc5d0 \ub300\ud574 \uc54c\uc544\uac00\ub294 \uc2dc\uac04\uc744 \ub9ce\uc774 \uac00\uc9c4 \ubd80\ubd84\uc774 \ub9e4\uc6b0 \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 5\uc6d4\ubd80\ud130 \uc870\uae08 \ub354 \ud654\uc774\ud305 \ud574\uc57c\uaca0\ub2e4."]})]})}function u(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function c(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),l=function(e){var r=t.useContext(i),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},u=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,c=e.originalType,i=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),h=l(n),j=s,d=h["".concat(i,".").concat(j)]||h[j]||p[j]||c;return n?t.createElement(d,o(o({ref:r},u),{},{components:n})):t.createElement(d,o({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/24b9bc70.6793a550.js b/assets/js/24b9bc70.d6ffdb3f.js similarity index 97% rename from assets/js/24b9bc70.6793a550.js rename to assets/js/24b9bc70.d6ffdb3f.js index 0f5fef603..ec6deea35 100644 --- a/assets/js/24b9bc70.6793a550.js +++ b/assets/js/24b9bc70.d6ffdb3f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5798],{58346:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var r=n(85893),s=n(3905);const i={title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",slug:"test-double",tags:["Test","Mock"]},l=void 0,c={permalink:"/test-double",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",source:"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",description:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?",date:"2023-04-04T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 4\uc77c",tags:[{label:"Test",permalink:"/tags/test"},{label:"Mock",permalink:"/tags/mock"}],readingTime:4.52,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",slug:"test-double",tags:["Test","Mock"]},unlisted:!1,prevItem:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",permalink:"/transaction-and-isolation"},nextItem:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",permalink:"/java-class-file"}},d={authorsImageUrls:[]},o=[{value:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?",id:"\ud14c\uc2a4\ud2b8-\ub300\uc5ed\uc774\ub780",level:3},{value:"\ub354\ubbf8(Dummy)",id:"\ub354\ubbf8dummy",level:3},{value:"\uc2a4\ud141(Stub)",id:"\uc2a4\ud141stub",level:3},{value:"\uc2a4\ud30c\uc774(Spy)",id:"\uc2a4\ud30c\uc774spy",level:3},{value:"\ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)",id:"\ubaa9-\ubaa8\uc758-\uac1d\uccb4mock",level:3},{value:"\uac00\uc9dc(Fake)",id:"\uac00\uc9dcfake",level:3},{value:"\uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84",id:"\uc0c1\ud638\uc791\uc6a9\uc5d0-\ub530\ub978-\ubaa9\uacfc-\uc2a4\ud141-\uad6c\ubd84",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function a(e){const t={a:"a",admonition:"admonition",br:"br",h3:"h3",mermaid:"mermaid",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\ud14c\uc2a4\ud2b8-\ub300\uc5ed\uc774\ub780",children:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?"}),"\n",(0,r.jsxs)(t.p,{children:["\ubaa8\ub4e0 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \uac00\uc9dc \uc758\uc874\uc131\uc744 \uc758\ubbf8\ud558\uace0, \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud589\ub420 \ub54c \ub2e4\ub978 \uac1d\uccb4\ub97c \ub300\uc2e0\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Gerard Meszaros\uc758 xUnit Test Patterns\ub77c\ub294 \ucc45\uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ub2e4\uc12f \uac00\uc9c0(\ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774, \ubaa9, \ud398\uc774\ud06c)\ub85c \uad6c\ubd84\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \uae30\ubcf8 \uba54\ucee4\ub2c8\uc998\uc740 \ub2e4\ud615\uc131\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc678\ubd80 \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uacbd\uc6b0, \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uace0 \uc678\ubd80 \uc11c\ube44\uc2a4 \ub300\uc2e0 \ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\uc758 \uad6c\ud604\uccb4\ub97c \uc0dd\uc131\ud558\ub294 \uac83\uc774\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.strong,{children:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \ud0c0\uc785 \uacc4\uce35 \uad6c\uc870"})}),"\n",(0,r.jsx)(t.mermaid,{value:"flowchart LR\n Mock --\x3e Spy --\x3e Stub --\x3e Dummy --\x3e TestDouble\n Fake --\x3e TestDouble"}),"\n",(0,r.jsx)(t.h3,{id:"\ub354\ubbf8dummy",children:"\ub354\ubbf8(Dummy)"}),"\n",(0,r.jsxs)(t.p,{children:["\uac00\uc7a5 \ub2e8\uc21c\ud558\uace0, \uc6d0\uc2dc\uc801\uc778 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c \uc544\ubb34 \uc77c\ub3c4 \ud558\uc9c0 \uc54a\ub294 \uad6c\ud604\uccb4\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\uac00 \ud544\uc694\ud55c \uacbd\uc6b0 \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub9cc\uc57d \uba54\uc11c\ub4dc\uac00 \ubb34\uc5b8\uac00 \ubc18\ud658\uc744 \ud574\uc57c\ud558\ub294 \uacbd\uc6b0 0, null\uacfc \uac19\uc740 \uac12\uc744 \ubc18\ud658\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud141stub",children:"\uc2a4\ud141(Stub)"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2dc\ub098\ub9ac\uc624\ub9c8\ub2e4 \ub2e4\ub978 \uac12(\ubbf8\ub9ac \uc900\ube44 \ub41c \uacb0\uacfc)\uc744 \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub97c \ud1b5\ud574 \ud2b9\uc815 \uc870\uac74\uc5d0\uc11c \uba54\uc11c\ub4dc\uac00 \uc608\uc0c1\ud55c\ub300\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud30c\uc774spy",children:"\uc2a4\ud30c\uc774(Spy)"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2a4\ud141\uacfc \uc720\uc0ac\ud558\uc9c0\ub9cc \ud638\ucd9c \uc5ec\ubd80\ub97c \uae30\ub85d\ud558\uac70\ub098 \ud638\ucd9c\ud560 \ub54c \uc804\ub2ec\ud55c \uc778\uc790\uac12\uc744 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608) \uba54\uc77c \uc804\uc1a1 \uae30\ub2a5\uc744 \uac00\uc9c4 \uac1d\uccb4\ub97c \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc73c\ub85c \uad6c\ud604\ud588\uc744 \ub54c \uba54\uc77c \uc804\uc1a1 \ud69f\uc218\ub97c \uae30\ub85d\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ubaa9-\ubaa8\uc758-\uac1d\uccb4mock",children:"\ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)"}),"\n",(0,r.jsxs)(t.p,{children:["\ubaa9\uc740 \ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774\ub97c \ud3ec\ud568\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud638\ucd9c \uc2dc \uc0ac\uc804\uc5d0 \uc815\uc758\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud558\uace0, \uc608\uc0c1\uce58 \ubabb\ud55c \ud638\ucd9c\uc774 \uc788\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub610\ud55c \ud638\ucd9c\uc5d0 \ub300\ud55c \uac80\uc99d\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uac00\uc9dcfake",children:"\uac00\uc9dc(Fake)"}),"\n",(0,r.jsxs)(t.p,{children:["DOC\uc640 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc9c0\ub9cc, \ub354\uc6b1 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ub41c \uac83\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608) \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \ub3d9\uc791\ud558\ub294 \uac00\uc9dc \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"DOC(depended-on component)",type:"note",children:(0,r.jsxs)(t.p,{children:["\uc758\uc874 \uad6c\uc131 \uc694\uc18c, DOC\ub97c \ud14c\uc2a4\ud2b8 \ub354\ube14\ub85c \ub300\uccb4\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8 \ub354\ube14\uc740 DOC\uc640 \ub3d9\uc77c\ud55c API\ub97c \uc81c\uacf5\ud574\uc57c \ud55c\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"\uc0c1\ud638\uc791\uc6a9\uc5d0-\ub530\ub978-\ubaa9\uacfc-\uc2a4\ud141-\uad6c\ubd84",children:"\uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84"}),"\n",(0,r.jsxs)(t.p,{children:["\ub2e8\uc704 \ud14c\uc2a4\ud2b8 p.149 \uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ud06c\uac8c \ubaa9\uacfc \uc2a4\ud141\uc73c\ub85c \uad6c\ubd84\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ubaa9\uc740 SUT\uc640 \uad00\ub828\ub41c \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ubc18\uba74, \uc2a4\ud141\uc740 \ub2e8\uc21c \ubaa8\ubc29\ub9cc \ud55c\ub2e4."]}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"TestDouble"}),(0,r.jsx)(t.th,{children:"Mock"}),(0,r.jsx)(t.th,{children:"Stub"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\ud3ec\ud568 \uc720\ud615"}),(0,r.jsx)(t.td,{children:"\ubaa9, \uc2a4\ud30c\uc774"}),(0,r.jsx)(t.td,{children:"\uc2a4\ud141, \ub354\ubbf8, \ud398\uc774\ud06c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc6a9\ub3c4"}),(0,r.jsx)(t.td,{children:"\uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ub370 \uc0ac\uc6a9"}),(0,r.jsx)(t.td,{children:"\ub0b4\ubd80\ub85c \ub4e4\uc5b4\uc624\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\ub294 \ub370 \uc0ac\uc6a9"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc124\uba85"}),(0,r.jsx)(t.td,{children:"SUT\uac00 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9"}),(0,r.jsx)(t.td,{children:"SUT\uac00 \uc785\ub825 \ub370\uc774\ud130\ub97c \uc5bb\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc608\uc2dc"}),(0,r.jsx)(t.td,{children:"\uc774\uba54\uc77c \ubc1c\uc1a1"}),(0,r.jsx)(t.td,{children:"\ub370\uc774\ud130 \uac80\uc0c9"})]})]})]}),"\n",(0,r.jsx)(t.admonition,{title:"SUT(system under test)",type:"note",children:(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc0c1 \uc2dc\uc2a4\ud15c",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8\ub97c \ud558\ub824\ub294 \ub300\uc0c1"]})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:["\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30 - 3\uc7a5 \uace0\uae09 \ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4",(0,r.jsx)(t.br,{}),"\n","\ub2e8\uc704 \ud14c\uc2a4\ud2b8 - 5\uc7a5 \ubaa9\uacfc \ud14c\uc2a4\ud2b8 \ucde8\uc57d\uc131, \ube14\ub77c\ub514\ubbf8\ub974 \ucf54\ub9ac\ucf54\ud504",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uc2dc\uc791\ud558\uae30 - 7\uc7a5 \ub300\uc5ed, \ucd5c\ubc94\uade0",(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://www.martinfowler.com/bliki/TestDouble.html",children:"\ud14c\uc2a4\ud2b8 \ub354\ube14, Martin Fowler"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://johngrib.github.io/wiki/test-terms/",children:"\ud14c\uc2a4\ud2b8 \uad00\ub828 \uc6a9\uc5b4 \uc815\ub9ac, Johngrib"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"http://xunitpatterns.com/Test%20Double.html",children:"Test Double, Gerard Meszaros"})]})]})}function h(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>o});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var d=r.createContext({}),o=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},a={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,d=e.parentName,h=c(e,["components","mdxType","originalType","parentName"]),j=o(n),x=s,u=j["".concat(d,".").concat(x)]||j[x]||a[x]||i;return n?r.createElement(u,l(l({ref:t},h),{},{components:n})):r.createElement(u,l({ref:t},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5798],{58346:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var r=n(85893),s=n(3905);const i={title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",slug:"test-double",tags:["Test","Mock"]},l=void 0,c={permalink:"/test-double",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",source:"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",description:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?",date:"2023-04-04T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 4\uc77c",tags:[{label:"Test",permalink:"/tags/test"},{label:"Mock",permalink:"/tags/mock"}],readingTime:4.52,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",slug:"test-double",tags:["Test","Mock"]},unlisted:!1,prevItem:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",permalink:"/java-class-file"},nextItem:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",permalink:"/transaction-and-isolation"}},d={authorsImageUrls:[]},o=[{value:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?",id:"\ud14c\uc2a4\ud2b8-\ub300\uc5ed\uc774\ub780",level:3},{value:"\ub354\ubbf8(Dummy)",id:"\ub354\ubbf8dummy",level:3},{value:"\uc2a4\ud141(Stub)",id:"\uc2a4\ud141stub",level:3},{value:"\uc2a4\ud30c\uc774(Spy)",id:"\uc2a4\ud30c\uc774spy",level:3},{value:"\ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)",id:"\ubaa9-\ubaa8\uc758-\uac1d\uccb4mock",level:3},{value:"\uac00\uc9dc(Fake)",id:"\uac00\uc9dcfake",level:3},{value:"\uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84",id:"\uc0c1\ud638\uc791\uc6a9\uc5d0-\ub530\ub978-\ubaa9\uacfc-\uc2a4\ud141-\uad6c\ubd84",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function a(e){const t={a:"a",admonition:"admonition",br:"br",h3:"h3",mermaid:"mermaid",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\ud14c\uc2a4\ud2b8-\ub300\uc5ed\uc774\ub780",children:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?"}),"\n",(0,r.jsxs)(t.p,{children:["\ubaa8\ub4e0 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \uac00\uc9dc \uc758\uc874\uc131\uc744 \uc758\ubbf8\ud558\uace0, \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud589\ub420 \ub54c \ub2e4\ub978 \uac1d\uccb4\ub97c \ub300\uc2e0\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Gerard Meszaros\uc758 xUnit Test Patterns\ub77c\ub294 \ucc45\uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ub2e4\uc12f \uac00\uc9c0(\ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774, \ubaa9, \ud398\uc774\ud06c)\ub85c \uad6c\ubd84\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \uae30\ubcf8 \uba54\ucee4\ub2c8\uc998\uc740 \ub2e4\ud615\uc131\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc678\ubd80 \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uacbd\uc6b0, \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uace0 \uc678\ubd80 \uc11c\ube44\uc2a4 \ub300\uc2e0 \ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\uc758 \uad6c\ud604\uccb4\ub97c \uc0dd\uc131\ud558\ub294 \uac83\uc774\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.strong,{children:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \ud0c0\uc785 \uacc4\uce35 \uad6c\uc870"})}),"\n",(0,r.jsx)(t.mermaid,{value:"flowchart LR\n Mock --\x3e Spy --\x3e Stub --\x3e Dummy --\x3e TestDouble\n Fake --\x3e TestDouble"}),"\n",(0,r.jsx)(t.h3,{id:"\ub354\ubbf8dummy",children:"\ub354\ubbf8(Dummy)"}),"\n",(0,r.jsxs)(t.p,{children:["\uac00\uc7a5 \ub2e8\uc21c\ud558\uace0, \uc6d0\uc2dc\uc801\uc778 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c \uc544\ubb34 \uc77c\ub3c4 \ud558\uc9c0 \uc54a\ub294 \uad6c\ud604\uccb4\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\uac00 \ud544\uc694\ud55c \uacbd\uc6b0 \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub9cc\uc57d \uba54\uc11c\ub4dc\uac00 \ubb34\uc5b8\uac00 \ubc18\ud658\uc744 \ud574\uc57c\ud558\ub294 \uacbd\uc6b0 0, null\uacfc \uac19\uc740 \uac12\uc744 \ubc18\ud658\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud141stub",children:"\uc2a4\ud141(Stub)"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2dc\ub098\ub9ac\uc624\ub9c8\ub2e4 \ub2e4\ub978 \uac12(\ubbf8\ub9ac \uc900\ube44 \ub41c \uacb0\uacfc)\uc744 \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub97c \ud1b5\ud574 \ud2b9\uc815 \uc870\uac74\uc5d0\uc11c \uba54\uc11c\ub4dc\uac00 \uc608\uc0c1\ud55c\ub300\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud30c\uc774spy",children:"\uc2a4\ud30c\uc774(Spy)"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2a4\ud141\uacfc \uc720\uc0ac\ud558\uc9c0\ub9cc \ud638\ucd9c \uc5ec\ubd80\ub97c \uae30\ub85d\ud558\uac70\ub098 \ud638\ucd9c\ud560 \ub54c \uc804\ub2ec\ud55c \uc778\uc790\uac12\uc744 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608) \uba54\uc77c \uc804\uc1a1 \uae30\ub2a5\uc744 \uac00\uc9c4 \uac1d\uccb4\ub97c \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc73c\ub85c \uad6c\ud604\ud588\uc744 \ub54c \uba54\uc77c \uc804\uc1a1 \ud69f\uc218\ub97c \uae30\ub85d\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ubaa9-\ubaa8\uc758-\uac1d\uccb4mock",children:"\ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)"}),"\n",(0,r.jsxs)(t.p,{children:["\ubaa9\uc740 \ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774\ub97c \ud3ec\ud568\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud638\ucd9c \uc2dc \uc0ac\uc804\uc5d0 \uc815\uc758\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud558\uace0, \uc608\uc0c1\uce58 \ubabb\ud55c \ud638\ucd9c\uc774 \uc788\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub610\ud55c \ud638\ucd9c\uc5d0 \ub300\ud55c \uac80\uc99d\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uac00\uc9dcfake",children:"\uac00\uc9dc(Fake)"}),"\n",(0,r.jsxs)(t.p,{children:["DOC\uc640 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc9c0\ub9cc, \ub354\uc6b1 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ub41c \uac83\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608) \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \ub3d9\uc791\ud558\ub294 \uac00\uc9dc \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"DOC(depended-on component)",type:"note",children:(0,r.jsxs)(t.p,{children:["\uc758\uc874 \uad6c\uc131 \uc694\uc18c, DOC\ub97c \ud14c\uc2a4\ud2b8 \ub354\ube14\ub85c \ub300\uccb4\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8 \ub354\ube14\uc740 DOC\uc640 \ub3d9\uc77c\ud55c API\ub97c \uc81c\uacf5\ud574\uc57c \ud55c\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"\uc0c1\ud638\uc791\uc6a9\uc5d0-\ub530\ub978-\ubaa9\uacfc-\uc2a4\ud141-\uad6c\ubd84",children:"\uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84"}),"\n",(0,r.jsxs)(t.p,{children:["\ub2e8\uc704 \ud14c\uc2a4\ud2b8 p.149 \uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ud06c\uac8c \ubaa9\uacfc \uc2a4\ud141\uc73c\ub85c \uad6c\ubd84\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ubaa9\uc740 SUT\uc640 \uad00\ub828\ub41c \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ubc18\uba74, \uc2a4\ud141\uc740 \ub2e8\uc21c \ubaa8\ubc29\ub9cc \ud55c\ub2e4."]}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"TestDouble"}),(0,r.jsx)(t.th,{children:"Mock"}),(0,r.jsx)(t.th,{children:"Stub"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\ud3ec\ud568 \uc720\ud615"}),(0,r.jsx)(t.td,{children:"\ubaa9, \uc2a4\ud30c\uc774"}),(0,r.jsx)(t.td,{children:"\uc2a4\ud141, \ub354\ubbf8, \ud398\uc774\ud06c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc6a9\ub3c4"}),(0,r.jsx)(t.td,{children:"\uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ub370 \uc0ac\uc6a9"}),(0,r.jsx)(t.td,{children:"\ub0b4\ubd80\ub85c \ub4e4\uc5b4\uc624\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\ub294 \ub370 \uc0ac\uc6a9"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc124\uba85"}),(0,r.jsx)(t.td,{children:"SUT\uac00 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9"}),(0,r.jsx)(t.td,{children:"SUT\uac00 \uc785\ub825 \ub370\uc774\ud130\ub97c \uc5bb\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc608\uc2dc"}),(0,r.jsx)(t.td,{children:"\uc774\uba54\uc77c \ubc1c\uc1a1"}),(0,r.jsx)(t.td,{children:"\ub370\uc774\ud130 \uac80\uc0c9"})]})]})]}),"\n",(0,r.jsx)(t.admonition,{title:"SUT(system under test)",type:"note",children:(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc0c1 \uc2dc\uc2a4\ud15c",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8\ub97c \ud558\ub824\ub294 \ub300\uc0c1"]})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:["\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30 - 3\uc7a5 \uace0\uae09 \ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4",(0,r.jsx)(t.br,{}),"\n","\ub2e8\uc704 \ud14c\uc2a4\ud2b8 - 5\uc7a5 \ubaa9\uacfc \ud14c\uc2a4\ud2b8 \ucde8\uc57d\uc131, \ube14\ub77c\ub514\ubbf8\ub974 \ucf54\ub9ac\ucf54\ud504",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uc2dc\uc791\ud558\uae30 - 7\uc7a5 \ub300\uc5ed, \ucd5c\ubc94\uade0",(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://www.martinfowler.com/bliki/TestDouble.html",children:"\ud14c\uc2a4\ud2b8 \ub354\ube14, Martin Fowler"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://johngrib.github.io/wiki/test-terms/",children:"\ud14c\uc2a4\ud2b8 \uad00\ub828 \uc6a9\uc5b4 \uc815\ub9ac, Johngrib"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"http://xunitpatterns.com/Test%20Double.html",children:"Test Double, Gerard Meszaros"})]})]})}function h(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>o});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var d=r.createContext({}),o=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},a={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,d=e.parentName,h=c(e,["components","mdxType","originalType","parentName"]),j=o(n),x=s,u=j["".concat(d,".").concat(x)]||j[x]||a[x]||i;return n?r.createElement(u,l(l({ref:t},h),{},{components:n})):r.createElement(u,l({ref:t},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/26dc40bf.bd9e249d.js b/assets/js/26dc40bf.116a2dcb.js similarity index 98% rename from assets/js/26dc40bf.bd9e249d.js rename to assets/js/26dc40bf.116a2dcb.js index bb7370294..c4cacf46b 100644 --- a/assets/js/26dc40bf.bd9e249d.js +++ b/assets/js/26dc40bf.116a2dcb.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5237],{55338:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var r=t(85893),a=t(3905);const i={title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",slug:"java-spring-springboot",tags:["Java","Spring Boot","Spring"]},s=void 0,l={permalink:"/java-spring-springboot",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",source:"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",description:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",date:"2023-07-24T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 24\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Spring Boot",permalink:"/tags/spring-boot"},{label:"Spring",permalink:"/tags/spring"}],readingTime:4.725,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",slug:"java-spring-springboot",tags:["Java","Spring Boot","Spring"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",permalink:"/route-image-intro"},nextItem:{title:"\uc6f9\uc18c\ucf13",permalink:"/websocket"}},o={authorsImageUrls:[]},c=[{value:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",id:"\uc790\ubc14-17-\uc2a4\ud504\ub9c1-60-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-31",level:2},{value:"\uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d",id:"\uc790\ubc14-\ubcc0\uacbd-\uc0ac\ud56d",level:2},{value:"Switch Expressions(Java 14)",id:"switch-expressionsjava-14",level:3},{value:"Text Block(Java 15)",id:"text-blockjava-15",level:3},{value:"NPE \uba54\uc2dc\uc9c0(Java 15)",id:"npe-\uba54\uc2dc\uc9c0java-15",level:3},{value:"Record(Java 16)",id:"recordjava-16",level:3},{value:"\ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d",id:"\ucd94\uac00\uc801\uc778-\ubcc0\uacbd\uc0ac\ud56d",level:3},{value:"\uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ubcc0\uacbd-\uc0ac\ud56d",level:2},{value:"\uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd",id:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4-\ubcc0\uacbd",level:3},{value:"PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c",id:"pathpatternparser---trailing-slash-\ud5c8\uc6a9\ud558\uc9c0-\uc54a\uc74c",level:3},{value:"HTTP interface client",id:"http-interface-client",level:3},{value:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ucd5c\uc18c-\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function h(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"\uc790\ubc14-17-\uc2a4\ud504\ub9c1-60-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-31",children:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1"}),"\n",(0,r.jsxs)(n.p,{children:["\ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\uc744 \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","2.7 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc5c8\uc9c0\ub9cc LTS \uae30\uac04\uacfc \ucde8\uc57d\uc810 \ud328\uce58\ub85c \uc778\ud55c \ubc84\uc804\uc5c5 \ub4f1\uc744 \uace0\ub824\ud588\uc744 \ub54c 3.1\uacfc \uc790\ubc14 17\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \ub354 \ud6a8\uc728\uc801\uc774\ub77c\uace0 \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uc790\ubc14-\ubcc0\uacbd-\uc0ac\ud56d",children:"\uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2\uae4c\uc9c0\ub294 \uc790\ubc14 11\uc744 \uc0ac\uc6a9\ud588\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc790\ubc14 11\ubd80\ud130 \uc790\ubc14 17\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d\uc744 \uc815\uc2dd \ub9b4\ub9ac\uc988 \uae30\uc900\uc73c\ub85c \uc815\ub9ac\ud574\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"switch-expressionsjava-14",children:"Switch Expressions(Java 14)"}),"\n",(0,r.jsx)(n.p,{children:"Java 14\uc5d0\uc11c\ub294 \uae30\uc874\uc758 Switch \ubb38\uc744 \uac04\uacb0\ud558\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub294 Switch \uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"enum RESULT {\n WIN, LOSE, DRAW\n}\n\nRESULT result = RESULT.WIN;\n\nint prize = switch (result) {\n case WIN -> 10_000_000;\n case LOSE, DRAW -> 5_000_000;\n\tdefault -> 0;\n};\n"})}),"\n",(0,r.jsx)(n.p,{children:"\uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"->"})," \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 case\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc14\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsxs)(n.li,{children:["case\ub97c \ucf64\ub9c8(",(0,r.jsx)(n.code,{children:","}),")\ub85c \uc5f0\uacb0\ud558\uc5ec \ud558\ub098\uc758 case\uc5d0 \uc5ec\ub7ec \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.li,{children:"break \ubb38\uc774 \ud544\uc694 \uc5c6\ub2e4."}),"\n",(0,r.jsx)(n.li,{children:"default \ube14\ub85d\uc744 \ud1b5\ud574 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"text-blockjava-15",children:"Text Block(Java 15)"}),"\n",(0,r.jsxs)(n.p,{children:["Java 15\uc5d0\ub294 \uc0c8\ub85c\uc6b4 \ubb38\uc790\uc5f4 \ud45c\ud604\ubc29\uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae34 \ubb38\uc790\uc5f4\uc744 + \uc5f0\uc0b0\uc790\uc758 \ub3c4\uc6c0 \uc5c6\uc774 \uac00\ub3c5\uc131\uc788\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'@Repository\npublic interface PostRepository extends JpaRepository {\n @Query("""\n SELECT p FROM Post p\n WHERE p.title LIKE %:keyword%\n OR p.content LIKE %:keyword%\n """)\n List findPostsByTitleOrContentContainingKeyword(String keyword);\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"npe-\uba54\uc2dc\uc9c0java-15",children:"NPE \uba54\uc2dc\uc9c0(Java 15)"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'String name = null;\nname.chars();\n\n/** \n# before\njava.lang.NullPointerException\n\tat com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)\n\n# after\nCannot invoke "String.chars()" because "name" is null\njava.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null\n*/\n'})}),"\n",(0,r.jsx)(n.h3,{id:"recordjava-16",children:"Record(Java 16)"}),"\n",(0,r.jsxs)(n.p,{children:["Lombok\uc758 ",(0,r.jsx)(n.code,{children:"@Data"}),", kotlin\uc758 data \ud074\ub798\uc2a4\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Record\ub97c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0 \uc811\uadfc\uc790, \uc0dd\uc131\uc790, equals & hashcode, toString\uc774 \uc81c\uacf5\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub370\uc774\ud130 \uc804\uc1a1 \uc6a9\ub3c4\ub85c \uc801\ud569\ud574 \ubcf4\uc778\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public record PostDto(String title, String content) {\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\ucd94\uac00\uc801\uc778-\ubcc0\uacbd\uc0ac\ud56d",children:"\ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d"}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uc678\uc5d0\ub3c4 stream\uc758 toList, \uc778\uc2a4\ud134\uc2a4\uc758 \ud0c0\uc785\uc744 \uac04\ud3b8\ud558\uac8c \uccb4\ud06c\ud558\ub294 Pattern Matching Instanceof, Sealed class \ub4f1\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.h2,{id:"\uc2a4\ud504\ub9c1-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ubcc0\uacbd-\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1\uacfc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\ub3c4 \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud544\uc694\ud574\ubcf4\uc774\ub294 \uba87\uac1c \uc815\ub3c4\ub9cc \uc815\ub9ac\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc2a4\ud504\ub9c1-\uc694\uad6c\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d"}),"\n",(0,r.jsx)(n.p,{children:"Java 17, Jakarta EE 9 \uc774\uc0c1\uc774\uc5b4\uc57c \ud55c\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4-\ubcc0\uacbd",children:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd"}),"\n",(0,r.jsx)(n.p,{children:"Jakarta EE 9\uac00 \uc801\uc6a9\ub418\uba74\uc11c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub3c4 \uc804\ubc18\uc801\uc73c\ub85c javax -> jakarta\ub85c \ubcc0\uacbd\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"pathpatternparser---trailing-slash-\ud5c8\uc6a9\ud558\uc9c0-\uc54a\uc74c",children:"PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c"}),"\n",(0,r.jsxs)(n.p,{children:["6.0 \uc774\uc804\uc758 \uacbd\uc6b0 \uae30\ubcf8 \uc124\uc815 \uae30\uc900\uc73c\ub85c ",(0,r.jsx)(n.code,{children:'@GetMapping("/hello")'}),"\uc640 ",(0,r.jsx)(n.code,{children:'@GetMapping("/hello/")'}),"\uac00 \ub3d9\uc77c\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","6.0 \uc774\ud6c4\uc758 PathPatternParser\uac00 \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0, ",(0,r.jsx)(n.code,{children:"/hello"}),"\uc640 ",(0,r.jsx)(n.code,{children:"/hello/"}),"\ub294 \uc11c\ub85c \ub2e4\ub978 URL\ub85c \ub9e4\uce6d\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"PathPatternParser used by default (with the ability to opt into PathMatcher)."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"http-interface-client",children:"HTTP interface client"}),"\n",(0,r.jsxs)(n.p,{children:["\uc790\ubc14 \uc778\ud130\ud398\uc774\uc2a4\uc640 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc774\uc6a9\ud558\uc5ec HTTP \uc694\uccad\uc744 \uc704\ud55c \uc11c\ube44\uc2a4\ub97c \uc815\uc758\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Kb37Q5GCyZs",children:"\ud1a0\ube44\ub2d8\uc758 \uac15\uc758"}),"\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ucd5c\uc18c-\uc694\uad6c\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6",(0,r.jsx)(n.br,{}),"\n","\uc774\uc678\uc5d0\ub3c4 \uc11c\ub4dc\ud30c\ud2f0\ub4e4\uc758 \ucd5c\uc2e0 \ub9b4\ub9ac\uc988 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud568\uc73c\ub85c, \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ubc84\uc804\uc5d0 \ub9de\ub294 \ub9b4\ub9ac\uc988 \ub178\ud2b8\ub97c \ucc38\uace0\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=1WT6oxchM9M",children:"\uc5b4\ub290\xa0\uc6d4\uae09\uc7c1\uc774\uac1c\ubc1c\uc790\xa0\uc758 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ub530\ub77c\uc7a1\uae30"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=7SlDdzVk6GE",children:"\uc790\ubc14 9-16 \uc8fc\uc694 \ud2b9\uc9d5 \ubcf5\uc2b5\ud558\uae30"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.samsungsds.com/kr/insights/java_jakarta.html",children:"Java EE\uc5d0\uc11c Jakarta EE\ub85c\uc758 \uc804\ud658"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Kb37Q5GCyZs",children:"Spring 6\uc758 \uc0c8\ub85c\uc6b4 HTTP Interface\uc640 3 \uac00\uc9c0 REST Clients \ub77c\uc774\ube0c \ucf54\ub529"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-6.x",children:"What's New in Spring Framework 6.x"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes",children:"Spring Boot 3.0 Release Notes"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes",children:"Spring Boot 3.1 Release Notes"})]})]})}function d(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var o=r.createContext({}),c=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},h={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),p=c(t),j=a,u=p["".concat(o,".").concat(j)]||p[j]||h[j]||i;return t?r.createElement(u,s(s({ref:n},d),{},{components:t})):r.createElement(u,s({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5237],{55338:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var r=t(85893),a=t(3905);const i={title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",slug:"java-spring-springboot",tags:["Java","Spring Boot","Spring"]},s=void 0,l={permalink:"/java-spring-springboot",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",source:"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",description:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",date:"2023-07-24T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 24\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Spring Boot",permalink:"/tags/spring-boot"},{label:"Spring",permalink:"/tags/spring"}],readingTime:4.725,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",slug:"java-spring-springboot",tags:["Java","Spring Boot","Spring"]},unlisted:!1,prevItem:{title:"\uc6f9\uc18c\ucf13",permalink:"/websocket"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",permalink:"/route-image-intro"}},o={authorsImageUrls:[]},c=[{value:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",id:"\uc790\ubc14-17-\uc2a4\ud504\ub9c1-60-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-31",level:2},{value:"\uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d",id:"\uc790\ubc14-\ubcc0\uacbd-\uc0ac\ud56d",level:2},{value:"Switch Expressions(Java 14)",id:"switch-expressionsjava-14",level:3},{value:"Text Block(Java 15)",id:"text-blockjava-15",level:3},{value:"NPE \uba54\uc2dc\uc9c0(Java 15)",id:"npe-\uba54\uc2dc\uc9c0java-15",level:3},{value:"Record(Java 16)",id:"recordjava-16",level:3},{value:"\ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d",id:"\ucd94\uac00\uc801\uc778-\ubcc0\uacbd\uc0ac\ud56d",level:3},{value:"\uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ubcc0\uacbd-\uc0ac\ud56d",level:2},{value:"\uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd",id:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4-\ubcc0\uacbd",level:3},{value:"PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c",id:"pathpatternparser---trailing-slash-\ud5c8\uc6a9\ud558\uc9c0-\uc54a\uc74c",level:3},{value:"HTTP interface client",id:"http-interface-client",level:3},{value:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ucd5c\uc18c-\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function h(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"\uc790\ubc14-17-\uc2a4\ud504\ub9c1-60-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-31",children:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1"}),"\n",(0,r.jsxs)(n.p,{children:["\ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\uc744 \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","2.7 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc5c8\uc9c0\ub9cc LTS \uae30\uac04\uacfc \ucde8\uc57d\uc810 \ud328\uce58\ub85c \uc778\ud55c \ubc84\uc804\uc5c5 \ub4f1\uc744 \uace0\ub824\ud588\uc744 \ub54c 3.1\uacfc \uc790\ubc14 17\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \ub354 \ud6a8\uc728\uc801\uc774\ub77c\uace0 \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uc790\ubc14-\ubcc0\uacbd-\uc0ac\ud56d",children:"\uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2\uae4c\uc9c0\ub294 \uc790\ubc14 11\uc744 \uc0ac\uc6a9\ud588\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc790\ubc14 11\ubd80\ud130 \uc790\ubc14 17\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d\uc744 \uc815\uc2dd \ub9b4\ub9ac\uc988 \uae30\uc900\uc73c\ub85c \uc815\ub9ac\ud574\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"switch-expressionsjava-14",children:"Switch Expressions(Java 14)"}),"\n",(0,r.jsx)(n.p,{children:"Java 14\uc5d0\uc11c\ub294 \uae30\uc874\uc758 Switch \ubb38\uc744 \uac04\uacb0\ud558\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub294 Switch \uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"enum RESULT {\n WIN, LOSE, DRAW\n}\n\nRESULT result = RESULT.WIN;\n\nint prize = switch (result) {\n case WIN -> 10_000_000;\n case LOSE, DRAW -> 5_000_000;\n\tdefault -> 0;\n};\n"})}),"\n",(0,r.jsx)(n.p,{children:"\uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"->"})," \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 case\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc14\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsxs)(n.li,{children:["case\ub97c \ucf64\ub9c8(",(0,r.jsx)(n.code,{children:","}),")\ub85c \uc5f0\uacb0\ud558\uc5ec \ud558\ub098\uc758 case\uc5d0 \uc5ec\ub7ec \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.li,{children:"break \ubb38\uc774 \ud544\uc694 \uc5c6\ub2e4."}),"\n",(0,r.jsx)(n.li,{children:"default \ube14\ub85d\uc744 \ud1b5\ud574 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"text-blockjava-15",children:"Text Block(Java 15)"}),"\n",(0,r.jsxs)(n.p,{children:["Java 15\uc5d0\ub294 \uc0c8\ub85c\uc6b4 \ubb38\uc790\uc5f4 \ud45c\ud604\ubc29\uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae34 \ubb38\uc790\uc5f4\uc744 + \uc5f0\uc0b0\uc790\uc758 \ub3c4\uc6c0 \uc5c6\uc774 \uac00\ub3c5\uc131\uc788\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'@Repository\npublic interface PostRepository extends JpaRepository {\n @Query("""\n SELECT p FROM Post p\n WHERE p.title LIKE %:keyword%\n OR p.content LIKE %:keyword%\n """)\n List findPostsByTitleOrContentContainingKeyword(String keyword);\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"npe-\uba54\uc2dc\uc9c0java-15",children:"NPE \uba54\uc2dc\uc9c0(Java 15)"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'String name = null;\nname.chars();\n\n/** \n# before\njava.lang.NullPointerException\n\tat com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)\n\n# after\nCannot invoke "String.chars()" because "name" is null\njava.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null\n*/\n'})}),"\n",(0,r.jsx)(n.h3,{id:"recordjava-16",children:"Record(Java 16)"}),"\n",(0,r.jsxs)(n.p,{children:["Lombok\uc758 ",(0,r.jsx)(n.code,{children:"@Data"}),", kotlin\uc758 data \ud074\ub798\uc2a4\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Record\ub97c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0 \uc811\uadfc\uc790, \uc0dd\uc131\uc790, equals & hashcode, toString\uc774 \uc81c\uacf5\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub370\uc774\ud130 \uc804\uc1a1 \uc6a9\ub3c4\ub85c \uc801\ud569\ud574 \ubcf4\uc778\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public record PostDto(String title, String content) {\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\ucd94\uac00\uc801\uc778-\ubcc0\uacbd\uc0ac\ud56d",children:"\ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d"}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uc678\uc5d0\ub3c4 stream\uc758 toList, \uc778\uc2a4\ud134\uc2a4\uc758 \ud0c0\uc785\uc744 \uac04\ud3b8\ud558\uac8c \uccb4\ud06c\ud558\ub294 Pattern Matching Instanceof, Sealed class \ub4f1\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.h2,{id:"\uc2a4\ud504\ub9c1-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ubcc0\uacbd-\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1\uacfc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\ub3c4 \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud544\uc694\ud574\ubcf4\uc774\ub294 \uba87\uac1c \uc815\ub3c4\ub9cc \uc815\ub9ac\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc2a4\ud504\ub9c1-\uc694\uad6c\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d"}),"\n",(0,r.jsx)(n.p,{children:"Java 17, Jakarta EE 9 \uc774\uc0c1\uc774\uc5b4\uc57c \ud55c\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4-\ubcc0\uacbd",children:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd"}),"\n",(0,r.jsx)(n.p,{children:"Jakarta EE 9\uac00 \uc801\uc6a9\ub418\uba74\uc11c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub3c4 \uc804\ubc18\uc801\uc73c\ub85c javax -> jakarta\ub85c \ubcc0\uacbd\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"pathpatternparser---trailing-slash-\ud5c8\uc6a9\ud558\uc9c0-\uc54a\uc74c",children:"PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c"}),"\n",(0,r.jsxs)(n.p,{children:["6.0 \uc774\uc804\uc758 \uacbd\uc6b0 \uae30\ubcf8 \uc124\uc815 \uae30\uc900\uc73c\ub85c ",(0,r.jsx)(n.code,{children:'@GetMapping("/hello")'}),"\uc640 ",(0,r.jsx)(n.code,{children:'@GetMapping("/hello/")'}),"\uac00 \ub3d9\uc77c\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","6.0 \uc774\ud6c4\uc758 PathPatternParser\uac00 \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0, ",(0,r.jsx)(n.code,{children:"/hello"}),"\uc640 ",(0,r.jsx)(n.code,{children:"/hello/"}),"\ub294 \uc11c\ub85c \ub2e4\ub978 URL\ub85c \ub9e4\uce6d\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"PathPatternParser used by default (with the ability to opt into PathMatcher)."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"http-interface-client",children:"HTTP interface client"}),"\n",(0,r.jsxs)(n.p,{children:["\uc790\ubc14 \uc778\ud130\ud398\uc774\uc2a4\uc640 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc774\uc6a9\ud558\uc5ec HTTP \uc694\uccad\uc744 \uc704\ud55c \uc11c\ube44\uc2a4\ub97c \uc815\uc758\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Kb37Q5GCyZs",children:"\ud1a0\ube44\ub2d8\uc758 \uac15\uc758"}),"\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ucd5c\uc18c-\uc694\uad6c\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6",(0,r.jsx)(n.br,{}),"\n","\uc774\uc678\uc5d0\ub3c4 \uc11c\ub4dc\ud30c\ud2f0\ub4e4\uc758 \ucd5c\uc2e0 \ub9b4\ub9ac\uc988 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud568\uc73c\ub85c, \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ubc84\uc804\uc5d0 \ub9de\ub294 \ub9b4\ub9ac\uc988 \ub178\ud2b8\ub97c \ucc38\uace0\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=1WT6oxchM9M",children:"\uc5b4\ub290\xa0\uc6d4\uae09\uc7c1\uc774\uac1c\ubc1c\uc790\xa0\uc758 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ub530\ub77c\uc7a1\uae30"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=7SlDdzVk6GE",children:"\uc790\ubc14 9-16 \uc8fc\uc694 \ud2b9\uc9d5 \ubcf5\uc2b5\ud558\uae30"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.samsungsds.com/kr/insights/java_jakarta.html",children:"Java EE\uc5d0\uc11c Jakarta EE\ub85c\uc758 \uc804\ud658"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Kb37Q5GCyZs",children:"Spring 6\uc758 \uc0c8\ub85c\uc6b4 HTTP Interface\uc640 3 \uac00\uc9c0 REST Clients \ub77c\uc774\ube0c \ucf54\ub529"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-6.x",children:"What's New in Spring Framework 6.x"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes",children:"Spring Boot 3.0 Release Notes"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes",children:"Spring Boot 3.1 Release Notes"})]})]})}function d(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var o=r.createContext({}),c=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},h={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),p=c(t),j=a,u=p["".concat(o,".").concat(j)]||p[j]||h[j]||i;return t?r.createElement(u,s(s({ref:n},d),{},{components:t})):r.createElement(u,s({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/2a8faff0.bab1919e.js b/assets/js/2a8faff0.1aef9017.js similarity index 70% rename from assets/js/2a8faff0.bab1919e.js rename to assets/js/2a8faff0.1aef9017.js index b2d2882db..1aef217f4 100644 --- a/assets/js/2a8faff0.bab1919e.js +++ b/assets/js/2a8faff0.1aef9017.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7901],{1150:e=>{e.exports=JSON.parse('{"label":"test","permalink":"/tags/test","allTagsPath":"/tags","count":2,"unlisted":false}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7901],{1150:e=>{e.exports=JSON.parse('{"label":"Test","permalink":"/tags/test","allTagsPath":"/tags","count":2,"unlisted":false}')}}]); \ No newline at end of file diff --git a/assets/js/2c9f5501.313f53d8.js b/assets/js/2c9f5501.5b78b3b1.js similarity index 98% rename from assets/js/2c9f5501.313f53d8.js rename to assets/js/2c9f5501.5b78b3b1.js index 2fc0dfa95..6e34c4e80 100644 --- a/assets/js/2c9f5501.313f53d8.js +++ b/assets/js/2c9f5501.5b78b3b1.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7775],{75040:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var t=r(85893),l=r(3905);const i={title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",slug:"the-essence-of-object-orientation",tags:["Book"]},s=void 0,c={permalink:"/the-essence-of-object-orientation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",source:"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",description:"\ucc45 \uc815\ubcf4",date:"2023-01-07T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 7\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:5.415,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",slug:"the-essence-of-object-orientation",tags:["Book"]},unlisted:!1,prevItem:{title:"JSR-310",permalink:"/jsr-310"},nextItem:{title:"2022\ub144 \ud68c\uace0",permalink:"/2022-retrospective"}},o={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173",id:"\ucc45\uc784\uc758-\uc790\uc728\uc131\uc744-\uac15\uc870\ud558\ub294-\uc774\uc720-p173",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function p(e){const n={blockquote:"blockquote",br:"br",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,l.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",(0,t.jsx)(n.br,{}),"\n","\uc870\uc601\ud638"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc870\uc601\ud638\ub2d8\uc758 \uc624\ube0c\uc81d\ud2b8\ub97c \uc77d\uace0 \ub098\uc11c \ub2e4\uc2dc \ud55c \ubc88 \uc77d\uc5b4\ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc544\uc9c1 \uc774\ud574\uac00 \uc548\ub418\ub294 \ubd80\ubd84\uc774 \ub9ce\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ud56d\uc0c1 \uc0c8\ub85c\uc6c0\uc744 \ub290\ub080\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub354\ud560 \ub098\uc704 \uc5c6\uc774 \ud73c\ub96d\ud55c \uac1d\uccb4\uc9c0\ud5a5 \ucc45\uc774\uace0, \uc870\uae08 \ub354 \uacf5\ubd80\ud558\uace0 \ub2e4\uc2dc \uc77d\uc5b4\ubd10\uc57c\ub420 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ucee4\ud53c \uc804\ubb38\uc810, \uc9c0\ud558\ucca0 \ub178\uc120\ub3c4, \uc774\uc0c1\ud55c \ub098\ub77c\uc758 \uc5d8\ub9ac\uc2a4\ub97c \uc608\uc2dc\ub85c \ub4e0 \uc124\uba85\uc774 \ub108\ubb34 \uc88b\uc558\uace0",(0,t.jsx)(n.br,{}),"\n","\uc88b\uc740 \ub0b4\uc6a9\uc744 \ub2f4\uace0 \uc788\uc9c0\ub9cc \uadf8\ub807\ub2e4\uace0 \ub108\ubb34 \ubb34\uac81\uc9c0 \uc54a\uc544 \uac00\ubccd\uac8c \uc77d\uae30\ub3c4 \uc88b\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucc45\uc784\uc758-\uc790\uc728\uc131\uc744-\uac15\uc870\ud558\ub294-\uc774\uc720-p173",children:"\ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173"}),"\n",(0,t.jsx)(n.p,{children:"\ud611\ub825\uc744 \ub2e8\uc21c\ud558\uac8c \ub9cc\ub4e0\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604 \u2192 \ud611\ub825\uc758 \ubcf5\uc7a1\ud568 \uc800\ud558"}),"\n",(0,t.jsx)(n.li,{children:"\ucc45\uc784\uc758 \ucd94\uc0c1\ud654"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc678\ubd80\uc640 \ub0b4\ubd80\ub97c \uba85\ud655\ud558\uac8c \ubd84\ub9ac\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc694\uccad\ud558\ub294 \uac1d\uccb4\uac00 \ubab0\ub77c\ub3c4 \ub418\ub294 \ubd80\ubd84\uc774 \ucea1\uc290\ud654\ub428\uc73c\ub85c \uc778\ud130\ud398\uc774\uc2a4\uc640 \uad6c\ud604\uc758 \ubd84\ub9ac"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub0b4\ubd80\uc801\uc778 \ubc29\ubc95\uc744 \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 \uc678\ubd80\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ubcc0\uacbd\uc758 \ud30c\uae09\ud6a8\uacfc\ub97c \uac1d\uccb4 \ub0b4\ubd80\ub85c \ucea1\uc290\ud654 \u2192 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \uac1d\uccb4\uc640\uc758 \uacb0\ud569\ub3c4 \uc800\ud558"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ud611\ub825\uc758 \ub300\uc0c1\uc744 \ub2e4\uc591\ud558\uac8c \uc120\ud0dd\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\uc131\uc744 \uc81c\uacf5\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc720\uc5f0\ud55c \uc124\uacc4 \u2192 \uc7ac\uc0ac\uc6a9\uc131 \uc99d\uac00"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc758 \uc5ed\ud560\uc744 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc9c4\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc751\uc9d1\ub3c4\ub97c \ub192\uc740 \uc0c1\ud0dc\ub85c \uc720\uc9c0"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubaa9\ud45c\ub294 \uc2e4\uc138\uacc4\ub97c \ubaa8\ubc29\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\n\uc624\ud788\ub824 \uc0c8\ub85c\uc6b4 \uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc790\uc758 \uc5ed\ud560\uc740 \ub2e8\uc21c\ud788 \uc2e4\uc138\uacc4\ub97c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc548\uc73c\ub85c \uc62e\uaca8 \ub2f4\ub294 \uac83\uc774 \uc544\ub2c8\ub77c \uace0\uac1d\uacfc \uc0ac\uc6a9\uc790\ub97c \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\ub294 \uc2e0\uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\np.21"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uacfc\uac70\uc758 \uc804\ud1b5\uc801\uc778 \uac1c\ubc1c \ubc29\ubc95\uc740 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uc5c4\uaca9\ud558\uac8c \uad6c\ubd84\ud55c\ub2e4.\n\uc774\uc5d0 \ubc18\ud574 \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c\ub294 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uac1d\uccb4\ub77c\ub294 \ud558\ub098\uc758 \ud2c0 \uc548\uc5d0 \ud568\uaed8 \ubb36\uc5b4 \ub193\uc74c\uc73c\ub85c\uc368 \uac1d\uccb4\uc758 \uc790\uc728\uc131\uc744 \ubcf4\uc7a5\ud55c\ub2e4.\n\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub85c \uad6c\uc131\ub41c \uacf5\ub3d9\uccb4\ub294 \uc720\uc9c0 \ubcf4\uc218\uac00 \uc27d\uace0 \uc7ac\uc0ac\uc6a9\uc774 \uc6a9\uc774\ud55c \uc2dc\uc2a4\ud15c\uc744 \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uac00\ub2a5\uc131\uc744 \uc81c\uc2dc\ud55c\ub2e4.\np.33"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubcf8\uc9c8"})}),"\n",(0,t.jsx)(n.p,{children:"\uc2dc\uc2a4\ud15c\uc744 \uc0c1\ud638\uc791\uc6a9\ud558\ub294 \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub4e4\uc758 \uacf5\ub3d9\uccb4\ub85c \ubc14\ub77c\ubcf4\uace0 \uac1d\uccb4\ub97c \uc774\uc6a9\ud574 \uc2dc\uc2a4\ud15c\uc744 \ubd84\ud560\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.p,{children:"\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub780 \uc0c1\ud0dc\uc640 \ud589\uc704\ub97c \ud568\uaed8 \uc9c0\ub2c8\uba70 \uc2a4\uc2a4\ub85c \uc790\uae30 \uc790\uc2e0\uc744 \ucc45\uc784\uc9c0\ub294 \uac1d\uccb4\ub97c \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\ub294 \uc2dc\uc2a4\ud15c\uc758 \ud589\uc704\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud55c\ub2e4. \uac01 \uac1d\uccb4\ub294 \ud611\ub825 \ub0b4\uc5d0\uc11c \uc815\ud574\uc9c4 \uc5ed\ud560\uc744 \uc218\ud589\ud558\uba70 \uc5ed\ud560\uc740 \uad00\ub828\ub41c \ucc45\uc784\uc758 \uc9d1\ud569\uc774\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\ub294 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud558\uae30 \uc704\ud574 \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\uace0, \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c \uac1d\uccb4\ub294 \uba54\uc2dc\uc9c0\ub97c \ucc98\ub9ac\ud558\ub294 \ub370 \uc801\ud569\ud55c \uba54\uc11c\ub4dc\ub97c \uc790\uc728\uc801\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.\np.35"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ud074\ub798\uc2a4\uc758 \uad6c\uc870\uc640 \uba54\uc11c\ub4dc\uac00 \uc544\ub2c8\ub77c \uac1d\uccb4\uc758 \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc5d0 \uc9d1\uc911\ud558\ub77c.\n\uac1d\uccb4\uc9c0\ud5a5\uc740 \uac1d\uccb4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774\uc9c0 \ud074\ub798\uc2a4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\np.38"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub3d9\uc801\uc73c\ub85c \ubcc0\ud558\ub294 \uac1d\uccb4\uc758 \u2018\uc0c1\ud0dc\u2019\uc640 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \u2018\ud589\uc704\u2019\ub2e4.\n\ud074\ub798\uc2a4\ub294 \ud0c0\uc785\uc744 \uad6c\ud604\ud558\uae30 \uc704\ud574 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uad6c\ud604 \uba54\ucee4\ub2c8\uc998\uc774\ub77c\ub294 \uc0ac\uc2e4\uc744 \uae30\uc5b5\ud558\ub77c.\np.105"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ucc45\uc784 \uc8fc\ub3c4 \uc124\uacc4\uc758 \ud575\uc2ec\uc740 \uc5b4\ub5a4 \ud589\uc704\uac00 \ud544\uc694\ud55c\uc9c0\ub97c \uba3c\uc800 \uacb0\uc815\ud55c \ud6c4\uc5d0 \uc774 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac1d\uccb4\ub97c \uacb0\uc815\ud558\ub294 \uac83\uc774\ub2e4.\n\uc774 \uacfc\uc815\uc744 \ud754\ud788 What/Who \uc0ac\uc774\ud074\uc774\ub77c\uace0 \ud55c\ub2e4.\n\u2019\uc5b4\ub5a4 \ud589\uc704(What)\u2019\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud55c \ud6c4 \u2018\ub204\uac00(who)\u2019 \uadf8 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud574\uc57c \ud55c\ub2e4.\n\uc5ec\uae30\uc11c \u2018\uc5b4\ub5a4 \ud589\uc704\u2019\uac00 \ubc14\ub85c \uba54\uc2dc\uc9c0\ub2e4.\np.158"}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var o=t.createContext({}),a=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,l=e.mdxType,i=e.originalType,o=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=a(r),u=l,j=h["".concat(o,".").concat(u)]||h[u]||p[u]||i;return r?t.createElement(j,s(s({ref:n},d),{},{components:r})):t.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7775],{75040:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var t=r(85893),l=r(3905);const i={title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",slug:"the-essence-of-object-orientation",tags:["Book"]},s=void 0,c={permalink:"/the-essence-of-object-orientation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",source:"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",description:"\ucc45 \uc815\ubcf4",date:"2023-01-07T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 7\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:5.415,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",slug:"the-essence-of-object-orientation",tags:["Book"]},unlisted:!1,prevItem:{title:"2022\ub144 \ud68c\uace0",permalink:"/2022-retrospective"},nextItem:{title:"JSR-310",permalink:"/jsr-310"}},o={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173",id:"\ucc45\uc784\uc758-\uc790\uc728\uc131\uc744-\uac15\uc870\ud558\ub294-\uc774\uc720-p173",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function p(e){const n={blockquote:"blockquote",br:"br",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,l.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",(0,t.jsx)(n.br,{}),"\n","\uc870\uc601\ud638"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc870\uc601\ud638\ub2d8\uc758 \uc624\ube0c\uc81d\ud2b8\ub97c \uc77d\uace0 \ub098\uc11c \ub2e4\uc2dc \ud55c \ubc88 \uc77d\uc5b4\ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc544\uc9c1 \uc774\ud574\uac00 \uc548\ub418\ub294 \ubd80\ubd84\uc774 \ub9ce\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ud56d\uc0c1 \uc0c8\ub85c\uc6c0\uc744 \ub290\ub080\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub354\ud560 \ub098\uc704 \uc5c6\uc774 \ud73c\ub96d\ud55c \uac1d\uccb4\uc9c0\ud5a5 \ucc45\uc774\uace0, \uc870\uae08 \ub354 \uacf5\ubd80\ud558\uace0 \ub2e4\uc2dc \uc77d\uc5b4\ubd10\uc57c\ub420 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ucee4\ud53c \uc804\ubb38\uc810, \uc9c0\ud558\ucca0 \ub178\uc120\ub3c4, \uc774\uc0c1\ud55c \ub098\ub77c\uc758 \uc5d8\ub9ac\uc2a4\ub97c \uc608\uc2dc\ub85c \ub4e0 \uc124\uba85\uc774 \ub108\ubb34 \uc88b\uc558\uace0",(0,t.jsx)(n.br,{}),"\n","\uc88b\uc740 \ub0b4\uc6a9\uc744 \ub2f4\uace0 \uc788\uc9c0\ub9cc \uadf8\ub807\ub2e4\uace0 \ub108\ubb34 \ubb34\uac81\uc9c0 \uc54a\uc544 \uac00\ubccd\uac8c \uc77d\uae30\ub3c4 \uc88b\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucc45\uc784\uc758-\uc790\uc728\uc131\uc744-\uac15\uc870\ud558\ub294-\uc774\uc720-p173",children:"\ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173"}),"\n",(0,t.jsx)(n.p,{children:"\ud611\ub825\uc744 \ub2e8\uc21c\ud558\uac8c \ub9cc\ub4e0\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604 \u2192 \ud611\ub825\uc758 \ubcf5\uc7a1\ud568 \uc800\ud558"}),"\n",(0,t.jsx)(n.li,{children:"\ucc45\uc784\uc758 \ucd94\uc0c1\ud654"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc678\ubd80\uc640 \ub0b4\ubd80\ub97c \uba85\ud655\ud558\uac8c \ubd84\ub9ac\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc694\uccad\ud558\ub294 \uac1d\uccb4\uac00 \ubab0\ub77c\ub3c4 \ub418\ub294 \ubd80\ubd84\uc774 \ucea1\uc290\ud654\ub428\uc73c\ub85c \uc778\ud130\ud398\uc774\uc2a4\uc640 \uad6c\ud604\uc758 \ubd84\ub9ac"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub0b4\ubd80\uc801\uc778 \ubc29\ubc95\uc744 \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 \uc678\ubd80\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ubcc0\uacbd\uc758 \ud30c\uae09\ud6a8\uacfc\ub97c \uac1d\uccb4 \ub0b4\ubd80\ub85c \ucea1\uc290\ud654 \u2192 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \uac1d\uccb4\uc640\uc758 \uacb0\ud569\ub3c4 \uc800\ud558"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ud611\ub825\uc758 \ub300\uc0c1\uc744 \ub2e4\uc591\ud558\uac8c \uc120\ud0dd\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\uc131\uc744 \uc81c\uacf5\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc720\uc5f0\ud55c \uc124\uacc4 \u2192 \uc7ac\uc0ac\uc6a9\uc131 \uc99d\uac00"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc758 \uc5ed\ud560\uc744 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc9c4\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc751\uc9d1\ub3c4\ub97c \ub192\uc740 \uc0c1\ud0dc\ub85c \uc720\uc9c0"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubaa9\ud45c\ub294 \uc2e4\uc138\uacc4\ub97c \ubaa8\ubc29\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\n\uc624\ud788\ub824 \uc0c8\ub85c\uc6b4 \uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc790\uc758 \uc5ed\ud560\uc740 \ub2e8\uc21c\ud788 \uc2e4\uc138\uacc4\ub97c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc548\uc73c\ub85c \uc62e\uaca8 \ub2f4\ub294 \uac83\uc774 \uc544\ub2c8\ub77c \uace0\uac1d\uacfc \uc0ac\uc6a9\uc790\ub97c \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\ub294 \uc2e0\uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\np.21"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uacfc\uac70\uc758 \uc804\ud1b5\uc801\uc778 \uac1c\ubc1c \ubc29\ubc95\uc740 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uc5c4\uaca9\ud558\uac8c \uad6c\ubd84\ud55c\ub2e4.\n\uc774\uc5d0 \ubc18\ud574 \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c\ub294 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uac1d\uccb4\ub77c\ub294 \ud558\ub098\uc758 \ud2c0 \uc548\uc5d0 \ud568\uaed8 \ubb36\uc5b4 \ub193\uc74c\uc73c\ub85c\uc368 \uac1d\uccb4\uc758 \uc790\uc728\uc131\uc744 \ubcf4\uc7a5\ud55c\ub2e4.\n\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub85c \uad6c\uc131\ub41c \uacf5\ub3d9\uccb4\ub294 \uc720\uc9c0 \ubcf4\uc218\uac00 \uc27d\uace0 \uc7ac\uc0ac\uc6a9\uc774 \uc6a9\uc774\ud55c \uc2dc\uc2a4\ud15c\uc744 \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uac00\ub2a5\uc131\uc744 \uc81c\uc2dc\ud55c\ub2e4.\np.33"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubcf8\uc9c8"})}),"\n",(0,t.jsx)(n.p,{children:"\uc2dc\uc2a4\ud15c\uc744 \uc0c1\ud638\uc791\uc6a9\ud558\ub294 \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub4e4\uc758 \uacf5\ub3d9\uccb4\ub85c \ubc14\ub77c\ubcf4\uace0 \uac1d\uccb4\ub97c \uc774\uc6a9\ud574 \uc2dc\uc2a4\ud15c\uc744 \ubd84\ud560\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.p,{children:"\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub780 \uc0c1\ud0dc\uc640 \ud589\uc704\ub97c \ud568\uaed8 \uc9c0\ub2c8\uba70 \uc2a4\uc2a4\ub85c \uc790\uae30 \uc790\uc2e0\uc744 \ucc45\uc784\uc9c0\ub294 \uac1d\uccb4\ub97c \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\ub294 \uc2dc\uc2a4\ud15c\uc758 \ud589\uc704\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud55c\ub2e4. \uac01 \uac1d\uccb4\ub294 \ud611\ub825 \ub0b4\uc5d0\uc11c \uc815\ud574\uc9c4 \uc5ed\ud560\uc744 \uc218\ud589\ud558\uba70 \uc5ed\ud560\uc740 \uad00\ub828\ub41c \ucc45\uc784\uc758 \uc9d1\ud569\uc774\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\ub294 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud558\uae30 \uc704\ud574 \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\uace0, \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c \uac1d\uccb4\ub294 \uba54\uc2dc\uc9c0\ub97c \ucc98\ub9ac\ud558\ub294 \ub370 \uc801\ud569\ud55c \uba54\uc11c\ub4dc\ub97c \uc790\uc728\uc801\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.\np.35"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ud074\ub798\uc2a4\uc758 \uad6c\uc870\uc640 \uba54\uc11c\ub4dc\uac00 \uc544\ub2c8\ub77c \uac1d\uccb4\uc758 \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc5d0 \uc9d1\uc911\ud558\ub77c.\n\uac1d\uccb4\uc9c0\ud5a5\uc740 \uac1d\uccb4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774\uc9c0 \ud074\ub798\uc2a4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\np.38"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub3d9\uc801\uc73c\ub85c \ubcc0\ud558\ub294 \uac1d\uccb4\uc758 \u2018\uc0c1\ud0dc\u2019\uc640 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \u2018\ud589\uc704\u2019\ub2e4.\n\ud074\ub798\uc2a4\ub294 \ud0c0\uc785\uc744 \uad6c\ud604\ud558\uae30 \uc704\ud574 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uad6c\ud604 \uba54\ucee4\ub2c8\uc998\uc774\ub77c\ub294 \uc0ac\uc2e4\uc744 \uae30\uc5b5\ud558\ub77c.\np.105"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ucc45\uc784 \uc8fc\ub3c4 \uc124\uacc4\uc758 \ud575\uc2ec\uc740 \uc5b4\ub5a4 \ud589\uc704\uac00 \ud544\uc694\ud55c\uc9c0\ub97c \uba3c\uc800 \uacb0\uc815\ud55c \ud6c4\uc5d0 \uc774 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac1d\uccb4\ub97c \uacb0\uc815\ud558\ub294 \uac83\uc774\ub2e4.\n\uc774 \uacfc\uc815\uc744 \ud754\ud788 What/Who \uc0ac\uc774\ud074\uc774\ub77c\uace0 \ud55c\ub2e4.\n\u2019\uc5b4\ub5a4 \ud589\uc704(What)\u2019\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud55c \ud6c4 \u2018\ub204\uac00(who)\u2019 \uadf8 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud574\uc57c \ud55c\ub2e4.\n\uc5ec\uae30\uc11c \u2018\uc5b4\ub5a4 \ud589\uc704\u2019\uac00 \ubc14\ub85c \uba54\uc2dc\uc9c0\ub2e4.\np.158"}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var o=t.createContext({}),a=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,l=e.mdxType,i=e.originalType,o=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=a(r),u=l,j=h["".concat(o,".").concat(u)]||h[u]||p[u]||i;return r?t.createElement(j,s(s({ref:n},d),{},{components:r})):t.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/327fa616.f584e7ce.js b/assets/js/327fa616.43d3c065.js similarity index 98% rename from assets/js/327fa616.f584e7ce.js rename to assets/js/327fa616.43d3c065.js index fdd709c18..a45dc2ba1 100644 --- a/assets/js/327fa616.f584e7ce.js +++ b/assets/js/327fa616.43d3c065.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3407],{79748:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>x,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var t=r(85893),a=r(3905);const s={title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",slug:"ladder-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,l={permalink:"/ladder-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-ladder/pull/97",date:"2023-02-26T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 26\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:10.285,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",slug:"ladder-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",permalink:"/blackjack-retrospective"},nextItem:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",permalink:"/racing-car-retrospective"}},o={authorsImageUrls:[]},d=[{value:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30",id:"\uc0ac\ub2e4\ub9ac-\ud0c0\uae30",level:3},{value:"Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95",id:"position-\uae30\uc900\uc73c\ub85c-\uc0ac\ub2e4\ub9ac-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",level:3},{value:"Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95",id:"player\uc5d0\uac8c-ladder\ub97c-\uc804\ub2ec\ud558\uc5ec-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function c(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",del:"del",h3:"h3",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/java-ladder/pull/97",children:"https://github.com/woowacourse/java-ladder/pull/97"}),(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/java-ladder/pull/234",children:"https://github.com/woowacourse/java-ladder/pull/234"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc0ac\ub2e4\ub9ac-\ud0c0\uae30",children:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc6b0\uac00\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uc804 \ubbf8\uc158\uacfc \ub2ec\ub9ac TDD\ub85c \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ud544\uc218\uc600\uae30 \ub54c\ubb38\uc5d0 \uc775\uc219\ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, \uc6b0\uac00\uc640 \ubbf8\uc158\uc5d0 \uad00\ud55c \uc18c\ud1b5\uc774 \uc798 \ub418\uc5b4\uc11c \ud070 \ubb38\uc81c \uc5c6\uc774 \ubbf8\uc158\uc744 \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uc6b0\uac00\uc640 \uc774\uc57c\uae30\uac00 \uc798 \ud1b5\ud574\uc11c \uadf8\ub7f0\uc9c0 1\ub2e8\uacc4\ub294 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub294\ub370, 2\ub2e8\uacc4\uc5d0\uc11c \ub9ce\uc774 \uace0\uc804\ud55c \uac83 \uac19\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"2\ub2e8\uacc4\uc5d0\uc11c\ub294 2\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ud574\ubd24\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"LadderGame\uc5d0\uc11c Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.li,{children:"Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c Ladder\uc5d0\uac8c Position\uc744 \ub118\uaca8\uc8fc\uba70 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"position-\uae30\uc900\uc73c\ub85c-\uc0ac\ub2e4\ub9ac-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",children:"Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsxs)(n.p,{children:["\uc0ac\uc2e4\uc0c1 index\ub97c Ladder\uc5d0\uac8c \ub118\uaca8\uc8fc\uace0, \ud574\ub2f9 index\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc1b\ub294 \ubc29\ubc95\uacfc \uc720\uc0ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uad6c\ud604\ud558\uace0 \ub098\ub2c8 \ub2e4\ub978 \ud074\ub798\uc2a4\ub4e4\uc774 Position\uc5d0 \ub300\ud55c \uc758\uc874\ub3c4\uac00 \ub108\ubb34 \ub192\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c Players\uac00 \ubcc4\ub2e4\ub978 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\ub2e4\uace0 \ub290\uaf08\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph TD\n\n LadderGameController --\x3e LadderGame\n LadderGame --\x3e Ladder\n LadderGame --\x3e Players\n LadderGame --\x3e Items\n\n Ladder --\x3e Line\n Line --\x3e LineStatus\n\n LadderGame --\x3e Position\n Ladder --\x3e Position\n Items --\x3e Position\n Line --\x3e Position\n Players --\x3e Position\n\n LadderGame --\x3e LadderGameResult\n\n Items --\x3e Item\n Players --\x3e Player\n\n LadderGameController --\x3e InputView\n LadderGameController --\x3e OutputView\n"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public LadderGameResult play() {\n final Map result = new LinkedHashMap<>();\n // \uc0ac\uc6a9\uc790 \uc218\ub9cc\ud07c Position\uc744 \uac00\uc838\uc640\uc11c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4.\n for (Position position : Position.range(players.count())) {\n final Position resultPosition = ladder.play(position);\n result.put(players.get(position), items.get(resultPosition));\n }\n return new LadderGameResult(result);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"player\uc5d0\uac8c-ladder\ub97c-\uc804\ub2ec\ud558\uc5ec-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",children:"Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsxs)(n.p,{children:["Position\uc5d0 \ub300\ud55c \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub294 Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c, Player\uac00 Ladder\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ubc29\ubc95\uc774 \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc704\ud574\uc11c \uac1d\uccb4\ub4e4\uc774 \uae34\ubc00\ud558\uac8c \ud611\ub825\ud558\uace0, \uc870\uae08 \ub354 \ucc45\uc784\uc758 \ubd84\ubc30\uac00 \uc798 \ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph TD\n\n LadderGameController --\x3e LadderGame\n LadderGame --\x3e Ladder\n LadderGame --\x3e Players\n LadderGame --\x3e Items\n\n Ladder --\x3e Line\n Line --\x3e LineStatus\n Line --\x3e Position\n\n Players --\x3e Ladder\n Player --\x3e Ladder\n\n Item --\x3e Position\n Player --\x3e Position\n\n\n LadderGame --\x3e LadderGameResult\n\n Items --\x3e Item --\x3e ItemName\n Players --\x3e Player --\x3e PlayerName\n\n LadderGameController --\x3e InputView\n LadderGameController --\x3e OutputView\n\n OutputView --\x3e LadderMessageGenerator"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public LadderGameResult play() {\n // \ucc38\uac00\uc790\ub4e4\uc5d0\uac8c \uc0ac\ub2e4\ub9ac\ub97c \uc804\ub2ec\ud574\uc11c \uc0ac\ub2e4\ub9ac\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud55c\ub2e4.\n final Map playResult = players.play(ladder);\n\n final Map result = new LinkedHashMap<>();\n for (Player player : playResult.keySet()) {\n result.put(player, toItem(playResult.get(player)));\n }\n return new LadderGameResult(result);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\uc5d0 \uc2dc\uac04\uc744 \ub4e4\uc774\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc815\ud558\ub294\ub370 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ub4e4\uc5ec\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0ac\ub2e4\ub9ac \ud0c0\uae30\uc758 \uc2e4\ud589 \uacb0\uacfc\ub97c Item\uc73c\ub85c \uc9d3\ub2e4\ub2c8.. \ubb54\uac00 \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uc804 \ubbf8\uc158\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c, \uba85\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \ubd80\uc871\ud568\uc744 \ub9ce\uc774 \ub290\uaf08\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\ud398\uc5b4\uc640 \uc870\uae08 \ub354 \uce5c\ud574\uc9c0\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uccab\ub0a0\uc740 \ud398\uc5b4\uc640 \uce5c\ud574\uc9c0\ub294 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \uac00\uc838\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\uac00\ub791 \ud68c\uace0\ud560 \ub54c \ub0b4\uac00 \uc2dc\uc791\ud558\uc790\ub9c8\uc790 \ucee8\ubca4\uc158 \uc815\ud558\uc790\uace0 \ud574\uc11c \ub9ce\uc774 \ub2f9\ud669\uc2a4\ub7ec\uc6e0\ub2e4\uace0 \ud55c\ub2e4. \uc6b0\uac00 \ubbf8\uc548.. \ud83e\udd72"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"README\ub97c \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c"}),(0,t.jsx)(n.br,{}),"\n","\uc774\uc0c1\ud558\uac8c \ucf54\ub529\uc5d0 \uc9d1\uc911\ud558\uba74 README\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uba74\uc11c \uac19\uc774 \ucee4\ubc0b \ud558\ub294 \uac78 \ud56d\uc0c1 \uae4c\uba39\ub294\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\uc5d0\ub294 \uc870\uae08 \ub354 \uc2e0\uacbd \uc368\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc88b\uc740 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uccab PR\ub54c \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \uc9c8\ubb38\uc744 \ub0a8\uae30\uc9c0 \ubabb\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9ac\ubdf0\uc5b4\uc640\uc758 \uc2dc\uac04\uc774 \uc18c\uc911\ud55c \uc2dc\uac04\uc774\ub77c\ub294 \uac83\uc744 \uae4c\uba39\uc9c0 \ub9d0\uace0, \ub098\uc758 \uc131\uc7a5\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"PR \ud6c4\uc5d0\ub3c4 \uaf3c\uaf3c\ud558\uac8c \ud655\uc778\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\ubd84\uba85 \uc54c\uace0 \uc788\ub294 \ubd80\ubd84\uc774\uc9c0\ub9cc, \ub193\uce5c \ubd80\ubd84\uc774 \ub9ce\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","PR \ud558\uae30 \uc804\uc5d0\ub3c4 \uacc4\uc18d \ud655\uc778\uc744 \ud588\uc9c0\ub9cc, \uc544\ubb34\ub798\ub3c4 IntelliJ\uc5d0\uc11c \ubcf4\ub2c8 \ucf54\ub4dc\uc5d0 \uc775\uc219\ud574\uc838\uc11c \uadf8\ub7f0\uc9c0 \ubcc0\uacbd\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc798 \uc548\ubcf4\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","github pr\uc5d0\uc11c\ub294 \uc804\uccb4 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\ub2c8 PR \ud6c4\uc5d0\ub3c4 \uaf2d \ud655\uc778\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc801\uadf9\uc801\uc73c\ub85c \ub098\uc758 \uc758\uacac\uc744 \ub9d0\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ud398\uc5b4\uc758 \uc758\uacac\uc774 \uad1c\ucc2e\ub2e4\uace0 \uc0dd\uac01\ud558\uba74 \uc218\uc6a9 \ud6c4 \uac1c\uc120\uc744 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\uc5c8\ub294\ub370, \uc870\uae08 \ub354 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ud5a5\uc774 \uc788\ub2e4\uba74 \ub098\ub3c4 \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub9d0\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub098\ub3c4 \uc124\ub4dd\ud558\ub294 \ud798\uc744 \uae30\ub974\uace0, \ud398\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc744 \uc54c \uc218 \uc788\uace0, \uacb0\uacfc\ubb3c\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub098\uc624\uc9c0 \uc54a\uc744\uae4c? (\uace0\ubbfc \ub4e4\uc5b4\uc8fc\uc2e0 \ub9ac\ubdf0\uc5b4 \ud130\ud2c0\ud83d\udc22 \uac10\uc0ac\ud569\ub2c8\ub2e4.)"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784"}),(0,t.jsx)(n.br,{}),"\n","Players\uac00 Position\uc744 \uc0dd\uc131\ud558\uace0 Player\uc758 \uc0dd\uc131\uc790\uc5d0 \ub123\uc5b4\uc8fc\uc5c8\ub2e4. \ud558\uc9c0\ub9cc \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ub828\ub41c \ucf54\uba58\ud2b8\uac00 \ub2ec\ub838\ub2e4.\n\uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uc0dd\uac01\ud574 \ubcf4\ub2c8 Position\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uac74 Player\uae30 \ub54c\ubb38\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 Player\uac00 \ub2f4\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud55c \ud328\ud134\uc73c\ub85c GRASP\uc758 Creator \ud328\ud134\uc774 \uc788\ub294\ub370 \ub2e4\uc74c\uc758 \uc694\uc18c\ub97c \ucd5c\ub300\ud55c \ub9cc\uc871\ud558\ub294 \ud074\ub798\uc2a4\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A\uc758 \ucd08\uae43\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc2e4\uc81c\ub85c \uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud574\uc11c \uae4a\uc774 \uc0dd\uac01\ud558\uba74\uc11c \ucf54\ub529\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc2dc\uc57c\uac00 \ub113\uc5b4\uc9c4 \uac83 \uac19\ub2e4."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\ud328\ud0a4\uc9c0 \ubd84\ub9ac \uae30\uc900"}),(0,t.jsx)(n.br,{}),"\n","\ud328\ud0a4\uc9c0 \ubd84\ub9ac\uc5d0 \ub300\ud55c \ub098\ub9cc\uc758 \uae30\uc900\uc774 \uc544\uc9c1 \uba85\ud655\ud558\uc9c0 \uc54a\uc544 \uc9c8\ubb38\uc774 \ub4e4\uc5b4\uc640\ub3c4 \uba85\ud655\ud558\uac8c \ub2f5\ubcc0\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9c8\uc9c0\ub9c9 \uc81c\ucd9c \uc804\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub97c \ubd84\ub9ac\ud574 \ubd24\ub294\ub370, \uae30\uc900\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \uc88b\uc9c0 \uc54a\uc740 \uc120\ud0dd\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.\n\ud604\uc7ac \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ud06c\uae30\uac00 \uadf8\ub807\uac8c \ud06c\uc9c0 \uc54a\uc73c\ub2c8, domain \ud328\ud0a4\uc9c0\uc5d0\uc11c \uc138\ubd80 \ud328\ud0a4\uc9c0\ub85c \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub420 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc0ac\uc6a9\ud558\ub294 \ucabd\uc5d0\uc11c \uc0dd\uac01\ud558\uae30 & \uc608\uce21\uac00\ub2a5\ud55c \ucf54\ub4dc \uc791\uc131\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","Position\uc5d0\uc11c \ub2e4\uc74c \uc704\uce58\ub098 \uc774\uc804 \uc704\uce58\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud5c8\uc6a9 \ubc94\uc704(0",(0,t.jsxs)(n.del,{children:["19)\uac00 \ubc97\uc5b4\ub09c\ub2e4\uba74, \uc758\ubbf8 \uc5c6\ub294 \uac12\uc774 \ub4e4\uc5b4\uac04 Position\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uac74 Position\uc744 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc744 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \ucf54\ub529\uc774\uc5c8\ub294\ub370, \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 0"]}),"19\uc758 \uac12\uc774 \ubcf4\uc7a5\ub418\uc5b4 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uac83\uc774\uae30 \ub54c\ubb38\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c hasNext, hasPrevious\ub77c\ub294 \uc774\uc804 \uac12, \uc774\ud6c4 \uac12\uc774 \ubc94\uc704 \ub0b4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud558\uace0, \uae30\uc874\uc758 \uac12\uc744 \uac00\uc838\uc624\ub294 \uba54\uc11c\ub4dc\ub294 \ubc94\uc704\uac00 \ubc97\uc5b4\ub098\uba74 \uc608\uc678\ub97c \ub358\uc9c0\ub294 \ubc29\ud5a5\uc73c\ub85c \ud574\uacb0\ud558\uc600\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:["\ubc1d\uc740 \uae30\uc6b4\uc744 \uac00\uc9c0\uace0 \uc788\uace0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \uce5c\ud654\ub825\uc774 \uc88b\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88\uc5d0 \ud398\uc5b4 \ud560 \ub54c \ucee8\ub514\uc158 \uad00\ub9ac\ub97c \uc81c\ub300\ub85c \ubabb\ud574\uc11c \ub9ce\uc774 \ubbf8\uc548\ud588\ub2e4. \ub2e4\uc74c\uc5d0\ub294 \ucd5c\uc0c1\uc758 \ucee8\ub514\uc158\uc73c\ub85c \ud398\uc5b4\ub97c \uc900\ube44\ud574 \ubd10\uc57c\uaca0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc6b0\uac00\ub791 \ud398\uc5b4\ub97c \ud558\uace0 \ub098\uc11c, \ub098\ub3c4 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \ub354 \uc798 \uc9c0\ub0b4\ubd10\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5b4 \uc870\uae08 \ub354 \uc6a9\uae30\ub97c \ub0b4 \uc7a1\ub2f4 \uc911\uc774\ub2e4!"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589\uc774 \uc798 \ub418\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ud398\uc5b4 \uc9c4\ud589\uc774 \ub290\ub9b0 \uac83 \uac19\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c \uc548\uc815\uc801\uc73c\ub85c \uc2dc\uac04 \uc548\uc5d0 \ubbf8\uc158\uc744 \uc644\ub8cc\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589 \uc18d\ub3c4\uc5d0 \ub300\ud574 \uc870\uae08 \ub354 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4!"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud56d\uc0c1 \uc9c0\ub098\uac08 \ub54c\ub9c8\ub2e4 \uc6c3\uc5b4\uc8fc\ub294\ub370, \ub098\ub3c4 \uc790\uc8fc \uc6c3\uc5b4\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6c3\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uc0ac\ub78c\uc774 \ubc1d\uc544 \ubcf4\uc5ec\uc11c \ub108\ubb34 \uc88b\uc740 \uac83 \uac19\ub2e4!"]})]})}function x(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>d});var t=r(67294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function s(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var o=t.createContext({}),d=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},c={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},x=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,s=e.originalType,o=e.parentName,x=l(e,["components","mdxType","originalType","parentName"]),p=d(r),u=a,j=p["".concat(o,".").concat(u)]||p[u]||c[u]||s;return r?t.createElement(j,i(i({ref:n},x),{},{components:r})):t.createElement(j,i({ref:n},x))}));x.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3407],{79748:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>x,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var t=r(85893),a=r(3905);const s={title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",slug:"ladder-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,l={permalink:"/ladder-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-ladder/pull/97",date:"2023-02-26T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 26\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:10.285,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",slug:"ladder-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",permalink:"/racing-car-retrospective"},nextItem:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",permalink:"/blackjack-retrospective"}},o={authorsImageUrls:[]},d=[{value:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30",id:"\uc0ac\ub2e4\ub9ac-\ud0c0\uae30",level:3},{value:"Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95",id:"position-\uae30\uc900\uc73c\ub85c-\uc0ac\ub2e4\ub9ac-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",level:3},{value:"Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95",id:"player\uc5d0\uac8c-ladder\ub97c-\uc804\ub2ec\ud558\uc5ec-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function c(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",del:"del",h3:"h3",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/java-ladder/pull/97",children:"https://github.com/woowacourse/java-ladder/pull/97"}),(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/java-ladder/pull/234",children:"https://github.com/woowacourse/java-ladder/pull/234"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc0ac\ub2e4\ub9ac-\ud0c0\uae30",children:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc6b0\uac00\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uc804 \ubbf8\uc158\uacfc \ub2ec\ub9ac TDD\ub85c \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ud544\uc218\uc600\uae30 \ub54c\ubb38\uc5d0 \uc775\uc219\ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, \uc6b0\uac00\uc640 \ubbf8\uc158\uc5d0 \uad00\ud55c \uc18c\ud1b5\uc774 \uc798 \ub418\uc5b4\uc11c \ud070 \ubb38\uc81c \uc5c6\uc774 \ubbf8\uc158\uc744 \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uc6b0\uac00\uc640 \uc774\uc57c\uae30\uac00 \uc798 \ud1b5\ud574\uc11c \uadf8\ub7f0\uc9c0 1\ub2e8\uacc4\ub294 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub294\ub370, 2\ub2e8\uacc4\uc5d0\uc11c \ub9ce\uc774 \uace0\uc804\ud55c \uac83 \uac19\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"2\ub2e8\uacc4\uc5d0\uc11c\ub294 2\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ud574\ubd24\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"LadderGame\uc5d0\uc11c Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.li,{children:"Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c Ladder\uc5d0\uac8c Position\uc744 \ub118\uaca8\uc8fc\uba70 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"position-\uae30\uc900\uc73c\ub85c-\uc0ac\ub2e4\ub9ac-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",children:"Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsxs)(n.p,{children:["\uc0ac\uc2e4\uc0c1 index\ub97c Ladder\uc5d0\uac8c \ub118\uaca8\uc8fc\uace0, \ud574\ub2f9 index\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc1b\ub294 \ubc29\ubc95\uacfc \uc720\uc0ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uad6c\ud604\ud558\uace0 \ub098\ub2c8 \ub2e4\ub978 \ud074\ub798\uc2a4\ub4e4\uc774 Position\uc5d0 \ub300\ud55c \uc758\uc874\ub3c4\uac00 \ub108\ubb34 \ub192\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c Players\uac00 \ubcc4\ub2e4\ub978 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\ub2e4\uace0 \ub290\uaf08\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph TD\n\n LadderGameController --\x3e LadderGame\n LadderGame --\x3e Ladder\n LadderGame --\x3e Players\n LadderGame --\x3e Items\n\n Ladder --\x3e Line\n Line --\x3e LineStatus\n\n LadderGame --\x3e Position\n Ladder --\x3e Position\n Items --\x3e Position\n Line --\x3e Position\n Players --\x3e Position\n\n LadderGame --\x3e LadderGameResult\n\n Items --\x3e Item\n Players --\x3e Player\n\n LadderGameController --\x3e InputView\n LadderGameController --\x3e OutputView\n"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public LadderGameResult play() {\n final Map result = new LinkedHashMap<>();\n // \uc0ac\uc6a9\uc790 \uc218\ub9cc\ud07c Position\uc744 \uac00\uc838\uc640\uc11c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4.\n for (Position position : Position.range(players.count())) {\n final Position resultPosition = ladder.play(position);\n result.put(players.get(position), items.get(resultPosition));\n }\n return new LadderGameResult(result);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"player\uc5d0\uac8c-ladder\ub97c-\uc804\ub2ec\ud558\uc5ec-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",children:"Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsxs)(n.p,{children:["Position\uc5d0 \ub300\ud55c \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub294 Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c, Player\uac00 Ladder\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ubc29\ubc95\uc774 \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc704\ud574\uc11c \uac1d\uccb4\ub4e4\uc774 \uae34\ubc00\ud558\uac8c \ud611\ub825\ud558\uace0, \uc870\uae08 \ub354 \ucc45\uc784\uc758 \ubd84\ubc30\uac00 \uc798 \ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph TD\n\n LadderGameController --\x3e LadderGame\n LadderGame --\x3e Ladder\n LadderGame --\x3e Players\n LadderGame --\x3e Items\n\n Ladder --\x3e Line\n Line --\x3e LineStatus\n Line --\x3e Position\n\n Players --\x3e Ladder\n Player --\x3e Ladder\n\n Item --\x3e Position\n Player --\x3e Position\n\n\n LadderGame --\x3e LadderGameResult\n\n Items --\x3e Item --\x3e ItemName\n Players --\x3e Player --\x3e PlayerName\n\n LadderGameController --\x3e InputView\n LadderGameController --\x3e OutputView\n\n OutputView --\x3e LadderMessageGenerator"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public LadderGameResult play() {\n // \ucc38\uac00\uc790\ub4e4\uc5d0\uac8c \uc0ac\ub2e4\ub9ac\ub97c \uc804\ub2ec\ud574\uc11c \uc0ac\ub2e4\ub9ac\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud55c\ub2e4.\n final Map playResult = players.play(ladder);\n\n final Map result = new LinkedHashMap<>();\n for (Player player : playResult.keySet()) {\n result.put(player, toItem(playResult.get(player)));\n }\n return new LadderGameResult(result);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\uc5d0 \uc2dc\uac04\uc744 \ub4e4\uc774\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc815\ud558\ub294\ub370 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ub4e4\uc5ec\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0ac\ub2e4\ub9ac \ud0c0\uae30\uc758 \uc2e4\ud589 \uacb0\uacfc\ub97c Item\uc73c\ub85c \uc9d3\ub2e4\ub2c8.. \ubb54\uac00 \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uc804 \ubbf8\uc158\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c, \uba85\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \ubd80\uc871\ud568\uc744 \ub9ce\uc774 \ub290\uaf08\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\ud398\uc5b4\uc640 \uc870\uae08 \ub354 \uce5c\ud574\uc9c0\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uccab\ub0a0\uc740 \ud398\uc5b4\uc640 \uce5c\ud574\uc9c0\ub294 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \uac00\uc838\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\uac00\ub791 \ud68c\uace0\ud560 \ub54c \ub0b4\uac00 \uc2dc\uc791\ud558\uc790\ub9c8\uc790 \ucee8\ubca4\uc158 \uc815\ud558\uc790\uace0 \ud574\uc11c \ub9ce\uc774 \ub2f9\ud669\uc2a4\ub7ec\uc6e0\ub2e4\uace0 \ud55c\ub2e4. \uc6b0\uac00 \ubbf8\uc548.. \ud83e\udd72"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"README\ub97c \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c"}),(0,t.jsx)(n.br,{}),"\n","\uc774\uc0c1\ud558\uac8c \ucf54\ub529\uc5d0 \uc9d1\uc911\ud558\uba74 README\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uba74\uc11c \uac19\uc774 \ucee4\ubc0b \ud558\ub294 \uac78 \ud56d\uc0c1 \uae4c\uba39\ub294\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\uc5d0\ub294 \uc870\uae08 \ub354 \uc2e0\uacbd \uc368\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc88b\uc740 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uccab PR\ub54c \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \uc9c8\ubb38\uc744 \ub0a8\uae30\uc9c0 \ubabb\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9ac\ubdf0\uc5b4\uc640\uc758 \uc2dc\uac04\uc774 \uc18c\uc911\ud55c \uc2dc\uac04\uc774\ub77c\ub294 \uac83\uc744 \uae4c\uba39\uc9c0 \ub9d0\uace0, \ub098\uc758 \uc131\uc7a5\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"PR \ud6c4\uc5d0\ub3c4 \uaf3c\uaf3c\ud558\uac8c \ud655\uc778\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\ubd84\uba85 \uc54c\uace0 \uc788\ub294 \ubd80\ubd84\uc774\uc9c0\ub9cc, \ub193\uce5c \ubd80\ubd84\uc774 \ub9ce\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","PR \ud558\uae30 \uc804\uc5d0\ub3c4 \uacc4\uc18d \ud655\uc778\uc744 \ud588\uc9c0\ub9cc, \uc544\ubb34\ub798\ub3c4 IntelliJ\uc5d0\uc11c \ubcf4\ub2c8 \ucf54\ub4dc\uc5d0 \uc775\uc219\ud574\uc838\uc11c \uadf8\ub7f0\uc9c0 \ubcc0\uacbd\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc798 \uc548\ubcf4\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","github pr\uc5d0\uc11c\ub294 \uc804\uccb4 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\ub2c8 PR \ud6c4\uc5d0\ub3c4 \uaf2d \ud655\uc778\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc801\uadf9\uc801\uc73c\ub85c \ub098\uc758 \uc758\uacac\uc744 \ub9d0\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ud398\uc5b4\uc758 \uc758\uacac\uc774 \uad1c\ucc2e\ub2e4\uace0 \uc0dd\uac01\ud558\uba74 \uc218\uc6a9 \ud6c4 \uac1c\uc120\uc744 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\uc5c8\ub294\ub370, \uc870\uae08 \ub354 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ud5a5\uc774 \uc788\ub2e4\uba74 \ub098\ub3c4 \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub9d0\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub098\ub3c4 \uc124\ub4dd\ud558\ub294 \ud798\uc744 \uae30\ub974\uace0, \ud398\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc744 \uc54c \uc218 \uc788\uace0, \uacb0\uacfc\ubb3c\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub098\uc624\uc9c0 \uc54a\uc744\uae4c? (\uace0\ubbfc \ub4e4\uc5b4\uc8fc\uc2e0 \ub9ac\ubdf0\uc5b4 \ud130\ud2c0\ud83d\udc22 \uac10\uc0ac\ud569\ub2c8\ub2e4.)"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784"}),(0,t.jsx)(n.br,{}),"\n","Players\uac00 Position\uc744 \uc0dd\uc131\ud558\uace0 Player\uc758 \uc0dd\uc131\uc790\uc5d0 \ub123\uc5b4\uc8fc\uc5c8\ub2e4. \ud558\uc9c0\ub9cc \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ub828\ub41c \ucf54\uba58\ud2b8\uac00 \ub2ec\ub838\ub2e4.\n\uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uc0dd\uac01\ud574 \ubcf4\ub2c8 Position\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uac74 Player\uae30 \ub54c\ubb38\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 Player\uac00 \ub2f4\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud55c \ud328\ud134\uc73c\ub85c GRASP\uc758 Creator \ud328\ud134\uc774 \uc788\ub294\ub370 \ub2e4\uc74c\uc758 \uc694\uc18c\ub97c \ucd5c\ub300\ud55c \ub9cc\uc871\ud558\ub294 \ud074\ub798\uc2a4\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A\uc758 \ucd08\uae43\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc2e4\uc81c\ub85c \uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud574\uc11c \uae4a\uc774 \uc0dd\uac01\ud558\uba74\uc11c \ucf54\ub529\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc2dc\uc57c\uac00 \ub113\uc5b4\uc9c4 \uac83 \uac19\ub2e4."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\ud328\ud0a4\uc9c0 \ubd84\ub9ac \uae30\uc900"}),(0,t.jsx)(n.br,{}),"\n","\ud328\ud0a4\uc9c0 \ubd84\ub9ac\uc5d0 \ub300\ud55c \ub098\ub9cc\uc758 \uae30\uc900\uc774 \uc544\uc9c1 \uba85\ud655\ud558\uc9c0 \uc54a\uc544 \uc9c8\ubb38\uc774 \ub4e4\uc5b4\uc640\ub3c4 \uba85\ud655\ud558\uac8c \ub2f5\ubcc0\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9c8\uc9c0\ub9c9 \uc81c\ucd9c \uc804\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub97c \ubd84\ub9ac\ud574 \ubd24\ub294\ub370, \uae30\uc900\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \uc88b\uc9c0 \uc54a\uc740 \uc120\ud0dd\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.\n\ud604\uc7ac \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ud06c\uae30\uac00 \uadf8\ub807\uac8c \ud06c\uc9c0 \uc54a\uc73c\ub2c8, domain \ud328\ud0a4\uc9c0\uc5d0\uc11c \uc138\ubd80 \ud328\ud0a4\uc9c0\ub85c \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub420 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc0ac\uc6a9\ud558\ub294 \ucabd\uc5d0\uc11c \uc0dd\uac01\ud558\uae30 & \uc608\uce21\uac00\ub2a5\ud55c \ucf54\ub4dc \uc791\uc131\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","Position\uc5d0\uc11c \ub2e4\uc74c \uc704\uce58\ub098 \uc774\uc804 \uc704\uce58\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud5c8\uc6a9 \ubc94\uc704(0",(0,t.jsxs)(n.del,{children:["19)\uac00 \ubc97\uc5b4\ub09c\ub2e4\uba74, \uc758\ubbf8 \uc5c6\ub294 \uac12\uc774 \ub4e4\uc5b4\uac04 Position\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uac74 Position\uc744 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc744 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \ucf54\ub529\uc774\uc5c8\ub294\ub370, \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 0"]}),"19\uc758 \uac12\uc774 \ubcf4\uc7a5\ub418\uc5b4 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uac83\uc774\uae30 \ub54c\ubb38\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c hasNext, hasPrevious\ub77c\ub294 \uc774\uc804 \uac12, \uc774\ud6c4 \uac12\uc774 \ubc94\uc704 \ub0b4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud558\uace0, \uae30\uc874\uc758 \uac12\uc744 \uac00\uc838\uc624\ub294 \uba54\uc11c\ub4dc\ub294 \ubc94\uc704\uac00 \ubc97\uc5b4\ub098\uba74 \uc608\uc678\ub97c \ub358\uc9c0\ub294 \ubc29\ud5a5\uc73c\ub85c \ud574\uacb0\ud558\uc600\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:["\ubc1d\uc740 \uae30\uc6b4\uc744 \uac00\uc9c0\uace0 \uc788\uace0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \uce5c\ud654\ub825\uc774 \uc88b\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88\uc5d0 \ud398\uc5b4 \ud560 \ub54c \ucee8\ub514\uc158 \uad00\ub9ac\ub97c \uc81c\ub300\ub85c \ubabb\ud574\uc11c \ub9ce\uc774 \ubbf8\uc548\ud588\ub2e4. \ub2e4\uc74c\uc5d0\ub294 \ucd5c\uc0c1\uc758 \ucee8\ub514\uc158\uc73c\ub85c \ud398\uc5b4\ub97c \uc900\ube44\ud574 \ubd10\uc57c\uaca0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc6b0\uac00\ub791 \ud398\uc5b4\ub97c \ud558\uace0 \ub098\uc11c, \ub098\ub3c4 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \ub354 \uc798 \uc9c0\ub0b4\ubd10\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5b4 \uc870\uae08 \ub354 \uc6a9\uae30\ub97c \ub0b4 \uc7a1\ub2f4 \uc911\uc774\ub2e4!"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589\uc774 \uc798 \ub418\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ud398\uc5b4 \uc9c4\ud589\uc774 \ub290\ub9b0 \uac83 \uac19\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c \uc548\uc815\uc801\uc73c\ub85c \uc2dc\uac04 \uc548\uc5d0 \ubbf8\uc158\uc744 \uc644\ub8cc\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589 \uc18d\ub3c4\uc5d0 \ub300\ud574 \uc870\uae08 \ub354 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4!"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud56d\uc0c1 \uc9c0\ub098\uac08 \ub54c\ub9c8\ub2e4 \uc6c3\uc5b4\uc8fc\ub294\ub370, \ub098\ub3c4 \uc790\uc8fc \uc6c3\uc5b4\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6c3\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uc0ac\ub78c\uc774 \ubc1d\uc544 \ubcf4\uc5ec\uc11c \ub108\ubb34 \uc88b\uc740 \uac83 \uac19\ub2e4!"]})]})}function x(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>d});var t=r(67294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function s(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var o=t.createContext({}),d=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},c={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},x=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,s=e.originalType,o=e.parentName,x=l(e,["components","mdxType","originalType","parentName"]),p=d(r),u=a,j=p["".concat(o,".").concat(u)]||p[u]||c[u]||s;return r?t.createElement(j,i(i({ref:n},x),{},{components:r})):t.createElement(j,i({ref:n},x))}));x.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/372ccfe9.2d5d0a9f.js b/assets/js/372ccfe9.560e7db1.js similarity index 99% rename from assets/js/372ccfe9.2d5d0a9f.js rename to assets/js/372ccfe9.560e7db1.js index 51cebaaeb..79eb1526b 100644 --- a/assets/js/372ccfe9.2d5d0a9f.js +++ b/assets/js/372ccfe9.560e7db1.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9111],{21063:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>c,metadata:()=>l,toc:()=>a});var t=r(85893),o=r(3905);const c={title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",slug:"book-writer",tags:["Book"]},i=void 0,l={permalink:"/book-writer",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",source:"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",description:"\ucc45 \uc815\ubcf4",date:"2023-01-01T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 1\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:4.425,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",slug:"book-writer",tags:["Book"]},unlisted:!1,prevItem:{title:"2022\ub144 \ud68c\uace0",permalink:"/2022-retrospective"}},s={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function u(e){const n={blockquote:"blockquote",br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc15\uc194\ubbf8"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc800\uc790\uc758 \uacbd\ud5d8\uacfc \ud568\uaed8 \uae00\uc4f0\uae30\uc5d0 \ub300\ud55c \uac00\ubcbc\uc6b4 \uc870\uc5b8\uc774 \ub2f4\uaca8\uc788\uc5b4 \uac00\ubccd\uac8c \uc77d\uae30 \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae00\uc744 \uc798 \uc791\uc131\ud574 \ubcf4\uace0 \uc2f6\uc744 \ub54c \uc801\uc6a9\ud574 \ubcfc \uc218 \uc788\ub294 \uc815\ubcf4\uac00 \ub9ce\uc544\uc11c \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\uc758 \ud504\ub9ac\ucf54\uc2a4\ub97c \uc9c4\ud589\ud560 \ub54c \ud6c4\uae30\ub97c \uc791\uc131\ud558\uace0 \ub098\uba74 \ud56d\uc0c1 \uae00\uc774 \ub531\ub531\ud558\ub2e4\ub294 \ub290\ub08c\uc744 \ubc1b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub2e4\ub978 \uc9c0\uc6d0\uc790\ub4e4\uc758 \uc77d\uae30 \ud3b8\ud558\uace0, \ubc1d\uc740 \ub290\ub08c\uc744 \uc8fc\ub294 \uae00\uc744 \ubcf4\uba74 \ubd80\ub7ec\uc6b4 \ub9c8\uc74c\uc744 \uac00\uc9c0\uae30\ub3c4 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ucc45\uc744 \uc77d\uc5c8\uc73c\ub2c8 2023\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae00\uc744 \uc798 \uc801\uc5b4\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ubb38\uc7a5\uc774 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74\n\ub0b4\uc6a9\uc744 \uc77c\ubaa9\uc694\uc5f0\ud558\uac8c \uc815\ub9ac\ud588\uace0, \uae00\uc758 \uc758\ub3c4\ub3c4 \uc090\ub6a4\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub3c4 \uc801\uc808\ud55c \uac83\uc73c\ub85c \uace8\ub790\ub294\ub370\u2026 \uadf8\ub7f0\ub370\ub3c4 \uc5b4\ub518\uac00\uac00 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74? \ucd95\ucd95 \ucc98\uc9c0\uace0 \ub530\ubd84\ud558\ub2e4\uba74? \ub9d0\uaf2c\ub9ac\ub97c \ubaa8\uc870\ub9ac \u2018~\ub2e4\u2019\ub85c \ud1b5\uc77c\ud55c \uac74 \uc544\ub2cc\uc9c0 \uc810\uac80\ud574 \ubcf4\uc138\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ub9d0\uaf2c\ub9ac\ub97c \uc798 \uac16\uace0 \ub180\uc544\uc57c \ud569\ub2c8\ub2e4. \ubb38\uc7a5\uc758 \ub9c8\uc9c0\ub9c9 \uae00\uc790\ub97c \ub9e4\ubc88 \ub2e4\ub974\uac8c \uace0\uccd0\uc4f0\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uae00\uc5d0 \ud65c\uae30\ub97c \ub354\ud560 \uc218 \uc788\uc8e0. \ub54c\ub860 \ubb38\uc7a5\uc744 \ub2e4 \ub9c8\uce58\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub85c\ub9cc \ub05d\ub9fa\ub294 \uac83\ub3c4 \ubc29\ubc95. \ubb38\uc7a5\uacfc \ubb38\uc7a5 \uc0ac\uc774\uc5d0 \uc27c\ud45c\uac00 \ub4e4\uc5b4\uc11c\uba70 \uae00 \uc804\uccb4\uc5d0 \ud65c\uae30\uac00 \ub3cc\uac8c \ub3fc\uc694. \ubb38\uc7a5\uc758 \uae38\uc774\ub3c4 \ub2e4\ucc44\ub85c\uc6cc\uc9c0\ub294 \ub355\ubd84\uc5d0 \ub364\uc73c\ub85c \uc5bb\uac8c \ub418\ub294 \uac83\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ubc14\ub85c, \uae00\uc758 \ub9ac\ub4ec."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc774\uc804 \ubb38\uc7a5\uc5d0\uc11c \ub05d\ub09c \uae00\uc790\ub85c, \ub2e4\uc74c \ubb38\uc7a5\uc744 \ub05d\ub9fa\uc9c0 \uc54a\uae30. \ud55c\ub450 \ubb38\ub2e8\ub9c8\ub2e4 \ub2e8\uc5b4 \uc218\uc900\uc758 \uc544\uc8fc \uc9e7\uc740 \ubb38\uc7a5 \ubc30\uce58\ud558\uae30."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc758 \uc9c4\uc9dc \uc774\uc720, \uae00\uc758 \uc9c4\uc9dc \ubaa9\uc801, \uae00\uc758 \uc9c4\uc9dc \ub300\uc0c1\uc744 \ucc3e\uc73c\ub824\uace0 \uc560\uc37c\uc2b5\ub2c8\ub2e4. \uc9c0\uae08\ucc98\ub7fc \ud2c0\uc744 \ub5a0\uc62c\ub9b0\ub2e4\uac70\ub098, \ub208\uce58\ub97c \ubcf8\ub2e4\uac70\ub098, \uc815\uce58\uc801\uc778 \uc148\ub3c4 \ud558\uc9c0 \uc54a\uc558\uc5b4\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc81c\ubaa9\uc740 \uc9e7\uac8c, \ubcf4\uae30 \uc27d\uac8c, \uc77d\uae30 \uc27d\uac8c, \ubc1c\uc74c\uc774 \ube44\uc2b7\ud558\uac8c, \uc21c\uc11c\ub97c \ubc14\uafd4\uc11c"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc744 \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ub2e4\ub4ec\uc744 \ub54c, \ub178\ub798\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubd05\ub2c8\ub2e4. \uac10\ud788 \uac00 \ub2ff\uc744 \uc218 \uc5c6\ub294 \ubaa9\ud45c\uc774\uaca0\uc9c0\ub9cc, \ud560 \uc218 \uc788\ub294 \ucd5c\uc18c\ud55c\uc758 \ub9ac\ub4ec\uc774\ub77c\ub3c4 \ubd99\uc5ec\uc8fc\uace0 \uc2f6\uc5b4\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc5ec\ub294 \ub9d0\uacfc \ub9c8\uc9c0\ub9c9 \ub9d0\uc5d0 \uc791\uc815\ud558\uace0 \ub9c8\uc74c\uc744 \ub2f4\ub294 \uc5f0\uc2b5\uc744 \ud574\ubd05\uc2dc\ub2e4. \uae00\uc758 \uc5b4\ub290 \uad6c\uc11d\uc774\ub77c\ub3c4 \ubed4\ud55c \uae00\uc790\ub294 \ub0a8\uae30\uc9c0 \uc54a\uaca0\ub178\ub77c \ub2e4\uc9d0\ud558\uba70 \uc368\ubcf4\ub294 \uac81\ub2c8\ub2e4. \ub098\ub9cc\uc774 \uac00\uc9c4 \uc720\uc77c\ud55c \uba54\uc2dc\uc9c0\uc5d0 \uc9d1\uc911\ud558\uba74\uc11c\uc694. \uadf8\ub7fc \uc0dd\uac01\uc774 \ub2ec\ub77c\uc9c0\uace0, \uace0\ub974\ub294 \ub2e8\uc5b4\ub3c4 \ub2ec\ub77c\uc9c0\uace0, \ub0a8\uae34 \ubb38\uc7a5\ub3c4 \ub2ec\ub77c\uc838\uc694. \uacb0\uad6d\uc5d0\ub294 \uae00\uc744 \uc4f4 \uc0ac\ub78c\uc778 \ub098 \uc790\uc2e0\ub3c4 \ub0a8\ub2ec\ub77c\uc9c8 \uac81\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ub9de\ucda4\ubc95\uc740 \uc911\uc694\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub9de\ucda4\ubc95\ubcf4\ub2e4 \ub354 \uc911\uc694\ud55c \uac74 \uac70\uae30\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc785\ub2c8\ub2e4. \ub0b4 \ub9c8\uc74c\uc744 \uae00\uc5d0 \ub2f4\uc544 \uc2e4\uc5b4 \ubcf4\ub0b4\uae30 \uc804, \ub9de\ucda4\ubc95\uc744 \uc810\uac80\ud558\ub294 \uc774\uc720 \uc5ed\uc2dc \uadf8\uac81\ub2c8\ub2e4. \uc624\uc9c1 \ub0b4 \ub9c8\uc74c\uc774 \ub0a8\uc5d0\uac8c \uc77d\ud788\ub294 \ub3d9\uc548 \ubc29\ud574\uac00 \ub418\uc9c0 \uc54a\uae30\ub97c \ubc14\ub77c\uae30 \ub54c\ubb38\uc774\uc8e0. \ub0b4\uac00 \uc4f4 \uae00\ub3c4, \ub0a8\uc774 \uc4f4 \uae00\ub3c4. \uc5b8\uc81c\ub098 \uadf8 \uc548\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc774 \uba3c\uc800\uc785\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc744 \uc4f4\ub2e4\uace0 \uae00\uc774 \uc644\uc131\ub418\ub294 \uac8c \uc544\ub2c8\uc5d0\uc694. \uae00\uacfc \ub2ee\uc740 \ubaa8\uc2b5\uc73c\ub85c \uc0b4 \ub54c, \uae00\uc740 \ube44\ub85c\uc18c \uc644\uc131\ub429\ub2c8\ub2e4."}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function c(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=t.createContext({}),a=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=a(r),b=o,h=d["".concat(s,".").concat(b)]||d[b]||u[b]||c;return r?t.createElement(h,i(i({ref:n},p),{},{components:r})):t.createElement(h,i({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9111],{21063:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>c,metadata:()=>l,toc:()=>a});var t=r(85893),o=r(3905);const c={title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",slug:"book-writer",tags:["Book"]},i=void 0,l={permalink:"/book-writer",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",source:"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",description:"\ucc45 \uc815\ubcf4",date:"2023-01-01T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 1\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:4.425,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",slug:"book-writer",tags:["Book"]},unlisted:!1,nextItem:{title:"2022\ub144 \ud68c\uace0",permalink:"/2022-retrospective"}},s={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function u(e){const n={blockquote:"blockquote",br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc15\uc194\ubbf8"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc800\uc790\uc758 \uacbd\ud5d8\uacfc \ud568\uaed8 \uae00\uc4f0\uae30\uc5d0 \ub300\ud55c \uac00\ubcbc\uc6b4 \uc870\uc5b8\uc774 \ub2f4\uaca8\uc788\uc5b4 \uac00\ubccd\uac8c \uc77d\uae30 \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae00\uc744 \uc798 \uc791\uc131\ud574 \ubcf4\uace0 \uc2f6\uc744 \ub54c \uc801\uc6a9\ud574 \ubcfc \uc218 \uc788\ub294 \uc815\ubcf4\uac00 \ub9ce\uc544\uc11c \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\uc758 \ud504\ub9ac\ucf54\uc2a4\ub97c \uc9c4\ud589\ud560 \ub54c \ud6c4\uae30\ub97c \uc791\uc131\ud558\uace0 \ub098\uba74 \ud56d\uc0c1 \uae00\uc774 \ub531\ub531\ud558\ub2e4\ub294 \ub290\ub08c\uc744 \ubc1b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub2e4\ub978 \uc9c0\uc6d0\uc790\ub4e4\uc758 \uc77d\uae30 \ud3b8\ud558\uace0, \ubc1d\uc740 \ub290\ub08c\uc744 \uc8fc\ub294 \uae00\uc744 \ubcf4\uba74 \ubd80\ub7ec\uc6b4 \ub9c8\uc74c\uc744 \uac00\uc9c0\uae30\ub3c4 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ucc45\uc744 \uc77d\uc5c8\uc73c\ub2c8 2023\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae00\uc744 \uc798 \uc801\uc5b4\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ubb38\uc7a5\uc774 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74\n\ub0b4\uc6a9\uc744 \uc77c\ubaa9\uc694\uc5f0\ud558\uac8c \uc815\ub9ac\ud588\uace0, \uae00\uc758 \uc758\ub3c4\ub3c4 \uc090\ub6a4\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub3c4 \uc801\uc808\ud55c \uac83\uc73c\ub85c \uace8\ub790\ub294\ub370\u2026 \uadf8\ub7f0\ub370\ub3c4 \uc5b4\ub518\uac00\uac00 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74? \ucd95\ucd95 \ucc98\uc9c0\uace0 \ub530\ubd84\ud558\ub2e4\uba74? \ub9d0\uaf2c\ub9ac\ub97c \ubaa8\uc870\ub9ac \u2018~\ub2e4\u2019\ub85c \ud1b5\uc77c\ud55c \uac74 \uc544\ub2cc\uc9c0 \uc810\uac80\ud574 \ubcf4\uc138\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ub9d0\uaf2c\ub9ac\ub97c \uc798 \uac16\uace0 \ub180\uc544\uc57c \ud569\ub2c8\ub2e4. \ubb38\uc7a5\uc758 \ub9c8\uc9c0\ub9c9 \uae00\uc790\ub97c \ub9e4\ubc88 \ub2e4\ub974\uac8c \uace0\uccd0\uc4f0\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uae00\uc5d0 \ud65c\uae30\ub97c \ub354\ud560 \uc218 \uc788\uc8e0. \ub54c\ub860 \ubb38\uc7a5\uc744 \ub2e4 \ub9c8\uce58\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub85c\ub9cc \ub05d\ub9fa\ub294 \uac83\ub3c4 \ubc29\ubc95. \ubb38\uc7a5\uacfc \ubb38\uc7a5 \uc0ac\uc774\uc5d0 \uc27c\ud45c\uac00 \ub4e4\uc5b4\uc11c\uba70 \uae00 \uc804\uccb4\uc5d0 \ud65c\uae30\uac00 \ub3cc\uac8c \ub3fc\uc694. \ubb38\uc7a5\uc758 \uae38\uc774\ub3c4 \ub2e4\ucc44\ub85c\uc6cc\uc9c0\ub294 \ub355\ubd84\uc5d0 \ub364\uc73c\ub85c \uc5bb\uac8c \ub418\ub294 \uac83\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ubc14\ub85c, \uae00\uc758 \ub9ac\ub4ec."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc774\uc804 \ubb38\uc7a5\uc5d0\uc11c \ub05d\ub09c \uae00\uc790\ub85c, \ub2e4\uc74c \ubb38\uc7a5\uc744 \ub05d\ub9fa\uc9c0 \uc54a\uae30. \ud55c\ub450 \ubb38\ub2e8\ub9c8\ub2e4 \ub2e8\uc5b4 \uc218\uc900\uc758 \uc544\uc8fc \uc9e7\uc740 \ubb38\uc7a5 \ubc30\uce58\ud558\uae30."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc758 \uc9c4\uc9dc \uc774\uc720, \uae00\uc758 \uc9c4\uc9dc \ubaa9\uc801, \uae00\uc758 \uc9c4\uc9dc \ub300\uc0c1\uc744 \ucc3e\uc73c\ub824\uace0 \uc560\uc37c\uc2b5\ub2c8\ub2e4. \uc9c0\uae08\ucc98\ub7fc \ud2c0\uc744 \ub5a0\uc62c\ub9b0\ub2e4\uac70\ub098, \ub208\uce58\ub97c \ubcf8\ub2e4\uac70\ub098, \uc815\uce58\uc801\uc778 \uc148\ub3c4 \ud558\uc9c0 \uc54a\uc558\uc5b4\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc81c\ubaa9\uc740 \uc9e7\uac8c, \ubcf4\uae30 \uc27d\uac8c, \uc77d\uae30 \uc27d\uac8c, \ubc1c\uc74c\uc774 \ube44\uc2b7\ud558\uac8c, \uc21c\uc11c\ub97c \ubc14\uafd4\uc11c"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc744 \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ub2e4\ub4ec\uc744 \ub54c, \ub178\ub798\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubd05\ub2c8\ub2e4. \uac10\ud788 \uac00 \ub2ff\uc744 \uc218 \uc5c6\ub294 \ubaa9\ud45c\uc774\uaca0\uc9c0\ub9cc, \ud560 \uc218 \uc788\ub294 \ucd5c\uc18c\ud55c\uc758 \ub9ac\ub4ec\uc774\ub77c\ub3c4 \ubd99\uc5ec\uc8fc\uace0 \uc2f6\uc5b4\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc5ec\ub294 \ub9d0\uacfc \ub9c8\uc9c0\ub9c9 \ub9d0\uc5d0 \uc791\uc815\ud558\uace0 \ub9c8\uc74c\uc744 \ub2f4\ub294 \uc5f0\uc2b5\uc744 \ud574\ubd05\uc2dc\ub2e4. \uae00\uc758 \uc5b4\ub290 \uad6c\uc11d\uc774\ub77c\ub3c4 \ubed4\ud55c \uae00\uc790\ub294 \ub0a8\uae30\uc9c0 \uc54a\uaca0\ub178\ub77c \ub2e4\uc9d0\ud558\uba70 \uc368\ubcf4\ub294 \uac81\ub2c8\ub2e4. \ub098\ub9cc\uc774 \uac00\uc9c4 \uc720\uc77c\ud55c \uba54\uc2dc\uc9c0\uc5d0 \uc9d1\uc911\ud558\uba74\uc11c\uc694. \uadf8\ub7fc \uc0dd\uac01\uc774 \ub2ec\ub77c\uc9c0\uace0, \uace0\ub974\ub294 \ub2e8\uc5b4\ub3c4 \ub2ec\ub77c\uc9c0\uace0, \ub0a8\uae34 \ubb38\uc7a5\ub3c4 \ub2ec\ub77c\uc838\uc694. \uacb0\uad6d\uc5d0\ub294 \uae00\uc744 \uc4f4 \uc0ac\ub78c\uc778 \ub098 \uc790\uc2e0\ub3c4 \ub0a8\ub2ec\ub77c\uc9c8 \uac81\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ub9de\ucda4\ubc95\uc740 \uc911\uc694\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub9de\ucda4\ubc95\ubcf4\ub2e4 \ub354 \uc911\uc694\ud55c \uac74 \uac70\uae30\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc785\ub2c8\ub2e4. \ub0b4 \ub9c8\uc74c\uc744 \uae00\uc5d0 \ub2f4\uc544 \uc2e4\uc5b4 \ubcf4\ub0b4\uae30 \uc804, \ub9de\ucda4\ubc95\uc744 \uc810\uac80\ud558\ub294 \uc774\uc720 \uc5ed\uc2dc \uadf8\uac81\ub2c8\ub2e4. \uc624\uc9c1 \ub0b4 \ub9c8\uc74c\uc774 \ub0a8\uc5d0\uac8c \uc77d\ud788\ub294 \ub3d9\uc548 \ubc29\ud574\uac00 \ub418\uc9c0 \uc54a\uae30\ub97c \ubc14\ub77c\uae30 \ub54c\ubb38\uc774\uc8e0. \ub0b4\uac00 \uc4f4 \uae00\ub3c4, \ub0a8\uc774 \uc4f4 \uae00\ub3c4. \uc5b8\uc81c\ub098 \uadf8 \uc548\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc774 \uba3c\uc800\uc785\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc744 \uc4f4\ub2e4\uace0 \uae00\uc774 \uc644\uc131\ub418\ub294 \uac8c \uc544\ub2c8\uc5d0\uc694. \uae00\uacfc \ub2ee\uc740 \ubaa8\uc2b5\uc73c\ub85c \uc0b4 \ub54c, \uae00\uc740 \ube44\ub85c\uc18c \uc644\uc131\ub429\ub2c8\ub2e4."}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function c(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=t.createContext({}),a=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=a(r),b=o,h=d["".concat(s,".").concat(b)]||d[b]||u[b]||c;return r?t.createElement(h,i(i({ref:n},p),{},{components:r})):t.createElement(h,i({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/3dd4d232.a5b347e4.js b/assets/js/3dd4d232.025b37fc.js similarity index 97% rename from assets/js/3dd4d232.a5b347e4.js rename to assets/js/3dd4d232.025b37fc.js index 1d7a30693..369b4667a 100644 --- a/assets/js/3dd4d232.a5b347e4.js +++ b/assets/js/3dd4d232.025b37fc.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7727],{22195:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var t=n(85893),s=n(3905);const c={title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",slug:"blackjack-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,a={permalink:"/blackjack-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-blackjack/pull/427",date:"2023-03-14T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 14\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.17,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",slug:"blackjack-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",permalink:"/grasp"},nextItem:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",permalink:"/ladder-retrospective"}},i={authorsImageUrls:[]},l=[{value:"\ube14\ub799\uc7ad",id:"\ube14\ub799\uc7ad",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function j(e){const r={a:"a",admonition:"admonition",br:"br",h3:"h3",p:"p",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-blackjack/pull/427",children:"https://github.com/woowacourse/java-blackjack/pull/427"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-blackjack/pull/537",children:"https://github.com/woowacourse/java-blackjack/pull/537"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\ube14\ub799\uc7ad",children:"\ube14\ub799\uc7ad"}),"\n",(0,t.jsxs)(r.p,{children:["\ube14\ub799\uc7ad \ubbf8\uc158\uc5d0\uc11c\ub294 \ud6c4\ucd94\uc640 \ud398\uc5b4(\uc870\ubbf8\ub8cc \ub4c0\uc624?)\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \uc2e4\uc218\ud558\uc9c0 \uc54a\uace0, \ubc14\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uc9c0 \uc54a\uace0 \uce5c\ud574\uc9c0\uae30 \ubd80\ud130 \uc2dc\uc791\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ube14\ub799\uc7ad\uc740 \uad6c\ud604\ud574\uc57c \ub420 \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud560 \uac83 \uac19\uc558\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\ud6c4\ucd94\uc640 \ud568\uaed8 \uc804\ub7b5\uc801(\uc0bc\uc77c\uc808\uc5d0 \ubbf8\uc158 \uc774\uc57c\uae30 \ub098\ub204\uae30)\uc73c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud574 \uc2dc\uac04 \ub0b4\uc5d0 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ubbf8\uc158\uc744 \ub05d\ub098\uace0 \ud68c\uace0\ub97c \ud588\uc744 \ub54c \ud6c4\ucd94\uac00 \uace0\ubbfc\uac70\ub9ac\ub97c \ud558\ub098 \ub0b4\uc92c\ub2e4.",(0,t.jsx)(r.br,{}),"\n",'"\ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \uc555\ubc15\uac10\uc744 \ub290\ub07c\ub294 \ud398\uc5b4\uac00 \uc788\ub2e4\uba74 \ud5c8\ube0c\uac00 \ud574\uc904 \uc218 \uc788\ub294\uac8c \ubb50\uac00 \uc788\uc744\uae4c?"']}),"\n",(0,t.jsxs)(r.p,{children:["\uacf0\uacf0\ud788 \uc0dd\uac01\ud574\ubd24\uc9c0\ub9cc \uc27d\uac8c \ub2f5\uc744 \ub0b4\ub9b4 \uc218 \uc5c6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ud68c\uace0\ub97c \ud558\uace0, \ub098\uc758 \uc18c\ud504\ud2b8\uc2a4\ud0ac\uc744 \ub192\ud788\ub294\uac8c \ub2f5\uc77c\uae4c?",(0,t.jsx)(r.br,{}),"\n","\ubd80\ub2f4\uac10\uc744 \ub290\ub07c\uc9c0 \uc54a\uace0 \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub420 \uc218 \uc788\ub3c4\ub85d \uacc4\uc18d \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc0dd\uac01\uc774 \ub9ce\uc544\uc838\uc11c \uc804 \ub9ac\ubdf0\uc5b4\uc778 \ud130\ud2c0\ud83d\udc22\uacfc\ub3c4 \ub300\ud654\ub97c \ub098\ub204\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud130\ud2c0\uc740 \uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84(\uad81\uadf9\uc801\uc778 \ubaa9\ud45c\uc778 \uc88b\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uac83)\uc5d0 \uc9d1\uc911\ud574\ubcf4\ub77c\uace0 \ud558\uc168\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\uc88b\uc740 \ucf54\ub4dc, \uc88b\uc740 \ud398\uc5b4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc77c\ub2e8 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ud398\uc5b4 \uc2e0\uacbd\uc4f0\uae30"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ud398\uc5b4\ud560 \ub54c \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub0b4\ubcf4\ub3c4\ub85d \ud588\ub2e4. \uadf8\ub807\uae30\uc5d0 \ub108\ubb34 \uc758\uacac\uc744 \uac15\ud558\uac8c \ubc00\uc5b4\ubd99\uc778 \ub290\ub08c\uc774 \ub4e4\uc5b4\uc11c \ubbf8\uc548\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud6c4\ucd94\uac00 \uc555\ubc15\uc744 \ub290\uaf08\uc744 \uc218\ub3c4 \uc788\uc744 \uac83 \uac19\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \uc791\uc740 \ud68c\uace0\ub97c \uc9c4\ud589\ud574\ubcf4\ub294 \uac83\uc774 \uc88b\uc744\uae4c?"]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uccb4\ub825 \uad00\ub9ac"}),(0,t.jsx)(r.br,{}),"\n","\uc694\uc998 \uc798 \ubabb\uba39\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc0b4 \ub0a0\uc774 \ub9ce\uc740\ub370 \uc798 \ucc59\uaca8\uba39\uace0, \ud798\ub0b4\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc911\uac04 \uc911\uac04 \ub3cc\uc544\ubcf4\uae30"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ubbf8\uc158\uacfc \uad00\ub828\ub41c \ub0b4\uc6a9\uc740 \uc544\ub2c8\uc9c0\ub9cc \uc6b0\ud14c\ucf54\ub97c \uc798 \ud65c\uc6a9 \ud558\uace0 \uc788\ub294\uc9c0 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \uc6b0\ud14c\ucf54\uc5d0 \uc9c0\uc6d0\ud55c \uc774\uc720\ub97c \ud56d\uc0c1 \uc78a\uc9c0 \uc54a\uc544\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc0c1\ud0dc \ud328\ud134"}),(0,t.jsx)(r.br,{}),"\n","\uac1d\uccb4\uc758 \ub0b4\ubd80 \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc2a4\uc2a4\ub85c \ud589\ub3d9\uc744 \ubcc0\uacbd\ud558\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc73c\ub85c if/else/switch\uc640 \uac19\uc740 \uc870\uac74\ubb38\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \uc81c\uac70\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube14\ub799\uc7ad \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc0c1\ud0dc \ud328\ud134\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ucc98\uc74c \uc801\uc6a9\ud574\ubcf4\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucc98\uc74c \uc801\uc6a9\ud558\uae30 \uc804\uc5d0\ub294 \ubcc4\ub85c\ub77c\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc0dd\uac01\ubcf4\ub2e4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc77c\uad00\uc131, \uac00\ub3c5\uc131, \ucd94\uc0c1\ud654"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ub9ac\ubdf0\uc5b4\ub294 \uac80\ud504\ud83c\udf6b \uc600\ub2e4!",(0,t.jsx)(r.br,{}),"\n","\uac80\ud504\uc758 \ub9ac\ubdf0\ub294 \uac04\uacb0\ud568\uc5d0 \uad00\ub828\ub41c \ub0b4\uc6a9\uc774 \ub9ce\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc77c\uad00\uc131\uc774 \uc788\ub294 \ucf54\ub4dc, \uac00\ub3c5\uc131\uc774 \uc88b\uc740 \ucf54\ub4dc, \ucd94\uc0c1\ud654\uac00 \uc798 \ub418\uc5b4\uc788\ub294 \ucf54\ub4dc",(0,t.jsx)(r.br,{}),"\n","\uc77d\uae30 \uc88b\uace0, \uac04\uacb0\ud55c \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b4 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucf54\ub4dc\ub97c \ubc14\ub77c\ubcf4\ub294 \uc2dc\uc810\uc774 \ud558\ub098 \ub298\uc5b4\ub09c \uae30\ubd84\uc774\ub2e4!(\uc55e\uc73c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc740 \ub098\uc758 \ubaab\uc774\uc9c0\ub9cc)"]}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc0dd\uac01 \uc815\ub9ac"}),(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ud604\uc7ac \uc0c1\ud669\uc5d0 \ub300\ud574 \uadf8\ub9bc\uc744 \uadf8\ub9ac\uac70\ub098, \uae00\uc744 \uc801\uc73c\uba74\uc11c \uc815\ub9ac\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud398\uc5b4\uc640 \ub3d9\uc77c\ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc9c4\ud589\ud558\ub294\ub370 \ub9e4\uc6b0 \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \ub2e4\uc74c \ud398\uc5b4\ub54c\ubd80\ud130 \ud39c\uc774\ub791 \uc885\uc774\ub97c \uc900\ube44\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uac00\uac10\uc5c6\uc774 \uc758\uacac\uc744 \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\uc9c4\ud589 \uc0c1\ud669\uc5d0 \ub300\ud55c \ubd80\ubd84, \uc9c4\ud589 \uc18d\ub3c4, \uc9c0\uae08 \uc790\uc2e0\uc774 \uc774\ud574\ud558\uace0 \uc788\ub294 \ubd80\ubd84\uc744 \ub9d0\ud574\uc918\uc11c \ud3b8\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud68c\uace0\ub54c\ub3c4 \uc11c\ub85c \uc194\uc9c1\ud558\uac8c \uc758\uacac\uc744 \uc8fc\uace0 \ubc1b\uc544\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ub3c4\uba54\uc778 \uc5b8\uc5b4\uc5d0 \uc2e0\uacbd\uc4f0\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\ud074\ub798\uc2a4\uba85, \ubcc0\uc218\uba85\uacfc \uac19\uc740 \uc5b8\uc5b4\ub97c \uc138\uc2ec\ud558\uac8c \uc2e0\uacbd\uc4f4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc694\uad6c\uc0ac\ud56d \uc815\ub9ac\ub3c4 \uae54\ub054\ud558\uac8c \uc798\ud558\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\ud6c4\ucd94 \ucd5c\uace0 \ud83d\udc4d"})]})}function p(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(j,{...e})}):j(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function c(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),l=function(e){var r=t.useContext(i),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},j={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},p=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,c=e.originalType,i=e.parentName,p=a(e,["components","mdxType","originalType","parentName"]),b=l(n),h=s,u=b["".concat(i,".").concat(h)]||b[h]||j[h]||c;return n?t.createElement(u,o(o({ref:r},p),{},{components:n})):t.createElement(u,o({ref:r},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7727],{22195:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var t=n(85893),s=n(3905);const c={title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",slug:"blackjack-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,a={permalink:"/blackjack-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-blackjack/pull/427",date:"2023-03-14T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 14\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.17,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",slug:"blackjack-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",permalink:"/ladder-retrospective"},nextItem:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",permalink:"/grasp"}},i={authorsImageUrls:[]},l=[{value:"\ube14\ub799\uc7ad",id:"\ube14\ub799\uc7ad",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function j(e){const r={a:"a",admonition:"admonition",br:"br",h3:"h3",p:"p",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-blackjack/pull/427",children:"https://github.com/woowacourse/java-blackjack/pull/427"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-blackjack/pull/537",children:"https://github.com/woowacourse/java-blackjack/pull/537"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\ube14\ub799\uc7ad",children:"\ube14\ub799\uc7ad"}),"\n",(0,t.jsxs)(r.p,{children:["\ube14\ub799\uc7ad \ubbf8\uc158\uc5d0\uc11c\ub294 \ud6c4\ucd94\uc640 \ud398\uc5b4(\uc870\ubbf8\ub8cc \ub4c0\uc624?)\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \uc2e4\uc218\ud558\uc9c0 \uc54a\uace0, \ubc14\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uc9c0 \uc54a\uace0 \uce5c\ud574\uc9c0\uae30 \ubd80\ud130 \uc2dc\uc791\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ube14\ub799\uc7ad\uc740 \uad6c\ud604\ud574\uc57c \ub420 \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud560 \uac83 \uac19\uc558\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\ud6c4\ucd94\uc640 \ud568\uaed8 \uc804\ub7b5\uc801(\uc0bc\uc77c\uc808\uc5d0 \ubbf8\uc158 \uc774\uc57c\uae30 \ub098\ub204\uae30)\uc73c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud574 \uc2dc\uac04 \ub0b4\uc5d0 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ubbf8\uc158\uc744 \ub05d\ub098\uace0 \ud68c\uace0\ub97c \ud588\uc744 \ub54c \ud6c4\ucd94\uac00 \uace0\ubbfc\uac70\ub9ac\ub97c \ud558\ub098 \ub0b4\uc92c\ub2e4.",(0,t.jsx)(r.br,{}),"\n",'"\ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \uc555\ubc15\uac10\uc744 \ub290\ub07c\ub294 \ud398\uc5b4\uac00 \uc788\ub2e4\uba74 \ud5c8\ube0c\uac00 \ud574\uc904 \uc218 \uc788\ub294\uac8c \ubb50\uac00 \uc788\uc744\uae4c?"']}),"\n",(0,t.jsxs)(r.p,{children:["\uacf0\uacf0\ud788 \uc0dd\uac01\ud574\ubd24\uc9c0\ub9cc \uc27d\uac8c \ub2f5\uc744 \ub0b4\ub9b4 \uc218 \uc5c6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ud68c\uace0\ub97c \ud558\uace0, \ub098\uc758 \uc18c\ud504\ud2b8\uc2a4\ud0ac\uc744 \ub192\ud788\ub294\uac8c \ub2f5\uc77c\uae4c?",(0,t.jsx)(r.br,{}),"\n","\ubd80\ub2f4\uac10\uc744 \ub290\ub07c\uc9c0 \uc54a\uace0 \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub420 \uc218 \uc788\ub3c4\ub85d \uacc4\uc18d \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc0dd\uac01\uc774 \ub9ce\uc544\uc838\uc11c \uc804 \ub9ac\ubdf0\uc5b4\uc778 \ud130\ud2c0\ud83d\udc22\uacfc\ub3c4 \ub300\ud654\ub97c \ub098\ub204\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud130\ud2c0\uc740 \uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84(\uad81\uadf9\uc801\uc778 \ubaa9\ud45c\uc778 \uc88b\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uac83)\uc5d0 \uc9d1\uc911\ud574\ubcf4\ub77c\uace0 \ud558\uc168\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\uc88b\uc740 \ucf54\ub4dc, \uc88b\uc740 \ud398\uc5b4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc77c\ub2e8 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ud398\uc5b4 \uc2e0\uacbd\uc4f0\uae30"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ud398\uc5b4\ud560 \ub54c \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub0b4\ubcf4\ub3c4\ub85d \ud588\ub2e4. \uadf8\ub807\uae30\uc5d0 \ub108\ubb34 \uc758\uacac\uc744 \uac15\ud558\uac8c \ubc00\uc5b4\ubd99\uc778 \ub290\ub08c\uc774 \ub4e4\uc5b4\uc11c \ubbf8\uc548\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud6c4\ucd94\uac00 \uc555\ubc15\uc744 \ub290\uaf08\uc744 \uc218\ub3c4 \uc788\uc744 \uac83 \uac19\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \uc791\uc740 \ud68c\uace0\ub97c \uc9c4\ud589\ud574\ubcf4\ub294 \uac83\uc774 \uc88b\uc744\uae4c?"]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uccb4\ub825 \uad00\ub9ac"}),(0,t.jsx)(r.br,{}),"\n","\uc694\uc998 \uc798 \ubabb\uba39\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc0b4 \ub0a0\uc774 \ub9ce\uc740\ub370 \uc798 \ucc59\uaca8\uba39\uace0, \ud798\ub0b4\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc911\uac04 \uc911\uac04 \ub3cc\uc544\ubcf4\uae30"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ubbf8\uc158\uacfc \uad00\ub828\ub41c \ub0b4\uc6a9\uc740 \uc544\ub2c8\uc9c0\ub9cc \uc6b0\ud14c\ucf54\ub97c \uc798 \ud65c\uc6a9 \ud558\uace0 \uc788\ub294\uc9c0 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \uc6b0\ud14c\ucf54\uc5d0 \uc9c0\uc6d0\ud55c \uc774\uc720\ub97c \ud56d\uc0c1 \uc78a\uc9c0 \uc54a\uc544\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc0c1\ud0dc \ud328\ud134"}),(0,t.jsx)(r.br,{}),"\n","\uac1d\uccb4\uc758 \ub0b4\ubd80 \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc2a4\uc2a4\ub85c \ud589\ub3d9\uc744 \ubcc0\uacbd\ud558\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc73c\ub85c if/else/switch\uc640 \uac19\uc740 \uc870\uac74\ubb38\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \uc81c\uac70\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube14\ub799\uc7ad \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc0c1\ud0dc \ud328\ud134\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ucc98\uc74c \uc801\uc6a9\ud574\ubcf4\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucc98\uc74c \uc801\uc6a9\ud558\uae30 \uc804\uc5d0\ub294 \ubcc4\ub85c\ub77c\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc0dd\uac01\ubcf4\ub2e4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc77c\uad00\uc131, \uac00\ub3c5\uc131, \ucd94\uc0c1\ud654"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ub9ac\ubdf0\uc5b4\ub294 \uac80\ud504\ud83c\udf6b \uc600\ub2e4!",(0,t.jsx)(r.br,{}),"\n","\uac80\ud504\uc758 \ub9ac\ubdf0\ub294 \uac04\uacb0\ud568\uc5d0 \uad00\ub828\ub41c \ub0b4\uc6a9\uc774 \ub9ce\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc77c\uad00\uc131\uc774 \uc788\ub294 \ucf54\ub4dc, \uac00\ub3c5\uc131\uc774 \uc88b\uc740 \ucf54\ub4dc, \ucd94\uc0c1\ud654\uac00 \uc798 \ub418\uc5b4\uc788\ub294 \ucf54\ub4dc",(0,t.jsx)(r.br,{}),"\n","\uc77d\uae30 \uc88b\uace0, \uac04\uacb0\ud55c \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b4 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucf54\ub4dc\ub97c \ubc14\ub77c\ubcf4\ub294 \uc2dc\uc810\uc774 \ud558\ub098 \ub298\uc5b4\ub09c \uae30\ubd84\uc774\ub2e4!(\uc55e\uc73c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc740 \ub098\uc758 \ubaab\uc774\uc9c0\ub9cc)"]}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc0dd\uac01 \uc815\ub9ac"}),(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ud604\uc7ac \uc0c1\ud669\uc5d0 \ub300\ud574 \uadf8\ub9bc\uc744 \uadf8\ub9ac\uac70\ub098, \uae00\uc744 \uc801\uc73c\uba74\uc11c \uc815\ub9ac\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud398\uc5b4\uc640 \ub3d9\uc77c\ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc9c4\ud589\ud558\ub294\ub370 \ub9e4\uc6b0 \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \ub2e4\uc74c \ud398\uc5b4\ub54c\ubd80\ud130 \ud39c\uc774\ub791 \uc885\uc774\ub97c \uc900\ube44\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uac00\uac10\uc5c6\uc774 \uc758\uacac\uc744 \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\uc9c4\ud589 \uc0c1\ud669\uc5d0 \ub300\ud55c \ubd80\ubd84, \uc9c4\ud589 \uc18d\ub3c4, \uc9c0\uae08 \uc790\uc2e0\uc774 \uc774\ud574\ud558\uace0 \uc788\ub294 \ubd80\ubd84\uc744 \ub9d0\ud574\uc918\uc11c \ud3b8\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud68c\uace0\ub54c\ub3c4 \uc11c\ub85c \uc194\uc9c1\ud558\uac8c \uc758\uacac\uc744 \uc8fc\uace0 \ubc1b\uc544\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ub3c4\uba54\uc778 \uc5b8\uc5b4\uc5d0 \uc2e0\uacbd\uc4f0\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\ud074\ub798\uc2a4\uba85, \ubcc0\uc218\uba85\uacfc \uac19\uc740 \uc5b8\uc5b4\ub97c \uc138\uc2ec\ud558\uac8c \uc2e0\uacbd\uc4f4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc694\uad6c\uc0ac\ud56d \uc815\ub9ac\ub3c4 \uae54\ub054\ud558\uac8c \uc798\ud558\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\ud6c4\ucd94 \ucd5c\uace0 \ud83d\udc4d"})]})}function p(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(j,{...e})}):j(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function c(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),l=function(e){var r=t.useContext(i),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},j={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},p=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,c=e.originalType,i=e.parentName,p=a(e,["components","mdxType","originalType","parentName"]),b=l(n),h=s,u=b["".concat(i,".").concat(h)]||b[h]||j[h]||c;return n?t.createElement(u,o(o({ref:r},p),{},{components:n})):t.createElement(u,o({ref:r},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/3f6ea930.c12b117e.js b/assets/js/3f6ea930.73dad3b0.js similarity index 97% rename from assets/js/3f6ea930.c12b117e.js rename to assets/js/3f6ea930.73dad3b0.js index e6417dff4..805674a67 100644 --- a/assets/js/3f6ea930.c12b117e.js +++ b/assets/js/3f6ea930.73dad3b0.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5186],{74818:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var t=r(85893),s=r(3905);const a={title:"Parameterized Tests",slug:"parameterized-tests",tags:["Java"]},i=void 0,l={permalink:"/parameterized-tests",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-12-Parameterized Tests.mdx",source:"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx",title:"Parameterized Tests",description:"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.",date:"2023-02-12T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 12\uc77c",tags:[{label:"Java",permalink:"/tags/java"}],readingTime:3.17,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Parameterized Tests",slug:"parameterized-tests",tags:["Java"]},unlisted:!1,prevItem:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",permalink:"/racing-car-retrospective"},nextItem:{title:"IntelliJ \uc124\uc815",permalink:"/intellij-settings"}},c={authorsImageUrls:[]},u=[{value:"Argument Sources",id:"argument-sources",level:2},{value:"Value Source",id:"value-source",level:3},{value:"Null & Empty Source",id:"null--empty-source",level:3},{value:"Enum Source",id:"enum-source",level:3},{value:"CSV Source",id:"csv-source",level:3},{value:"Method Source",id:"method-source",level:3},{value:"ETC.",id:"etc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function o(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ub54c ",(0,t.jsx)(n.code,{children:"@ParameterizedTest"}),"\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e8\uc77c \ud14c\uc2a4\ud2b8\ub97c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \ubc88 \ubc18\ubcf5\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.h2,{id:"argument-sources",children:"Argument Sources"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@ParameterizedTest"}),"\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 Source \uc560\ub178\ud14c\uc774\uc158\uc774 \ud544\uc694\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","JUnit\uc774 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c Source\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0, \ud14c\uc2a4\ud2b8\uc5d0 \ub9de\ucdb0 \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"value-source",children:"Value Source"}),"\n",(0,t.jsx)(n.p,{children:"\uac12\uc744 \uc774\uc6a9\ud558\uc5ec \uc81c\uacf5\ud558\ub294 \ud615\ud0dc\ub85c, \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"short, int, long, float, double"}),"\n",(0,t.jsx)(n.li,{children:"byte, char, boolean, String, Class"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@ValueSource(ints = {1, 100, Integer.MAX_VALUE})\nvoid valueTest(final int value) {\n Assertions.assertThat(value).isPositive();\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"null--empty-source",children:"Null & Empty Source"}),"\n",(0,t.jsxs)(n.p,{children:["null \uac12, \ube48 \uac12\uc744 \uc81c\uacf5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Empty Source\uc758 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc5d0 \ud55c\ud574 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"String"}),"\n",(0,t.jsx)(n.li,{children:"java.util.List, java.util.Set, java.util.Map"}),"\n",(0,t.jsx)(n.li,{children:"primitive arrays \u2014 ex) int[]"}),"\n",(0,t.jsx)(n.li,{children:"object arrays \u2014 ex) String[]"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@NullAndEmptySource\nvoid nullAndEmptyTest(final String value) {\n Assertions.assertThat(value).isNullOrEmpty();\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"enum-source",children:"Enum Source"}),"\n",(0,t.jsx)(n.p,{children:"EnumSource\ub97c \uc774\uc6a9\ud558\uc5ec Enum \ub610\ud55c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"enum Day {\n MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n}\n\n@ParameterizedTest\n@EnumSource(Day.class)\nvoid enumTest(final Day day) {\n assertThat(day).isInstanceOf(Day.class);\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 mode \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b9\uc9d5 Enum\uc744 \uc81c\uc678\ud558\uac70\ub098, \ud3ec\ud568\uc2dc\ud0ac \uc218 \uc788\ub2e4. (default: Mode.Include)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@ParameterizedTest\n@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)\nvoid enumTest(final Day day) {\n // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\n assertThat(day).isInstanceOf(Day.class);\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"csv-source",children:"CSV Source"}),"\n",(0,t.jsxs)(n.p,{children:["csv \ud615\uc2dd\uc758 \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uad6c\ubd84\uc790\uc758 \uae30\ubcf8\uac12\uc740 \uc27c\ud45c(,)\ub85c \uad6c\ubd84\uc790\ub97c \ubcc0\uacbd\ud558\uace0 \uc2f6\uc744 \ub550 delimeter \uac12\uc744 \ub530\ub85c \uc804\ub2ec\ud558\uc5ec \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\n\uac1c\uc778\uc801\uc73c\ub85c 2\uac1c \uc815\ub3c4\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ud558\ub294 \uacbd\uc6b0 CsvSource\ub97c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@ParameterizedTest\n@CsvSource({"1,1", "2,4", "3,9", "4,16"})\nvoid csvTest(final int number, final int result) {\n assertThat(number * number).isEqualTo(result);\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"method-source",children:"Method Source"}),"\n",(0,t.jsxs)(n.p,{children:["\ubcf5\uc7a1\ud55c \ud0c0\uc785\uc758 \uac12\uc744 \uc804\ub2ec\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc\uba85\uc744 \uc785\ub825\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc\uba85\uc744 \ub530\ub85c \uc785\ub825\ud558\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uba85\uacfc \ub3d9\uc77c\ud55c static \uba54\uc11c\ub4dc\uac00 \uc9c0\uc815\ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@MethodSource\nvoid methodTest(final List numbers, final int count) {\n assertThat(numbers).hasSize(count);\n}\n\nprivate static Stream methodTest() {\n return Stream.of(\n Arguments.of(List.of(1), 1),\n Arguments.of(List.of(1, 2), 2),\n Arguments.of(List.of(1, 2, 3), 3)\n );\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"etc",children:"ETC."}),"\n",(0,t.jsx)(n.p,{children:"\uc704\uc5d0\uc11c \uc5b8\uae09\ud55c \ubc29\ubc95 \uc774\uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ubc29\ubc95\uc73c\ub85c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"CSV \ud30c\uc77c\uc744 \uc774\uc6a9\ud55c CsvFileSource"}),"\n",(0,t.jsx)(n.li,{children:"ArgumentsProvider \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \uc774\uc6a9\ud558\ub294 ArgumentsSource"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.baeldung.com/parameterized-tests-junit-5",children:"Guide to JUnit 5 Parameterized Tests"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(o,{...e})}):o(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>u});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var c=t.createContext({}),u=function(e){var n=t.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},o={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,a=e.originalType,c=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),m=u(r),h=s,p=m["".concat(c,".").concat(h)]||m[h]||o[h]||a;return r?t.createElement(p,i(i({ref:n},d),{},{components:r})):t.createElement(p,i({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5186],{74818:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var t=r(85893),s=r(3905);const a={title:"Parameterized Tests",slug:"parameterized-tests",tags:["Java"]},i=void 0,l={permalink:"/parameterized-tests",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-12-Parameterized Tests.mdx",source:"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx",title:"Parameterized Tests",description:"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.",date:"2023-02-12T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 12\uc77c",tags:[{label:"Java",permalink:"/tags/java"}],readingTime:3.17,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Parameterized Tests",slug:"parameterized-tests",tags:["Java"]},unlisted:!1,prevItem:{title:"IntelliJ \uc124\uc815",permalink:"/intellij-settings"},nextItem:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",permalink:"/racing-car-retrospective"}},c={authorsImageUrls:[]},u=[{value:"Argument Sources",id:"argument-sources",level:2},{value:"Value Source",id:"value-source",level:3},{value:"Null & Empty Source",id:"null--empty-source",level:3},{value:"Enum Source",id:"enum-source",level:3},{value:"CSV Source",id:"csv-source",level:3},{value:"Method Source",id:"method-source",level:3},{value:"ETC.",id:"etc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function o(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ub54c ",(0,t.jsx)(n.code,{children:"@ParameterizedTest"}),"\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e8\uc77c \ud14c\uc2a4\ud2b8\ub97c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \ubc88 \ubc18\ubcf5\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.h2,{id:"argument-sources",children:"Argument Sources"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@ParameterizedTest"}),"\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 Source \uc560\ub178\ud14c\uc774\uc158\uc774 \ud544\uc694\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","JUnit\uc774 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c Source\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0, \ud14c\uc2a4\ud2b8\uc5d0 \ub9de\ucdb0 \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"value-source",children:"Value Source"}),"\n",(0,t.jsx)(n.p,{children:"\uac12\uc744 \uc774\uc6a9\ud558\uc5ec \uc81c\uacf5\ud558\ub294 \ud615\ud0dc\ub85c, \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"short, int, long, float, double"}),"\n",(0,t.jsx)(n.li,{children:"byte, char, boolean, String, Class"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@ValueSource(ints = {1, 100, Integer.MAX_VALUE})\nvoid valueTest(final int value) {\n Assertions.assertThat(value).isPositive();\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"null--empty-source",children:"Null & Empty Source"}),"\n",(0,t.jsxs)(n.p,{children:["null \uac12, \ube48 \uac12\uc744 \uc81c\uacf5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Empty Source\uc758 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc5d0 \ud55c\ud574 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"String"}),"\n",(0,t.jsx)(n.li,{children:"java.util.List, java.util.Set, java.util.Map"}),"\n",(0,t.jsx)(n.li,{children:"primitive arrays \u2014 ex) int[]"}),"\n",(0,t.jsx)(n.li,{children:"object arrays \u2014 ex) String[]"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@NullAndEmptySource\nvoid nullAndEmptyTest(final String value) {\n Assertions.assertThat(value).isNullOrEmpty();\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"enum-source",children:"Enum Source"}),"\n",(0,t.jsx)(n.p,{children:"EnumSource\ub97c \uc774\uc6a9\ud558\uc5ec Enum \ub610\ud55c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"enum Day {\n MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n}\n\n@ParameterizedTest\n@EnumSource(Day.class)\nvoid enumTest(final Day day) {\n assertThat(day).isInstanceOf(Day.class);\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 mode \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b9\uc9d5 Enum\uc744 \uc81c\uc678\ud558\uac70\ub098, \ud3ec\ud568\uc2dc\ud0ac \uc218 \uc788\ub2e4. (default: Mode.Include)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@ParameterizedTest\n@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)\nvoid enumTest(final Day day) {\n // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\n assertThat(day).isInstanceOf(Day.class);\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"csv-source",children:"CSV Source"}),"\n",(0,t.jsxs)(n.p,{children:["csv \ud615\uc2dd\uc758 \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uad6c\ubd84\uc790\uc758 \uae30\ubcf8\uac12\uc740 \uc27c\ud45c(,)\ub85c \uad6c\ubd84\uc790\ub97c \ubcc0\uacbd\ud558\uace0 \uc2f6\uc744 \ub550 delimeter \uac12\uc744 \ub530\ub85c \uc804\ub2ec\ud558\uc5ec \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\n\uac1c\uc778\uc801\uc73c\ub85c 2\uac1c \uc815\ub3c4\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ud558\ub294 \uacbd\uc6b0 CsvSource\ub97c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'@ParameterizedTest\n@CsvSource({"1,1", "2,4", "3,9", "4,16"})\nvoid csvTest(final int number, final int result) {\n assertThat(number * number).isEqualTo(result);\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"method-source",children:"Method Source"}),"\n",(0,t.jsxs)(n.p,{children:["\ubcf5\uc7a1\ud55c \ud0c0\uc785\uc758 \uac12\uc744 \uc804\ub2ec\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc\uba85\uc744 \uc785\ub825\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba54\uc11c\ub4dc\uba85\uc744 \ub530\ub85c \uc785\ub825\ud558\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uba85\uacfc \ub3d9\uc77c\ud55c static \uba54\uc11c\ub4dc\uac00 \uc9c0\uc815\ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"@ParameterizedTest\n@MethodSource\nvoid methodTest(final List numbers, final int count) {\n assertThat(numbers).hasSize(count);\n}\n\nprivate static Stream methodTest() {\n return Stream.of(\n Arguments.of(List.of(1), 1),\n Arguments.of(List.of(1, 2), 2),\n Arguments.of(List.of(1, 2, 3), 3)\n );\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"etc",children:"ETC."}),"\n",(0,t.jsx)(n.p,{children:"\uc704\uc5d0\uc11c \uc5b8\uae09\ud55c \ubc29\ubc95 \uc774\uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ubc29\ubc95\uc73c\ub85c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"CSV \ud30c\uc77c\uc744 \uc774\uc6a9\ud55c CsvFileSource"}),"\n",(0,t.jsx)(n.li,{children:"ArgumentsProvider \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \uc774\uc6a9\ud558\ub294 ArgumentsSource"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.baeldung.com/parameterized-tests-junit-5",children:"Guide to JUnit 5 Parameterized Tests"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(o,{...e})}):o(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>u});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var c=t.createContext({}),u=function(e){var n=t.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},o={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,a=e.originalType,c=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),m=u(r),h=s,p=m["".concat(c,".").concat(h)]||m[h]||o[h]||a;return r?t.createElement(p,i(i({ref:n},d),{},{components:r})):t.createElement(p,i({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/42957a8d.205e0091.js b/assets/js/42957a8d.f8fb5118.js similarity index 97% rename from assets/js/42957a8d.205e0091.js rename to assets/js/42957a8d.f8fb5118.js index 85c1e9490..508399043 100644 --- a/assets/js/42957a8d.205e0091.js +++ b/assets/js/42957a8d.f8fb5118.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9312],{62206:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var n=r(85893),o=r(3905);const c={title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",slug:"mock-static-method",tags:["Mockito","static"]},i=void 0,a={permalink:"/mock-static-method",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",source:"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",description:"\uac1c\uc694",date:"2023-07-30T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 30\uc77c",tags:[{label:"Mockito",permalink:"/tags/mockito"},{label:"static",permalink:"/tags/static"}],readingTime:2.635,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",slug:"mock-static-method",tags:["Mockito","static"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",permalink:"/route-image-python"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",permalink:"/route-image-intro"}},s={authorsImageUrls:[]},l=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"Mocking static methods",id:"mocking-static-methods",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function m(e){const t={a:"a",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,n.jsxs)(t.p,{children:["\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud55c\ub2e4\ub294 \uac83\uc740 \uac1d\uccb4\uc9c0\ud5a5\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ubcfc \ub54c \uc548\ud2f0\ud328\ud134\uc774\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ud2b9\uc218\ud55c \uacbd\uc6b0\uc5d0\ub294 \uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc774 \ud544\uc694\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:"\uc608\ub97c \ub4e4\uc5b4 \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud55c\ub2e4\ub358\uc9c0, IO \uad00\ub828\ud55c \ubd80\ubd84\uc744 \ud14c\uc2a4\ud2b8 \ud560 \ub54c \uc815\ub9d0 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\ub9cc \uc801\uc6a9\ud560 \uc218 \uc788\uc744 \uac83\uc774\ub2e4."}),"\n",(0,n.jsxs)(t.p,{children:["\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba70 ImageIo.write \uba54\uc11c\ub4dc\uac00 \ud638\ucd9c\ub418\ub294 \uc9c0 \uac80\uc99d\uc774 \ud544\uc694\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud574\ub2f9 static \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294 \ubd80\ubd84\uc744 \ub530\ub85c RouteImageUploader \ud074\ub798\uc2a4\ub85c \ucd5c\ub300\ud55c \ubd84\ub9ac\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc800\uc7a5 \uae30\ub2a5 \uc790\uccb4\uac00 \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc774\uace0, \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294\ub370\ub294 mock\uc744 \uc0ac\uc6a9\ud558\ub294\uac8c \uc801\uc808\ud558\ub2e4\uace0 \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",children:"public void upload(BufferedImage bufferedImage) {\n File file = new File(\ud30c\uc77c\uacbd\ub85c);\n try {\n ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);\n } catch (IOException e) {\n throw new DrawException(IMAGE_SAVE_FAIL);\n }\n}\n"})}),"\n",(0,n.jsx)(t.h3,{id:"mocking-static-methods",children:"Mocking static methods"}),"\n",(0,n.jsxs)(t.p,{children:["Mockito 3.4.0 \uc774\ud6c4\uc5d0\ub294 static method\ub97c \ubaa8\ud0b9\ud560 \uc218 \uc788\ub294 Mockito.mockStatic \uba54\uc11c\ub4dc\ub97c \uc9c0\uc6d0\ud55c\ub2e4.",(0,n.jsx)(t.br,{}),"\n","mockStatic\uc744 \uc0ac\uc6a9\ud558\uba74 ",(0,n.jsx)(t.code,{children:"MockedStatic"}),"\uc774 \ubc18\ud658\ub418\ub294\ub370 \uc0ac\uc6a9 \ud6c4 \uaf2d close\ub97c \ud574\uc918\uc57c \ud55c\ub2e4."]}),"\n",(0,n.jsxs)(t.p,{children:["JUnit\uc758 @BeforeAll\ub85c \uc124\uc815\ud558\uace0 @AfterAll \uba54\uc11c\ub4dc\ub85c \uc885\ub8cc\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\uc9c0\ub9cc ",(0,n.jsx)(t.code,{children:"MockedStatic"}),"\uc758 \uc0c1\uc704 \uc778\ud130\ud398\uc774\uc2a4\uc778 ScopedMock\uc774 AutoCloseable\uc744 \uad6c\ud604\ud558\uace0 \uc788\uae30\uc5d0 try-with-resources\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \ub354\uc6b1 \uc88b\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",children:"// given\nBufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);\nRouteImageUploader routeImageUploader = new RouteImageUploader();\n\n// expect\ntry (MockedStatic imageIO = Mockito.mockStatic(ImageIO.class)) {\n routeImageUploader.upload(bufferedImage);\n imageIO.verify(\n () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),\n times(1)\n );\n}\n"})}),"\n",(0,n.jsx)(t.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,n.jsxs)(t.p,{children:["\uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc740 \uc548\ud2f0\ud328\ud134\uc774\uc73c\ub85c \uc801\uc808\ud55c \ucd94\uc0c1\ud654\ub97c \uc774\uc6a9\ud574 \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc88b\uc740 \ucf54\ub4dc\ub97c \ub9cc\ub4dc\ub294 \uc5f0\uc2b5\uc744 \ud558\uc790.",(0,n.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ucd94\uc0c1\ud654\ub97c \ud558\uba74 \ud560 \uc218\ub85d \ucf54\ub4dc\uc758 \ubcf5\uc7a1\ub3c4\ub294 \uc99d\uac00\ud55c\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud56d\uc0c1 \uc0c1\ud669\uc744 \uace0\ub824\ud558\uace0 \uac04\uacb0\ud568\uc744 \ud3ec\uae30\ud560 \ub9cc\ud07c \uc911\uc694\ud55c \ubd80\ubd84\uc778\uc9c0 \uc801\uc808\ud55c \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uace0\ub824\ud558\uc790."]}),"\n",(0,n.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks",children:"Mocking static methods"}),(0,n.jsx)(t.br,{}),"\n",(0,n.jsx)(t.a,{href:"https://www.baeldung.com/mockito-mock-static-methods",children:"Mockito mock static methods"}),(0,n.jsx)(t.br,{}),"\n",(0,n.jsx)(t.a,{href:"https://github.com/mockito/mockito/issues/1013",children:"Enable mocking static methods in Mockito"})]})]})}function d(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(m,{...e})}):m(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,d=a(e,["components","mdxType","originalType","parentName"]),u=l(r),p=o,g=u["".concat(s,".").concat(p)]||u[p]||m[p]||c;return r?n.createElement(g,i(i({ref:t},d),{},{components:r})):n.createElement(g,i({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9312],{62206:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var n=r(85893),o=r(3905);const c={title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",slug:"mock-static-method",tags:["Mockito","static"]},i=void 0,a={permalink:"/mock-static-method",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",source:"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",description:"\uac1c\uc694",date:"2023-07-30T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 30\uc77c",tags:[{label:"Mockito",permalink:"/tags/mockito"},{label:"static",permalink:"/tags/static"}],readingTime:2.635,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",slug:"mock-static-method",tags:["Mockito","static"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",permalink:"/route-image-intro"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",permalink:"/route-image-python"}},s={authorsImageUrls:[]},l=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"Mocking static methods",id:"mocking-static-methods",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function m(e){const t={a:"a",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,n.jsxs)(t.p,{children:["\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud55c\ub2e4\ub294 \uac83\uc740 \uac1d\uccb4\uc9c0\ud5a5\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ubcfc \ub54c \uc548\ud2f0\ud328\ud134\uc774\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ud2b9\uc218\ud55c \uacbd\uc6b0\uc5d0\ub294 \uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc774 \ud544\uc694\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:"\uc608\ub97c \ub4e4\uc5b4 \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud55c\ub2e4\ub358\uc9c0, IO \uad00\ub828\ud55c \ubd80\ubd84\uc744 \ud14c\uc2a4\ud2b8 \ud560 \ub54c \uc815\ub9d0 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\ub9cc \uc801\uc6a9\ud560 \uc218 \uc788\uc744 \uac83\uc774\ub2e4."}),"\n",(0,n.jsxs)(t.p,{children:["\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba70 ImageIo.write \uba54\uc11c\ub4dc\uac00 \ud638\ucd9c\ub418\ub294 \uc9c0 \uac80\uc99d\uc774 \ud544\uc694\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud574\ub2f9 static \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294 \ubd80\ubd84\uc744 \ub530\ub85c RouteImageUploader \ud074\ub798\uc2a4\ub85c \ucd5c\ub300\ud55c \ubd84\ub9ac\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc800\uc7a5 \uae30\ub2a5 \uc790\uccb4\uac00 \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc774\uace0, \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294\ub370\ub294 mock\uc744 \uc0ac\uc6a9\ud558\ub294\uac8c \uc801\uc808\ud558\ub2e4\uace0 \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",children:"public void upload(BufferedImage bufferedImage) {\n File file = new File(\ud30c\uc77c\uacbd\ub85c);\n try {\n ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);\n } catch (IOException e) {\n throw new DrawException(IMAGE_SAVE_FAIL);\n }\n}\n"})}),"\n",(0,n.jsx)(t.h3,{id:"mocking-static-methods",children:"Mocking static methods"}),"\n",(0,n.jsxs)(t.p,{children:["Mockito 3.4.0 \uc774\ud6c4\uc5d0\ub294 static method\ub97c \ubaa8\ud0b9\ud560 \uc218 \uc788\ub294 Mockito.mockStatic \uba54\uc11c\ub4dc\ub97c \uc9c0\uc6d0\ud55c\ub2e4.",(0,n.jsx)(t.br,{}),"\n","mockStatic\uc744 \uc0ac\uc6a9\ud558\uba74 ",(0,n.jsx)(t.code,{children:"MockedStatic"}),"\uc774 \ubc18\ud658\ub418\ub294\ub370 \uc0ac\uc6a9 \ud6c4 \uaf2d close\ub97c \ud574\uc918\uc57c \ud55c\ub2e4."]}),"\n",(0,n.jsxs)(t.p,{children:["JUnit\uc758 @BeforeAll\ub85c \uc124\uc815\ud558\uace0 @AfterAll \uba54\uc11c\ub4dc\ub85c \uc885\ub8cc\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\uc9c0\ub9cc ",(0,n.jsx)(t.code,{children:"MockedStatic"}),"\uc758 \uc0c1\uc704 \uc778\ud130\ud398\uc774\uc2a4\uc778 ScopedMock\uc774 AutoCloseable\uc744 \uad6c\ud604\ud558\uace0 \uc788\uae30\uc5d0 try-with-resources\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \ub354\uc6b1 \uc88b\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",children:"// given\nBufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);\nRouteImageUploader routeImageUploader = new RouteImageUploader();\n\n// expect\ntry (MockedStatic imageIO = Mockito.mockStatic(ImageIO.class)) {\n routeImageUploader.upload(bufferedImage);\n imageIO.verify(\n () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),\n times(1)\n );\n}\n"})}),"\n",(0,n.jsx)(t.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,n.jsxs)(t.p,{children:["\uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc740 \uc548\ud2f0\ud328\ud134\uc774\uc73c\ub85c \uc801\uc808\ud55c \ucd94\uc0c1\ud654\ub97c \uc774\uc6a9\ud574 \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc88b\uc740 \ucf54\ub4dc\ub97c \ub9cc\ub4dc\ub294 \uc5f0\uc2b5\uc744 \ud558\uc790.",(0,n.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ucd94\uc0c1\ud654\ub97c \ud558\uba74 \ud560 \uc218\ub85d \ucf54\ub4dc\uc758 \ubcf5\uc7a1\ub3c4\ub294 \uc99d\uac00\ud55c\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud56d\uc0c1 \uc0c1\ud669\uc744 \uace0\ub824\ud558\uace0 \uac04\uacb0\ud568\uc744 \ud3ec\uae30\ud560 \ub9cc\ud07c \uc911\uc694\ud55c \ubd80\ubd84\uc778\uc9c0 \uc801\uc808\ud55c \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uace0\ub824\ud558\uc790."]}),"\n",(0,n.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks",children:"Mocking static methods"}),(0,n.jsx)(t.br,{}),"\n",(0,n.jsx)(t.a,{href:"https://www.baeldung.com/mockito-mock-static-methods",children:"Mockito mock static methods"}),(0,n.jsx)(t.br,{}),"\n",(0,n.jsx)(t.a,{href:"https://github.com/mockito/mockito/issues/1013",children:"Enable mocking static methods in Mockito"})]})]})}function d(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(m,{...e})}):m(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,d=a(e,["components","mdxType","originalType","parentName"]),u=l(r),p=o,g=u["".concat(s,".").concat(p)]||u[p]||m[p]||c;return r?n.createElement(g,i(i({ref:t},d),{},{components:r})):n.createElement(g,i({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/4485017c.9559a624.js b/assets/js/4485017c.34771f44.js similarity index 97% rename from assets/js/4485017c.9559a624.js rename to assets/js/4485017c.34771f44.js index 04cbb7def..78da2ffd4 100644 --- a/assets/js/4485017c.9559a624.js +++ b/assets/js/4485017c.34771f44.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1906],{36169:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var t=n(85893),s=n(3905);const c={title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",slug:"blackjack-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,a={permalink:"/blackjack-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-blackjack/pull/427",date:"2023-03-14T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 14\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.17,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",slug:"blackjack-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",permalink:"/grasp"},nextItem:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",permalink:"/ladder-retrospective"}},i={authorsImageUrls:[]},l=[{value:"\ube14\ub799\uc7ad",id:"\ube14\ub799\uc7ad",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function j(e){const r={a:"a",admonition:"admonition",br:"br",h3:"h3",p:"p",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-blackjack/pull/427",children:"https://github.com/woowacourse/java-blackjack/pull/427"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-blackjack/pull/537",children:"https://github.com/woowacourse/java-blackjack/pull/537"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\ube14\ub799\uc7ad",children:"\ube14\ub799\uc7ad"}),"\n",(0,t.jsxs)(r.p,{children:["\ube14\ub799\uc7ad \ubbf8\uc158\uc5d0\uc11c\ub294 \ud6c4\ucd94\uc640 \ud398\uc5b4(\uc870\ubbf8\ub8cc \ub4c0\uc624?)\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \uc2e4\uc218\ud558\uc9c0 \uc54a\uace0, \ubc14\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uc9c0 \uc54a\uace0 \uce5c\ud574\uc9c0\uae30 \ubd80\ud130 \uc2dc\uc791\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ube14\ub799\uc7ad\uc740 \uad6c\ud604\ud574\uc57c \ub420 \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud560 \uac83 \uac19\uc558\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\ud6c4\ucd94\uc640 \ud568\uaed8 \uc804\ub7b5\uc801(\uc0bc\uc77c\uc808\uc5d0 \ubbf8\uc158 \uc774\uc57c\uae30 \ub098\ub204\uae30)\uc73c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud574 \uc2dc\uac04 \ub0b4\uc5d0 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ubbf8\uc158\uc744 \ub05d\ub098\uace0 \ud68c\uace0\ub97c \ud588\uc744 \ub54c \ud6c4\ucd94\uac00 \uace0\ubbfc\uac70\ub9ac\ub97c \ud558\ub098 \ub0b4\uc92c\ub2e4.",(0,t.jsx)(r.br,{}),"\n",'"\ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \uc555\ubc15\uac10\uc744 \ub290\ub07c\ub294 \ud398\uc5b4\uac00 \uc788\ub2e4\uba74 \ud5c8\ube0c\uac00 \ud574\uc904 \uc218 \uc788\ub294\uac8c \ubb50\uac00 \uc788\uc744\uae4c?"']}),"\n",(0,t.jsxs)(r.p,{children:["\uacf0\uacf0\ud788 \uc0dd\uac01\ud574\ubd24\uc9c0\ub9cc \uc27d\uac8c \ub2f5\uc744 \ub0b4\ub9b4 \uc218 \uc5c6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ud68c\uace0\ub97c \ud558\uace0, \ub098\uc758 \uc18c\ud504\ud2b8\uc2a4\ud0ac\uc744 \ub192\ud788\ub294\uac8c \ub2f5\uc77c\uae4c?",(0,t.jsx)(r.br,{}),"\n","\ubd80\ub2f4\uac10\uc744 \ub290\ub07c\uc9c0 \uc54a\uace0 \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub420 \uc218 \uc788\ub3c4\ub85d \uacc4\uc18d \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc0dd\uac01\uc774 \ub9ce\uc544\uc838\uc11c \uc804 \ub9ac\ubdf0\uc5b4\uc778 \ud130\ud2c0\ud83d\udc22\uacfc\ub3c4 \ub300\ud654\ub97c \ub098\ub204\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud130\ud2c0\uc740 \uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84(\uad81\uadf9\uc801\uc778 \ubaa9\ud45c\uc778 \uc88b\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uac83)\uc5d0 \uc9d1\uc911\ud574\ubcf4\ub77c\uace0 \ud558\uc168\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\uc88b\uc740 \ucf54\ub4dc, \uc88b\uc740 \ud398\uc5b4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc77c\ub2e8 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ud398\uc5b4 \uc2e0\uacbd\uc4f0\uae30"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ud398\uc5b4\ud560 \ub54c \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub0b4\ubcf4\ub3c4\ub85d \ud588\ub2e4. \uadf8\ub807\uae30\uc5d0 \ub108\ubb34 \uc758\uacac\uc744 \uac15\ud558\uac8c \ubc00\uc5b4\ubd99\uc778 \ub290\ub08c\uc774 \ub4e4\uc5b4\uc11c \ubbf8\uc548\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud6c4\ucd94\uac00 \uc555\ubc15\uc744 \ub290\uaf08\uc744 \uc218\ub3c4 \uc788\uc744 \uac83 \uac19\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \uc791\uc740 \ud68c\uace0\ub97c \uc9c4\ud589\ud574\ubcf4\ub294 \uac83\uc774 \uc88b\uc744\uae4c?"]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uccb4\ub825 \uad00\ub9ac"}),(0,t.jsx)(r.br,{}),"\n","\uc694\uc998 \uc798 \ubabb\uba39\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc0b4 \ub0a0\uc774 \ub9ce\uc740\ub370 \uc798 \ucc59\uaca8\uba39\uace0, \ud798\ub0b4\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc911\uac04 \uc911\uac04 \ub3cc\uc544\ubcf4\uae30"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ubbf8\uc158\uacfc \uad00\ub828\ub41c \ub0b4\uc6a9\uc740 \uc544\ub2c8\uc9c0\ub9cc \uc6b0\ud14c\ucf54\ub97c \uc798 \ud65c\uc6a9 \ud558\uace0 \uc788\ub294\uc9c0 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \uc6b0\ud14c\ucf54\uc5d0 \uc9c0\uc6d0\ud55c \uc774\uc720\ub97c \ud56d\uc0c1 \uc78a\uc9c0 \uc54a\uc544\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc0c1\ud0dc \ud328\ud134"}),(0,t.jsx)(r.br,{}),"\n","\uac1d\uccb4\uc758 \ub0b4\ubd80 \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc2a4\uc2a4\ub85c \ud589\ub3d9\uc744 \ubcc0\uacbd\ud558\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc73c\ub85c if/else/switch\uc640 \uac19\uc740 \uc870\uac74\ubb38\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \uc81c\uac70\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube14\ub799\uc7ad \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc0c1\ud0dc \ud328\ud134\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ucc98\uc74c \uc801\uc6a9\ud574\ubcf4\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucc98\uc74c \uc801\uc6a9\ud558\uae30 \uc804\uc5d0\ub294 \ubcc4\ub85c\ub77c\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc0dd\uac01\ubcf4\ub2e4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc77c\uad00\uc131, \uac00\ub3c5\uc131, \ucd94\uc0c1\ud654"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ub9ac\ubdf0\uc5b4\ub294 \uac80\ud504\ud83c\udf6b \uc600\ub2e4!",(0,t.jsx)(r.br,{}),"\n","\uac80\ud504\uc758 \ub9ac\ubdf0\ub294 \uac04\uacb0\ud568\uc5d0 \uad00\ub828\ub41c \ub0b4\uc6a9\uc774 \ub9ce\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc77c\uad00\uc131\uc774 \uc788\ub294 \ucf54\ub4dc, \uac00\ub3c5\uc131\uc774 \uc88b\uc740 \ucf54\ub4dc, \ucd94\uc0c1\ud654\uac00 \uc798 \ub418\uc5b4\uc788\ub294 \ucf54\ub4dc",(0,t.jsx)(r.br,{}),"\n","\uc77d\uae30 \uc88b\uace0, \uac04\uacb0\ud55c \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b4 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucf54\ub4dc\ub97c \ubc14\ub77c\ubcf4\ub294 \uc2dc\uc810\uc774 \ud558\ub098 \ub298\uc5b4\ub09c \uae30\ubd84\uc774\ub2e4!(\uc55e\uc73c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc740 \ub098\uc758 \ubaab\uc774\uc9c0\ub9cc)"]}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc0dd\uac01 \uc815\ub9ac"}),(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ud604\uc7ac \uc0c1\ud669\uc5d0 \ub300\ud574 \uadf8\ub9bc\uc744 \uadf8\ub9ac\uac70\ub098, \uae00\uc744 \uc801\uc73c\uba74\uc11c \uc815\ub9ac\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud398\uc5b4\uc640 \ub3d9\uc77c\ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc9c4\ud589\ud558\ub294\ub370 \ub9e4\uc6b0 \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \ub2e4\uc74c \ud398\uc5b4\ub54c\ubd80\ud130 \ud39c\uc774\ub791 \uc885\uc774\ub97c \uc900\ube44\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uac00\uac10\uc5c6\uc774 \uc758\uacac\uc744 \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\uc9c4\ud589 \uc0c1\ud669\uc5d0 \ub300\ud55c \ubd80\ubd84, \uc9c4\ud589 \uc18d\ub3c4, \uc9c0\uae08 \uc790\uc2e0\uc774 \uc774\ud574\ud558\uace0 \uc788\ub294 \ubd80\ubd84\uc744 \ub9d0\ud574\uc918\uc11c \ud3b8\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud68c\uace0\ub54c\ub3c4 \uc11c\ub85c \uc194\uc9c1\ud558\uac8c \uc758\uacac\uc744 \uc8fc\uace0 \ubc1b\uc544\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ub3c4\uba54\uc778 \uc5b8\uc5b4\uc5d0 \uc2e0\uacbd\uc4f0\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\ud074\ub798\uc2a4\uba85, \ubcc0\uc218\uba85\uacfc \uac19\uc740 \uc5b8\uc5b4\ub97c \uc138\uc2ec\ud558\uac8c \uc2e0\uacbd\uc4f4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc694\uad6c\uc0ac\ud56d \uc815\ub9ac\ub3c4 \uae54\ub054\ud558\uac8c \uc798\ud558\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\ud6c4\ucd94 \ucd5c\uace0 \ud83d\udc4d"})]})}function p(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(j,{...e})}):j(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function c(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),l=function(e){var r=t.useContext(i),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},j={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},p=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,c=e.originalType,i=e.parentName,p=a(e,["components","mdxType","originalType","parentName"]),b=l(n),h=s,u=b["".concat(i,".").concat(h)]||b[h]||j[h]||c;return n?t.createElement(u,o(o({ref:r},p),{},{components:n})):t.createElement(u,o({ref:r},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1906],{36169:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var t=n(85893),s=n(3905);const c={title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",slug:"blackjack-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,a={permalink:"/blackjack-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-blackjack/pull/427",date:"2023-03-14T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 14\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.17,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",slug:"blackjack-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",permalink:"/ladder-retrospective"},nextItem:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",permalink:"/grasp"}},i={authorsImageUrls:[]},l=[{value:"\ube14\ub799\uc7ad",id:"\ube14\ub799\uc7ad",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function j(e){const r={a:"a",admonition:"admonition",br:"br",h3:"h3",p:"p",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-blackjack/pull/427",children:"https://github.com/woowacourse/java-blackjack/pull/427"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-blackjack/pull/537",children:"https://github.com/woowacourse/java-blackjack/pull/537"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\ube14\ub799\uc7ad",children:"\ube14\ub799\uc7ad"}),"\n",(0,t.jsxs)(r.p,{children:["\ube14\ub799\uc7ad \ubbf8\uc158\uc5d0\uc11c\ub294 \ud6c4\ucd94\uc640 \ud398\uc5b4(\uc870\ubbf8\ub8cc \ub4c0\uc624?)\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \uc2e4\uc218\ud558\uc9c0 \uc54a\uace0, \ubc14\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uc9c0 \uc54a\uace0 \uce5c\ud574\uc9c0\uae30 \ubd80\ud130 \uc2dc\uc791\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ube14\ub799\uc7ad\uc740 \uad6c\ud604\ud574\uc57c \ub420 \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud560 \uac83 \uac19\uc558\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\ud6c4\ucd94\uc640 \ud568\uaed8 \uc804\ub7b5\uc801(\uc0bc\uc77c\uc808\uc5d0 \ubbf8\uc158 \uc774\uc57c\uae30 \ub098\ub204\uae30)\uc73c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud574 \uc2dc\uac04 \ub0b4\uc5d0 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ubbf8\uc158\uc744 \ub05d\ub098\uace0 \ud68c\uace0\ub97c \ud588\uc744 \ub54c \ud6c4\ucd94\uac00 \uace0\ubbfc\uac70\ub9ac\ub97c \ud558\ub098 \ub0b4\uc92c\ub2e4.",(0,t.jsx)(r.br,{}),"\n",'"\ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \uc555\ubc15\uac10\uc744 \ub290\ub07c\ub294 \ud398\uc5b4\uac00 \uc788\ub2e4\uba74 \ud5c8\ube0c\uac00 \ud574\uc904 \uc218 \uc788\ub294\uac8c \ubb50\uac00 \uc788\uc744\uae4c?"']}),"\n",(0,t.jsxs)(r.p,{children:["\uacf0\uacf0\ud788 \uc0dd\uac01\ud574\ubd24\uc9c0\ub9cc \uc27d\uac8c \ub2f5\uc744 \ub0b4\ub9b4 \uc218 \uc5c6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ud68c\uace0\ub97c \ud558\uace0, \ub098\uc758 \uc18c\ud504\ud2b8\uc2a4\ud0ac\uc744 \ub192\ud788\ub294\uac8c \ub2f5\uc77c\uae4c?",(0,t.jsx)(r.br,{}),"\n","\ubd80\ub2f4\uac10\uc744 \ub290\ub07c\uc9c0 \uc54a\uace0 \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub420 \uc218 \uc788\ub3c4\ub85d \uacc4\uc18d \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc0dd\uac01\uc774 \ub9ce\uc544\uc838\uc11c \uc804 \ub9ac\ubdf0\uc5b4\uc778 \ud130\ud2c0\ud83d\udc22\uacfc\ub3c4 \ub300\ud654\ub97c \ub098\ub204\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud130\ud2c0\uc740 \uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84(\uad81\uadf9\uc801\uc778 \ubaa9\ud45c\uc778 \uc88b\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uac83)\uc5d0 \uc9d1\uc911\ud574\ubcf4\ub77c\uace0 \ud558\uc168\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\uc88b\uc740 \ucf54\ub4dc, \uc88b\uc740 \ud398\uc5b4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc77c\ub2e8 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ud398\uc5b4 \uc2e0\uacbd\uc4f0\uae30"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ud398\uc5b4\ud560 \ub54c \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub0b4\ubcf4\ub3c4\ub85d \ud588\ub2e4. \uadf8\ub807\uae30\uc5d0 \ub108\ubb34 \uc758\uacac\uc744 \uac15\ud558\uac8c \ubc00\uc5b4\ubd99\uc778 \ub290\ub08c\uc774 \ub4e4\uc5b4\uc11c \ubbf8\uc548\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud6c4\ucd94\uac00 \uc555\ubc15\uc744 \ub290\uaf08\uc744 \uc218\ub3c4 \uc788\uc744 \uac83 \uac19\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \uc791\uc740 \ud68c\uace0\ub97c \uc9c4\ud589\ud574\ubcf4\ub294 \uac83\uc774 \uc88b\uc744\uae4c?"]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uccb4\ub825 \uad00\ub9ac"}),(0,t.jsx)(r.br,{}),"\n","\uc694\uc998 \uc798 \ubabb\uba39\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc0b4 \ub0a0\uc774 \ub9ce\uc740\ub370 \uc798 \ucc59\uaca8\uba39\uace0, \ud798\ub0b4\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc911\uac04 \uc911\uac04 \ub3cc\uc544\ubcf4\uae30"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ubbf8\uc158\uacfc \uad00\ub828\ub41c \ub0b4\uc6a9\uc740 \uc544\ub2c8\uc9c0\ub9cc \uc6b0\ud14c\ucf54\ub97c \uc798 \ud65c\uc6a9 \ud558\uace0 \uc788\ub294\uc9c0 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \uc6b0\ud14c\ucf54\uc5d0 \uc9c0\uc6d0\ud55c \uc774\uc720\ub97c \ud56d\uc0c1 \uc78a\uc9c0 \uc54a\uc544\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc0c1\ud0dc \ud328\ud134"}),(0,t.jsx)(r.br,{}),"\n","\uac1d\uccb4\uc758 \ub0b4\ubd80 \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc2a4\uc2a4\ub85c \ud589\ub3d9\uc744 \ubcc0\uacbd\ud558\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc73c\ub85c if/else/switch\uc640 \uac19\uc740 \uc870\uac74\ubb38\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \uc81c\uac70\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube14\ub799\uc7ad \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc0c1\ud0dc \ud328\ud134\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ucc98\uc74c \uc801\uc6a9\ud574\ubcf4\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucc98\uc74c \uc801\uc6a9\ud558\uae30 \uc804\uc5d0\ub294 \ubcc4\ub85c\ub77c\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc0dd\uac01\ubcf4\ub2e4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc77c\uad00\uc131, \uac00\ub3c5\uc131, \ucd94\uc0c1\ud654"}),(0,t.jsx)(r.br,{}),"\n","\uc774\ubc88 \ub9ac\ubdf0\uc5b4\ub294 \uac80\ud504\ud83c\udf6b \uc600\ub2e4!",(0,t.jsx)(r.br,{}),"\n","\uac80\ud504\uc758 \ub9ac\ubdf0\ub294 \uac04\uacb0\ud568\uc5d0 \uad00\ub828\ub41c \ub0b4\uc6a9\uc774 \ub9ce\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc77c\uad00\uc131\uc774 \uc788\ub294 \ucf54\ub4dc, \uac00\ub3c5\uc131\uc774 \uc88b\uc740 \ucf54\ub4dc, \ucd94\uc0c1\ud654\uac00 \uc798 \ub418\uc5b4\uc788\ub294 \ucf54\ub4dc",(0,t.jsx)(r.br,{}),"\n","\uc77d\uae30 \uc88b\uace0, \uac04\uacb0\ud55c \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b4 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucf54\ub4dc\ub97c \ubc14\ub77c\ubcf4\ub294 \uc2dc\uc810\uc774 \ud558\ub098 \ub298\uc5b4\ub09c \uae30\ubd84\uc774\ub2e4!(\uc55e\uc73c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc740 \ub098\uc758 \ubaab\uc774\uc9c0\ub9cc)"]}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uc0dd\uac01 \uc815\ub9ac"}),(0,t.jsx)(r.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ud604\uc7ac \uc0c1\ud669\uc5d0 \ub300\ud574 \uadf8\ub9bc\uc744 \uadf8\ub9ac\uac70\ub098, \uae00\uc744 \uc801\uc73c\uba74\uc11c \uc815\ub9ac\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud398\uc5b4\uc640 \ub3d9\uc77c\ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc9c4\ud589\ud558\ub294\ub370 \ub9e4\uc6b0 \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \ub2e4\uc74c \ud398\uc5b4\ub54c\ubd80\ud130 \ud39c\uc774\ub791 \uc885\uc774\ub97c \uc900\ube44\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\uac00\uac10\uc5c6\uc774 \uc758\uacac\uc744 \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\uc9c4\ud589 \uc0c1\ud669\uc5d0 \ub300\ud55c \ubd80\ubd84, \uc9c4\ud589 \uc18d\ub3c4, \uc9c0\uae08 \uc790\uc2e0\uc774 \uc774\ud574\ud558\uace0 \uc788\ub294 \ubd80\ubd84\uc744 \ub9d0\ud574\uc918\uc11c \ud3b8\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud68c\uace0\ub54c\ub3c4 \uc11c\ub85c \uc194\uc9c1\ud558\uac8c \uc758\uacac\uc744 \uc8fc\uace0 \ubc1b\uc544\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ub3c4\uba54\uc778 \uc5b8\uc5b4\uc5d0 \uc2e0\uacbd\uc4f0\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\ud074\ub798\uc2a4\uba85, \ubcc0\uc218\uba85\uacfc \uac19\uc740 \uc5b8\uc5b4\ub97c \uc138\uc2ec\ud558\uac8c \uc2e0\uacbd\uc4f4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc694\uad6c\uc0ac\ud56d \uc815\ub9ac\ub3c4 \uae54\ub054\ud558\uac8c \uc798\ud558\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\ud6c4\ucd94 \ucd5c\uace0 \ud83d\udc4d"})]})}function p(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(j,{...e})}):j(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function c(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),l=function(e){var r=t.useContext(i),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},j={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},p=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,c=e.originalType,i=e.parentName,p=a(e,["components","mdxType","originalType","parentName"]),b=l(n),h=s,u=b["".concat(i,".").concat(h)]||b[h]||j[h]||c;return n?t.createElement(u,o(o({ref:r},p),{},{components:n})):t.createElement(u,o({ref:r},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/448c20a0.1a72b6ca.js b/assets/js/448c20a0.55a75d0f.js similarity index 97% rename from assets/js/448c20a0.1a72b6ca.js rename to assets/js/448c20a0.55a75d0f.js index 227192c91..998042032 100644 --- a/assets/js/448c20a0.1a72b6ca.js +++ b/assets/js/448c20a0.55a75d0f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7680],{14079:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var r=n(85893),s=n(3905);const i={title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",slug:"spring-test-isolation",tags:["test"]},a=void 0,o={permalink:"/spring-test-isolation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",source:"@site/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",description:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac",date:"2023-10-03T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 3\uc77c",tags:[{label:"test",permalink:"/tags/test"}],readingTime:4.315,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",slug:"spring-test-isolation",tags:["test"]},unlisted:!1,prevItem:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/mvc-retrospective"},nextItem:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",permalink:"/web-application-evolution"}},c={authorsImageUrls:[]},l=[{value:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac",id:"\ud14c\uc2a4\ud2b8-\uaca9\ub9ac",level:3},{value:"TestExecutionListener",id:"testexecutionlistener",level:3},{value:"AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604",id:"abstracttestexecutionlistener-\uc0c1\uc18d\ud558\uc5ec-\uad6c\ud604",level:3},{value:"Listener \ub4f1\ub85d",id:"listener-\ub4f1\ub85d",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\ud14c\uc2a4\ud2b8-\uaca9\ub9ac",children:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac"}),"\n",(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8\uc758 \uc21c\uc11c\uc5d0 \ub530\ub77c \uc131\uacf5 \uc2e4\ud328 \uc5ec\ubd80\uac00 \uacb0\uc815\ub418\ub294 \ube44\uacb0\uc815\uc801\uc778(non-determinism) \ud14c\uc2a4\ud2b8\uac00 \ub418\uc5b4\uc11c\ub294 \uc548\ub418\uace0, \ud14c\uc2a4\ud2b8\ub294 \ud56d\uc0c1 \uc21c\uc11c\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc218\ud589\ub418\ub3c4\ub85d \ubcf4\uc7a5\ub418\uc5b4\uc57c \ud55c\ub2e4. \uc77c\ubc18\uc801\uc73c\ub85c \uc790\uc6d0\uc758 \uacf5\uc720, \uc678\ubd80 API, \uc2dc\uac04 \ub4f1\uc73c\ub85c \ube44\uacb0\uc815\uc801\uc778 \ud14c\uc2a4\ud2b8\uac00 \ub41c\ub2e4. \uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \uc0ac\uc6a9\ud558\uac70\ub098, \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc7ac\uc2e4\ud589\ud558\ub294 ",(0,r.jsx)(t.code,{children:"@DirtiesContext"}),", \uc790\uc6d0\uc744 \ucd08\uae30\ud654\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uc774\ud6c4\uc5d0 \ud14c\uc774\ube14\uc744 \ub864\ubc31 \ud558\ub294 ",(0,r.jsx)(t.code,{children:"@Transactional"}),"\ub4f1 \ub2e4\uc591\ud55c \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud574\ub2f9 \uae00\uc5d0\uc11c\ub294 \uc2a4\ud504\ub9c1\uc5d0\uc11c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc790\uc6d0\uc758 \uacf5\uc720\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc218\ud589\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc124\uba85\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"Independent - FIRST",type:"note",children:(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8\ub07c\ub9ac \uc11c\ub85c \uc758\uc874\ud558\uba74 \uc548 \ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc11c\ub85c \uc758\uc874\ud558\uac8c \ub41c\ub2e4\uba74 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \ub54c, \ub610 \ub2e4\ub978 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud14c\uc2a4\ud2b8\uac00 \uc88b\uc740 \ud14c\uc2a4\ud2b8\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"testexecutionlistener",children:"TestExecutionListener"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 TextExecutionListner\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 \ud14c\uc2a4\ud2b8 \uc2e4\ud589 \ub2e8\uacc4\uc5d0\uc11c \uc774\ubca4\ud2b8\ub97c \uc218\uc2e0\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub97c \uc774\uc6a9\ud558\uba74 JUnit\uc758 @BeforeEach\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uacfc \uc720\uc0ac\ud558\uac8c, \ud14c\uc2a4\ud2b8\uc758 \uc0dd\uba85\uc8fc\uae30 \uc774\uc804 \ub610\ub294 \uc774\ud6c4\uc5d0 \ud544\uc694\ud55c \uc791\uc5c5\uc744 \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=TextExecutionListner",children:"public interface TestExecutionListener {\n default void beforeTestClass(TestContext testContext) throws Exception {}\n default void prepareTestInstance(TestContext testContext) throws Exception {}\n default void beforeTestMethod(TestContext testContext) throws Exception {}\n default void beforeTestExecution(TestContext testContext) throws Exception {}\n default void afterTestExecution(TestContext testContext) throws Exception {}\n default void afterTestMethod(TestContext testContext) throws Exception {}\n default void afterTestClass(TestContext testContext) throws Exception {}\n}\n"})}),"\n",(0,r.jsx)(t.h3,{id:"abstracttestexecutionlistener-\uc0c1\uc18d\ud558\uc5ec-\uad6c\ud604",children:"AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604"}),"\n",(0,r.jsxs)(t.p,{children:["AbstractTestExecutionListener\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac \ud658\uacbd\uc744 \ub9cc\ub4e4\uc5b4\uc8fc\ub294 \ud074\ub798\uc2a4\ub85c, \uc778\ud130\ud398\uc774\uc2a4\uc778 TextExecutionListner\uc640 \ub2ec\ub9ac Ordered\uac00 \uad6c\ud604\ub418\uc5b4 \uc788\uc5b4 \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ubc1b\uc544 \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub294 \ud504\ub808\uc784\uc6cc\ud06c\uac00 \uc81c\uacf5\ud558\ub294 \ub9ac\uc2a4\ub108 \ub2e4\uc74c\uc5d0 \uc2e4\ud589\uc2dc\ud0a4\ub3c4\ub85d \ud574\uc900\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\uc74c\uacfc \uac19\uc774 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac01\uac01\uc758 \ud14c\uc774\ube14\uc5d0 \ud574\ub2f9\ud558\ub294 Truncate \ucffc\ub9ac\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc870\ud68c\ud558\uace0, Test \uba54\uc11c\ub4dc\uac00 \ub05d\ub0a0\ub54c \ub9c8\ub2e4 \ud574\ub2f9 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uc5ec \ud14c\uc774\ube14\uc744 \ucd08\uae30\ud654\uc2dc\ud0a4\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=DatabaseCleaner",children:'\npublic class DatabaseCleaner extends AbstractTestExecutionListener {\n\n private static final String TRUNCATE_TABLE_QUERY = """\n SELECT Concat(\'TRUNCATE TABLE \', TABLE_NAME, \';\') \n FROM INFORMATION_SCHEMA.TABLES\n WHERE TABLE_SCHEMA = \'PUBLIC\'\n """;\n\n @Override\n public void afterTestMethod(TestContext testContext) {\n JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);\n List truncateTableQueries = getTruncateTableQueries(jdbcTemplate);\n truncateTables(jdbcTemplate, truncateTableQueries);\n }\n\n private JdbcTemplate getJdbcTemplate(TestContext testContext) {\n return testContext.getApplicationContext().getBean(JdbcTemplate.class);\n }\n\n private List getTruncateTableQueries(JdbcTemplate jdbcTemplate) {\n return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);\n }\n\n private void truncateTables(JdbcTemplate jdbcTemplate, List truncateTableQueries) {\n jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");\n truncateTableQueries.forEach(jdbcTemplate::execute);\n jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");\n }\n}\n\n'})}),"\n",(0,r.jsx)(t.h3,{id:"listener-\ub4f1\ub85d",children:"Listener \ub4f1\ub85d"}),"\n",(0,r.jsxs)(t.p,{children:["@TestExecutionListeners\ub97c \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790 \uc815\uc758 \ub9ac\uc2a4\ub108\ub97c \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","mergeMode\uc758 \uae30\ubcf8\uac12\uc740 REPLACE_DEFAULTS\ub85c \ub9ac\uc2a4\ub108\uac00 \uc774\ubbf8 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \ub4f1\ub85d\ub41c \ub9ac\uc2a4\ub108\ub85c \ubcc0\uacbd\ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","MERGE_WITH_DEFAULTS\ub85c \uc124\uc815\ud55c\ub2e4\uba74 Ordered \uae30\uc900\uc73c\ub85c \uc21c\uc11c\uac00 \uacb0\uc815\ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ud6c4 \uaca9\ub9ac\uac00 \ud544\uc694\ud55c \ud14c\uc2a4\ud2b8\ub4e4\uc740 \ub2e4\uc74c\uc758 \ucd94\uc0c1 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ud558\uc5ec \uc0ac\uc6a9\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=AcceptanceTest",children:"\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\n@TestExecutionListeners(\n value = DatabaseCleaner.class,\n mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS\n)\npublic abstract class AcceptanceTest {\n\n @LocalServerPort\n private int port;\n\n @BeforeEach\n public void setUp() {\n RestAssured.port = port;\n }\n}\n\n"})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://www.baeldung.com/spring-testexecutionlistener",children:"The Spring TestExecutionListener, Baeldung"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://tecoble.techcourse.co.kr/post/2020-09-15-test-isolation/",children:"\uc778\uc218\ud14c\uc2a4\ud2b8\uc5d0\uc11c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ud558\uae30, \ud14c\ucf54\ube14"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://martinfowler.com/articles/nonDeterminism.html",children:"Eradicating Non-Determinism in Tests, martin fowler"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://mangkyu.tistory.com/264",children:"@SpringBootTest\uc758 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\uc2dc\ud0a4\uae30, MangKyu"})]})]})}function p(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>l});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},p=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),u=l(n),T=s,x=u["".concat(c,".").concat(T)]||u[T]||d[T]||i;return n?r.createElement(x,a(a({ref:t},p),{},{components:n})):r.createElement(x,a({ref:t},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7680],{14079:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var r=n(85893),s=n(3905);const i={title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",slug:"spring-test-isolation",tags:["test"]},a=void 0,o={permalink:"/spring-test-isolation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",source:"@site/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",description:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac",date:"2023-10-03T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 3\uc77c",tags:[{label:"test",permalink:"/tags/test"}],readingTime:4.315,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",slug:"spring-test-isolation",tags:["test"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",permalink:"/web-application-evolution"},nextItem:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/mvc-retrospective"}},c={authorsImageUrls:[]},l=[{value:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac",id:"\ud14c\uc2a4\ud2b8-\uaca9\ub9ac",level:3},{value:"TestExecutionListener",id:"testexecutionlistener",level:3},{value:"AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604",id:"abstracttestexecutionlistener-\uc0c1\uc18d\ud558\uc5ec-\uad6c\ud604",level:3},{value:"Listener \ub4f1\ub85d",id:"listener-\ub4f1\ub85d",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\ud14c\uc2a4\ud2b8-\uaca9\ub9ac",children:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac"}),"\n",(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8\uc758 \uc21c\uc11c\uc5d0 \ub530\ub77c \uc131\uacf5 \uc2e4\ud328 \uc5ec\ubd80\uac00 \uacb0\uc815\ub418\ub294 \ube44\uacb0\uc815\uc801\uc778(non-determinism) \ud14c\uc2a4\ud2b8\uac00 \ub418\uc5b4\uc11c\ub294 \uc548\ub418\uace0, \ud14c\uc2a4\ud2b8\ub294 \ud56d\uc0c1 \uc21c\uc11c\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc218\ud589\ub418\ub3c4\ub85d \ubcf4\uc7a5\ub418\uc5b4\uc57c \ud55c\ub2e4. \uc77c\ubc18\uc801\uc73c\ub85c \uc790\uc6d0\uc758 \uacf5\uc720, \uc678\ubd80 API, \uc2dc\uac04 \ub4f1\uc73c\ub85c \ube44\uacb0\uc815\uc801\uc778 \ud14c\uc2a4\ud2b8\uac00 \ub41c\ub2e4. \uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \uc0ac\uc6a9\ud558\uac70\ub098, \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc7ac\uc2e4\ud589\ud558\ub294 ",(0,r.jsx)(t.code,{children:"@DirtiesContext"}),", \uc790\uc6d0\uc744 \ucd08\uae30\ud654\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uc774\ud6c4\uc5d0 \ud14c\uc774\ube14\uc744 \ub864\ubc31 \ud558\ub294 ",(0,r.jsx)(t.code,{children:"@Transactional"}),"\ub4f1 \ub2e4\uc591\ud55c \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud574\ub2f9 \uae00\uc5d0\uc11c\ub294 \uc2a4\ud504\ub9c1\uc5d0\uc11c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc790\uc6d0\uc758 \uacf5\uc720\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc218\ud589\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc124\uba85\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"Independent - FIRST",type:"note",children:(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8\ub07c\ub9ac \uc11c\ub85c \uc758\uc874\ud558\uba74 \uc548 \ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc11c\ub85c \uc758\uc874\ud558\uac8c \ub41c\ub2e4\uba74 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \ub54c, \ub610 \ub2e4\ub978 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud14c\uc2a4\ud2b8\uac00 \uc88b\uc740 \ud14c\uc2a4\ud2b8\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"testexecutionlistener",children:"TestExecutionListener"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 TextExecutionListner\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 \ud14c\uc2a4\ud2b8 \uc2e4\ud589 \ub2e8\uacc4\uc5d0\uc11c \uc774\ubca4\ud2b8\ub97c \uc218\uc2e0\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub97c \uc774\uc6a9\ud558\uba74 JUnit\uc758 @BeforeEach\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uacfc \uc720\uc0ac\ud558\uac8c, \ud14c\uc2a4\ud2b8\uc758 \uc0dd\uba85\uc8fc\uae30 \uc774\uc804 \ub610\ub294 \uc774\ud6c4\uc5d0 \ud544\uc694\ud55c \uc791\uc5c5\uc744 \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=TextExecutionListner",children:"public interface TestExecutionListener {\n default void beforeTestClass(TestContext testContext) throws Exception {}\n default void prepareTestInstance(TestContext testContext) throws Exception {}\n default void beforeTestMethod(TestContext testContext) throws Exception {}\n default void beforeTestExecution(TestContext testContext) throws Exception {}\n default void afterTestExecution(TestContext testContext) throws Exception {}\n default void afterTestMethod(TestContext testContext) throws Exception {}\n default void afterTestClass(TestContext testContext) throws Exception {}\n}\n"})}),"\n",(0,r.jsx)(t.h3,{id:"abstracttestexecutionlistener-\uc0c1\uc18d\ud558\uc5ec-\uad6c\ud604",children:"AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604"}),"\n",(0,r.jsxs)(t.p,{children:["AbstractTestExecutionListener\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac \ud658\uacbd\uc744 \ub9cc\ub4e4\uc5b4\uc8fc\ub294 \ud074\ub798\uc2a4\ub85c, \uc778\ud130\ud398\uc774\uc2a4\uc778 TextExecutionListner\uc640 \ub2ec\ub9ac Ordered\uac00 \uad6c\ud604\ub418\uc5b4 \uc788\uc5b4 \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ubc1b\uc544 \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub294 \ud504\ub808\uc784\uc6cc\ud06c\uac00 \uc81c\uacf5\ud558\ub294 \ub9ac\uc2a4\ub108 \ub2e4\uc74c\uc5d0 \uc2e4\ud589\uc2dc\ud0a4\ub3c4\ub85d \ud574\uc900\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\uc74c\uacfc \uac19\uc774 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac01\uac01\uc758 \ud14c\uc774\ube14\uc5d0 \ud574\ub2f9\ud558\ub294 Truncate \ucffc\ub9ac\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc870\ud68c\ud558\uace0, Test \uba54\uc11c\ub4dc\uac00 \ub05d\ub0a0\ub54c \ub9c8\ub2e4 \ud574\ub2f9 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uc5ec \ud14c\uc774\ube14\uc744 \ucd08\uae30\ud654\uc2dc\ud0a4\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=DatabaseCleaner",children:'\npublic class DatabaseCleaner extends AbstractTestExecutionListener {\n\n private static final String TRUNCATE_TABLE_QUERY = """\n SELECT Concat(\'TRUNCATE TABLE \', TABLE_NAME, \';\') \n FROM INFORMATION_SCHEMA.TABLES\n WHERE TABLE_SCHEMA = \'PUBLIC\'\n """;\n\n @Override\n public void afterTestMethod(TestContext testContext) {\n JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);\n List truncateTableQueries = getTruncateTableQueries(jdbcTemplate);\n truncateTables(jdbcTemplate, truncateTableQueries);\n }\n\n private JdbcTemplate getJdbcTemplate(TestContext testContext) {\n return testContext.getApplicationContext().getBean(JdbcTemplate.class);\n }\n\n private List getTruncateTableQueries(JdbcTemplate jdbcTemplate) {\n return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);\n }\n\n private void truncateTables(JdbcTemplate jdbcTemplate, List truncateTableQueries) {\n jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");\n truncateTableQueries.forEach(jdbcTemplate::execute);\n jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");\n }\n}\n\n'})}),"\n",(0,r.jsx)(t.h3,{id:"listener-\ub4f1\ub85d",children:"Listener \ub4f1\ub85d"}),"\n",(0,r.jsxs)(t.p,{children:["@TestExecutionListeners\ub97c \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790 \uc815\uc758 \ub9ac\uc2a4\ub108\ub97c \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","mergeMode\uc758 \uae30\ubcf8\uac12\uc740 REPLACE_DEFAULTS\ub85c \ub9ac\uc2a4\ub108\uac00 \uc774\ubbf8 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \ub4f1\ub85d\ub41c \ub9ac\uc2a4\ub108\ub85c \ubcc0\uacbd\ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","MERGE_WITH_DEFAULTS\ub85c \uc124\uc815\ud55c\ub2e4\uba74 Ordered \uae30\uc900\uc73c\ub85c \uc21c\uc11c\uac00 \uacb0\uc815\ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ud6c4 \uaca9\ub9ac\uac00 \ud544\uc694\ud55c \ud14c\uc2a4\ud2b8\ub4e4\uc740 \ub2e4\uc74c\uc758 \ucd94\uc0c1 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ud558\uc5ec \uc0ac\uc6a9\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=AcceptanceTest",children:"\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\n@TestExecutionListeners(\n value = DatabaseCleaner.class,\n mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS\n)\npublic abstract class AcceptanceTest {\n\n @LocalServerPort\n private int port;\n\n @BeforeEach\n public void setUp() {\n RestAssured.port = port;\n }\n}\n\n"})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://www.baeldung.com/spring-testexecutionlistener",children:"The Spring TestExecutionListener, Baeldung"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://tecoble.techcourse.co.kr/post/2020-09-15-test-isolation/",children:"\uc778\uc218\ud14c\uc2a4\ud2b8\uc5d0\uc11c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ud558\uae30, \ud14c\ucf54\ube14"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://martinfowler.com/articles/nonDeterminism.html",children:"Eradicating Non-Determinism in Tests, martin fowler"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://mangkyu.tistory.com/264",children:"@SpringBootTest\uc758 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\uc2dc\ud0a4\uae30, MangKyu"})]})]})}function p(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>l});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},p=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),u=l(n),T=s,x=u["".concat(c,".").concat(T)]||u[T]||d[T]||i;return n?r.createElement(x,a(a({ref:t},p),{},{components:n})):r.createElement(x,a({ref:t},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/454a6d0d.64dcde7c.js b/assets/js/454a6d0d.94706a96.js similarity index 98% rename from assets/js/454a6d0d.64dcde7c.js rename to assets/js/454a6d0d.94706a96.js index 85e7bd2d9..41dfbae9d 100644 --- a/assets/js/454a6d0d.64dcde7c.js +++ b/assets/js/454a6d0d.94706a96.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4104],{98592:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>p,frontMatter:()=>s,metadata:()=>i,toc:()=>o});var r=t(85893),a=t(3905);const s={title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",slug:"tecochat-retrospective-2",tags:["TecoChat","Retrospective"]},l=void 0,i={permalink:"/tecochat-retrospective-2",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",source:"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",description:"\ud504\ub860\ud2b8\uc5d4\ud2b8",date:"2023-05-01T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 1\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.67,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",slug:"tecochat-retrospective-2",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",permalink:"/web-racing-car-retrospective"},nextItem:{title:"Jenkins\ub85c CI/CD \uc124\uc815",permalink:"/jenkins"}},c={authorsImageUrls:[]},o=[{value:"\ud504\ub860\ud2b8\uc5d4\ud2b8",id:"\ud504\ub860\ud2b8\uc5d4\ud2b8",level:3},{value:"\ubc31\uc5d4\ub4dc",id:"\ubc31\uc5d4\ub4dc",level:3},{value:"Http Request Header",id:"http-request-header",level:3},{value:"Elastic Beanstalk",id:"elastic-beanstalk",level:3},{value:"Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac",id:"elastic-beanstalk-rds-\uc124\uc815-\ud6c4-\ubd84\ub9ac",level:3},{value:"Elastic Beanstalk nginx \uc124\uc815",id:"elastic-beanstalk-nginx-\uc124\uc815",level:3},{value:"Jenkins",id:"jenkins",level:3},{value:"Jenkins Blue Ocean",id:"jenkins-blue-ocean",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"\ud504\ub860\ud2b8\uc5d4\ud2b8",children:"\ud504\ub860\ud2b8\uc5d4\ud2b8"}),"\n",(0,r.jsxs)(n.p,{children:["\ub2c9\ub124\uc784\uc744 \uc785\ub825\ud558\uc5ec \uac04\ub2e8\ud788 \ub85c\uadf8\uc778\ud558\ub294 \ud654\uba74, \ucc44\ud305 \ubaa9\ub85d\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\uace0 \ub2e8\uc77c \ucc44\ud305\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ucc44\ud305\uc744 \uc774\uc5b4\ub098\uac08 \uc218 \uc788\uac8c \ud558\ub294 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\uc798\ud558\uac8c \uc2e0\uacbd \uc4f8 \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c, \ud504\ub860\ud2b8\uc5d4\ub4dc \ud558\ub294 \uc0ac\ub78c\ub4e4\uc774 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc5ec\uc720\uac00 \ub41c\ub2e4\uba74 \uc790\uc2e0\uc758 \ucc44\ud305\uc744 \ubcfc \uc218 \uc788\ub294 \uae30\ub2a5\uc774\ub098, \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub294 \uae30\ub2a5, \ub313\uae00 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud560 \uc608\uc815\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ubc31\uc5d4\ub4dc",children:"\ubc31\uc5d4\ub4dc"}),"\n",(0,r.jsxs)(n.p,{children:["\ucd5c\ub300\ud55c \ube68\ub9ac \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uae30\ub85c \uc815\ud574\uc11c, \ubc31\uc5d4\ub4dc\ub294 \ub9d0\ub791\uc774 \uc77c\ub2e8 \ub2e4 \ub9cc\ub4e4\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9d0\ub791\uc774 \ud55c \ubd80\ubd84\uc774 \ub108\ubb34 \ub9ce\uc544\uc11c \ub0b4\uac00 \ubabb \ub530\ub77c\uac00\ub294 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc911\uc5d0 \ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc774\ud574\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"http-request-header",children:"Http Request Header"}),"\n",(0,r.jsxs)(n.p,{children:["\uc544\uc9c1 \uc778\uc99d\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ud558\uc9c0 \uc54a\uc544\uc11c \uc694\uccad \ud5e4\ub354\uc5d0 \uc774\ub984\uc744 \ubcf4\ub0b4\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9d0\ub791\uc774 \ud55c\uae00\uc740 \uc548\ub41c\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c Base64\ub85c \uc778\ucf54\ub529\ud558\uace0, \ubc31\uc5d4\ub4dc\uc5d0\uc11c \ub514\ucf54\ub529 \ud558\uc5ec \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\ub294 pinia\uc5d0 \uc788\ub294 name \uac12\uc744 \uc778\ucf54\ub529 \ud558\ub294 \ucf54\ub4dc\ub2e4. deprecated \ub418\uc5c8\ub2e4\ub294\ub370, \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560 \uc904 \ubab0\ub77c\uc11c \uc77c\ub2e8 \uc774\uac78 \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"const encodedName = () => {\n const uriComponent = unescape(encodeURIComponent(name.value));\n return btoa(uriComponent);\n};\n"})}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk",children:"Elastic Beanstalk"}),"\n",(0,r.jsxs)(n.p,{children:["\uac00\uc7a5 \ube60\ub974\uac8c \ubc31\uc5d4\ub4dc\ub97c \ubc30\ud3ec\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ubb58\uc9c0 \uace0\ubbfc\ud558\ub2e4\uac00 Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uba74 \uc778\ud504\ub77c\uc5d0 \ub300\ud574 \uc798 \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube60\ub974\uac8c \ubc30\ud3ec\ud558\uace0 \uad00\ub9ac\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubaa8\ub2c8\ud130\ub9c1, \ub85c\uae45, \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk-rds-\uc124\uc815-\ud6c4-\ubd84\ub9ac",children:"Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac"}),"\n",(0,r.jsxs)(n.p,{children:["\ucd08\uae30 \uc124\uc815 \uc2dc RDS\ub97c \uc5f0\uacb0\ud558\uace0 \uc124\uc815 \uc644\ub8cc \ud6c4 \ubd84\ub9ac\ud55c\ub2e4\uba74, Beanstalk \uc778\uc2a4\ud134\uc2a4 -> RDS \uc694\uccad \uc2dc \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc744 \uc548 \ud574\ub3c4 \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","RDS \ubd84\ub9ac \uc2dc Beanstalk\uc5d0 \uae30\ubcf8\uc801\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub294 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD\uc640 \uac19\uc740 \ud658\uacbd \ubcc0\uc218\uac00 \uac19\uc774 \uc81c\uac70\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c Elastic Beanstalk\ub85c RDS\ub97c \uc124\uc815\ud558\uba74 \uae30\ubcf8 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uba85\uc740 ebdb\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk-nginx-\uc124\uc815",children:"Elastic Beanstalk nginx \uc124\uc815"}),"\n",(0,r.jsxs)(n.p,{children:["\uc5c5\ub85c\ub4dc\ud558\ub294 zip \ud30c\uc77c \ub0b4\ubd80\uc5d0 ",(0,r.jsx)(n.code,{children:".platform/nginx/conf.d/"})," \uacbd\ub85c\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ucd94\uac00\ud558\uba74 nginx \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"jenkins",children:"Jenkins"}),"\n",(0,r.jsxs)(n.p,{children:["\ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc77c\uc77c\ud788 \ubc30\ud3ec\ud558\uae30 \ubd88\ud3b8\ud574\uc11c Jenkins\ub97c \uc774\uc6a9\ud558\uc5ec Repository\uc5d0 \ucf54\ub4dc\ub97c push \ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ubc30\ud3ec\uac00 \ub418\uac8c \uc124\uc815\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc791\ub144\uc5d0 \ud655\uc778\ud588\uc744 \ub550 2022\ub144 12\uc6d4 31\uc77c\uae4c\uc9c0 EC2 ARM \uae30\ubc18 t4g.small\uc774 \ubb34\ub8cc\uc600\ub294\ub370, \ub2e4\uc2dc \ub4e4\uc5b4\uac00 \ubcf4\ub2c8 2023\ub144\uae4c\uc9c0 12\uc6d4 31\uc77c\uae4c\uc9c0 t4g.small\uc744 \ubb34\ub8cc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","t4g.small\uc740 \ub7a8\uc774 2G\uc778\ub370, \uc608\uc804\uc5d0\ub294 \ubd80\uc871\ud558\uc9c0 \uc54a\uc558\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370 Java 17\uc744 \uc368\uc11c \uadf8\ub7f0\uac00 \ube4c\ub4dc \ud560 \ub54c \ub7a8\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\uc544\uc11c Swap \uba54\ubaa8\ub9ac 2\uae30\uac00\ub97c \ucd94\uac00\ub85c \uc124\uc815\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c build.gradle\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8 \uc2dc \uc0ac\uc6a9\ud558\ub294 \ub7a8\uc744 \ub298\ub9b4 \uc218 \uc788\ub2e4. \uae30\ubcf8\uac12\uc740 512MB\ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-groovy",children:'test {\n maxHeapSize = "1024m"\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"jenkins-blue-ocean",children:"Jenkins Blue Ocean"}),"\n",(0,r.jsxs)(n.p,{children:["Blue Ocean\uc740 Jenkins Pipeline\uc744 \uad6c\uc131\ud558\ub294 \ub370\uc5d0 \uc788\uc5b4 \ud3b8\ub9ac\ud558\uac8c \ud574\uc8fc\ub294 \ub3c4\uad6c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc2dc\uac01\ud654\ub3c4 \uc798 \ub418\uc5b4\uc788\uace0, \uc124\uc815\ub3c4 \ud3b8\ub9ac\ud55c \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n",'\uc624\ub298 \uc801\uc6a9\ud574 \ubcf4\ub2c8 \ub7a8\uc774 \ubd80\uc871\ud558\uc5ec \uc911\uac04\uc5d0 \uc798 \uc548\ub418\uae30\ub3c4 \ud558\uace0 \uadf8\ub798\uc11c \uadf8\ub0e5 "Pipeline\ub9cc \uc0ac\uc6a9\ud560 \uac78 \uadf8\ub7ac\ub098?" \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.']}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/Welcome.html",children:"Elastic Beanstalk, AWS"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://aws.amazon.com/ko/ec2/graviton/",children:"EC2 AWS Graviton, AWS"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings",children:"Default Memory Settings, AWS"})]})]})}function p(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>o});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=r.createContext({}),o=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},d={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,s=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=o(t),h=a,b=u["".concat(c,".").concat(h)]||u[h]||d[h]||s;return t?r.createElement(b,l(l({ref:n},p),{},{components:t})):r.createElement(b,l({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4104],{98592:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>p,frontMatter:()=>s,metadata:()=>i,toc:()=>o});var r=t(85893),a=t(3905);const s={title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",slug:"tecochat-retrospective-2",tags:["TecoChat","Retrospective"]},l=void 0,i={permalink:"/tecochat-retrospective-2",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",source:"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",description:"\ud504\ub860\ud2b8\uc5d4\ud2b8",date:"2023-05-01T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 1\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.67,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",slug:"tecochat-retrospective-2",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"Jenkins\ub85c CI/CD \uc124\uc815",permalink:"/jenkins"},nextItem:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",permalink:"/web-racing-car-retrospective"}},c={authorsImageUrls:[]},o=[{value:"\ud504\ub860\ud2b8\uc5d4\ud2b8",id:"\ud504\ub860\ud2b8\uc5d4\ud2b8",level:3},{value:"\ubc31\uc5d4\ub4dc",id:"\ubc31\uc5d4\ub4dc",level:3},{value:"Http Request Header",id:"http-request-header",level:3},{value:"Elastic Beanstalk",id:"elastic-beanstalk",level:3},{value:"Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac",id:"elastic-beanstalk-rds-\uc124\uc815-\ud6c4-\ubd84\ub9ac",level:3},{value:"Elastic Beanstalk nginx \uc124\uc815",id:"elastic-beanstalk-nginx-\uc124\uc815",level:3},{value:"Jenkins",id:"jenkins",level:3},{value:"Jenkins Blue Ocean",id:"jenkins-blue-ocean",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"\ud504\ub860\ud2b8\uc5d4\ud2b8",children:"\ud504\ub860\ud2b8\uc5d4\ud2b8"}),"\n",(0,r.jsxs)(n.p,{children:["\ub2c9\ub124\uc784\uc744 \uc785\ub825\ud558\uc5ec \uac04\ub2e8\ud788 \ub85c\uadf8\uc778\ud558\ub294 \ud654\uba74, \ucc44\ud305 \ubaa9\ub85d\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\uace0 \ub2e8\uc77c \ucc44\ud305\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ucc44\ud305\uc744 \uc774\uc5b4\ub098\uac08 \uc218 \uc788\uac8c \ud558\ub294 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\uc798\ud558\uac8c \uc2e0\uacbd \uc4f8 \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c, \ud504\ub860\ud2b8\uc5d4\ub4dc \ud558\ub294 \uc0ac\ub78c\ub4e4\uc774 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc5ec\uc720\uac00 \ub41c\ub2e4\uba74 \uc790\uc2e0\uc758 \ucc44\ud305\uc744 \ubcfc \uc218 \uc788\ub294 \uae30\ub2a5\uc774\ub098, \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub294 \uae30\ub2a5, \ub313\uae00 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud560 \uc608\uc815\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ubc31\uc5d4\ub4dc",children:"\ubc31\uc5d4\ub4dc"}),"\n",(0,r.jsxs)(n.p,{children:["\ucd5c\ub300\ud55c \ube68\ub9ac \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uae30\ub85c \uc815\ud574\uc11c, \ubc31\uc5d4\ub4dc\ub294 \ub9d0\ub791\uc774 \uc77c\ub2e8 \ub2e4 \ub9cc\ub4e4\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9d0\ub791\uc774 \ud55c \ubd80\ubd84\uc774 \ub108\ubb34 \ub9ce\uc544\uc11c \ub0b4\uac00 \ubabb \ub530\ub77c\uac00\ub294 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc911\uc5d0 \ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc774\ud574\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"http-request-header",children:"Http Request Header"}),"\n",(0,r.jsxs)(n.p,{children:["\uc544\uc9c1 \uc778\uc99d\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ud558\uc9c0 \uc54a\uc544\uc11c \uc694\uccad \ud5e4\ub354\uc5d0 \uc774\ub984\uc744 \ubcf4\ub0b4\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9d0\ub791\uc774 \ud55c\uae00\uc740 \uc548\ub41c\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c Base64\ub85c \uc778\ucf54\ub529\ud558\uace0, \ubc31\uc5d4\ub4dc\uc5d0\uc11c \ub514\ucf54\ub529 \ud558\uc5ec \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\ub294 pinia\uc5d0 \uc788\ub294 name \uac12\uc744 \uc778\ucf54\ub529 \ud558\ub294 \ucf54\ub4dc\ub2e4. deprecated \ub418\uc5c8\ub2e4\ub294\ub370, \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560 \uc904 \ubab0\ub77c\uc11c \uc77c\ub2e8 \uc774\uac78 \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"const encodedName = () => {\n const uriComponent = unescape(encodeURIComponent(name.value));\n return btoa(uriComponent);\n};\n"})}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk",children:"Elastic Beanstalk"}),"\n",(0,r.jsxs)(n.p,{children:["\uac00\uc7a5 \ube60\ub974\uac8c \ubc31\uc5d4\ub4dc\ub97c \ubc30\ud3ec\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ubb58\uc9c0 \uace0\ubbfc\ud558\ub2e4\uac00 Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uba74 \uc778\ud504\ub77c\uc5d0 \ub300\ud574 \uc798 \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube60\ub974\uac8c \ubc30\ud3ec\ud558\uace0 \uad00\ub9ac\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubaa8\ub2c8\ud130\ub9c1, \ub85c\uae45, \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk-rds-\uc124\uc815-\ud6c4-\ubd84\ub9ac",children:"Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac"}),"\n",(0,r.jsxs)(n.p,{children:["\ucd08\uae30 \uc124\uc815 \uc2dc RDS\ub97c \uc5f0\uacb0\ud558\uace0 \uc124\uc815 \uc644\ub8cc \ud6c4 \ubd84\ub9ac\ud55c\ub2e4\uba74, Beanstalk \uc778\uc2a4\ud134\uc2a4 -> RDS \uc694\uccad \uc2dc \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc744 \uc548 \ud574\ub3c4 \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","RDS \ubd84\ub9ac \uc2dc Beanstalk\uc5d0 \uae30\ubcf8\uc801\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub294 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD\uc640 \uac19\uc740 \ud658\uacbd \ubcc0\uc218\uac00 \uac19\uc774 \uc81c\uac70\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c Elastic Beanstalk\ub85c RDS\ub97c \uc124\uc815\ud558\uba74 \uae30\ubcf8 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uba85\uc740 ebdb\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk-nginx-\uc124\uc815",children:"Elastic Beanstalk nginx \uc124\uc815"}),"\n",(0,r.jsxs)(n.p,{children:["\uc5c5\ub85c\ub4dc\ud558\ub294 zip \ud30c\uc77c \ub0b4\ubd80\uc5d0 ",(0,r.jsx)(n.code,{children:".platform/nginx/conf.d/"})," \uacbd\ub85c\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ucd94\uac00\ud558\uba74 nginx \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"jenkins",children:"Jenkins"}),"\n",(0,r.jsxs)(n.p,{children:["\ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc77c\uc77c\ud788 \ubc30\ud3ec\ud558\uae30 \ubd88\ud3b8\ud574\uc11c Jenkins\ub97c \uc774\uc6a9\ud558\uc5ec Repository\uc5d0 \ucf54\ub4dc\ub97c push \ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ubc30\ud3ec\uac00 \ub418\uac8c \uc124\uc815\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc791\ub144\uc5d0 \ud655\uc778\ud588\uc744 \ub550 2022\ub144 12\uc6d4 31\uc77c\uae4c\uc9c0 EC2 ARM \uae30\ubc18 t4g.small\uc774 \ubb34\ub8cc\uc600\ub294\ub370, \ub2e4\uc2dc \ub4e4\uc5b4\uac00 \ubcf4\ub2c8 2023\ub144\uae4c\uc9c0 12\uc6d4 31\uc77c\uae4c\uc9c0 t4g.small\uc744 \ubb34\ub8cc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","t4g.small\uc740 \ub7a8\uc774 2G\uc778\ub370, \uc608\uc804\uc5d0\ub294 \ubd80\uc871\ud558\uc9c0 \uc54a\uc558\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370 Java 17\uc744 \uc368\uc11c \uadf8\ub7f0\uac00 \ube4c\ub4dc \ud560 \ub54c \ub7a8\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\uc544\uc11c Swap \uba54\ubaa8\ub9ac 2\uae30\uac00\ub97c \ucd94\uac00\ub85c \uc124\uc815\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c build.gradle\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8 \uc2dc \uc0ac\uc6a9\ud558\ub294 \ub7a8\uc744 \ub298\ub9b4 \uc218 \uc788\ub2e4. \uae30\ubcf8\uac12\uc740 512MB\ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-groovy",children:'test {\n maxHeapSize = "1024m"\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"jenkins-blue-ocean",children:"Jenkins Blue Ocean"}),"\n",(0,r.jsxs)(n.p,{children:["Blue Ocean\uc740 Jenkins Pipeline\uc744 \uad6c\uc131\ud558\ub294 \ub370\uc5d0 \uc788\uc5b4 \ud3b8\ub9ac\ud558\uac8c \ud574\uc8fc\ub294 \ub3c4\uad6c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc2dc\uac01\ud654\ub3c4 \uc798 \ub418\uc5b4\uc788\uace0, \uc124\uc815\ub3c4 \ud3b8\ub9ac\ud55c \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n",'\uc624\ub298 \uc801\uc6a9\ud574 \ubcf4\ub2c8 \ub7a8\uc774 \ubd80\uc871\ud558\uc5ec \uc911\uac04\uc5d0 \uc798 \uc548\ub418\uae30\ub3c4 \ud558\uace0 \uadf8\ub798\uc11c \uadf8\ub0e5 "Pipeline\ub9cc \uc0ac\uc6a9\ud560 \uac78 \uadf8\ub7ac\ub098?" \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.']}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/Welcome.html",children:"Elastic Beanstalk, AWS"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://aws.amazon.com/ko/ec2/graviton/",children:"EC2 AWS Graviton, AWS"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings",children:"Default Memory Settings, AWS"})]})]})}function p(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>o});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=r.createContext({}),o=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},d={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,s=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=o(t),h=a,b=u["".concat(c,".").concat(h)]||u[h]||d[h]||s;return t?r.createElement(b,l(l({ref:n},p),{},{components:t})):r.createElement(b,l({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/48faf148.251b0554.js b/assets/js/48faf148.1717462a.js similarity index 97% rename from assets/js/48faf148.251b0554.js rename to assets/js/48faf148.1717462a.js index ccbb35572..cbf883798 100644 --- a/assets/js/48faf148.251b0554.js +++ b/assets/js/48faf148.1717462a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7328],{50973:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>o,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var n=r(85893),c=r(3905);const s={title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",slug:"tecochat-retrospective-3",tags:["TecoChat","Retrospective"]},i=void 0,a={permalink:"/tecochat-retrospective-3",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",source:"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",description:"\uac1c\uc694",date:"2023-06-01T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 1\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.005,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",slug:"tecochat-retrospective-3",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",permalink:"/order-retrospective"},nextItem:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",permalink:"/composite"}},o={authorsImageUrls:[]},l=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5",id:"\ub098\uc758-\ucc44\ud305-\ud655\uc778\ud558\uace0-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",level:3},{value:"\uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5",id:"\uc88b\uc544\uc694\uc640-\ub313\uae00-\uae30\ub2a5",level:3},{value:"\ud0a4\uc6cc\ub4dc \ucd94\ucd9c",id:"\ud0a4\uc6cc\ub4dc-\ucd94\ucd9c",level:3},{value:"\ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5",id:"\ub2e4\ub978-\ud06c\ub8e8\uc758-\ucc44\ud305-\ubcf5\uc0ac\ud574\uc11c-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",level:3},{value:"\uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30",id:"\uc0ac\uc6a9\uc131-\uace0\ub824\ud558\uae30",level:3},{value:"\ud5a5\ud6c4 \uacc4\ud68d",id:"\ud5a5\ud6c4-\uacc4\ud68d",level:3}];function p(e){const t={br:"br",code:"code",h3:"h3",img:"img",p:"p",...(0,c.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,n.jsxs)(t.p,{children:["\uc6d0\ub798 \ubaa9\uc801\uc778 ",(0,n.jsx)(t.code,{children:"\ud06c\ub8e8\ub4e4\uc758 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0"}),"\uc744 \uc8fc\uae30 \uc704\ud574 \uc5b4\ub5a4 \uae30\ub2a5\uc744 \ucd94\uac00\ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub808\ubca8 2\uac00 \uac70\uc758 \ub05d\ub098\uac00\ub294 \uc2dc\uc810, \uadf8\ub3d9\uc548 \ud588\ub358 \uac83\uc744 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ub098\uc758-\ucc44\ud305-\ud655\uc778\ud558\uace0-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",children:"\ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["GPT\uc5d0\ub3c4 \uc788\ub294 \uae30\ub2a5\uc778\ub370, \ub0b4\uac00 \uc774\uc804\uc5d0 \ud588\ub358 \ucc44\ud305\uc744 \uc774\uc5b4\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc608\uc804\uc5d0 \uc5b4\ub5a4 \uc9c8\ubb38\uc744 \ub0a8\uacbc\ub294\uc9c0, \ub610\ud55c \ud574\ub2f9 \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat1",src:r(49483).Z+"",width:"2878",height:"1316"})}),"\n",(0,n.jsx)(t.h3,{id:"\uc88b\uc544\uc694\uc640-\ub313\uae00-\uae30\ub2a5",children:"\uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc5d0 \ubc18\uc751\ud560 \uc218 \uc788\ub294 \ubb34\uc5b8\uac00\uac00 \uc788\uc5c8\uc73c\uba74 \uc88b\uaca0\ub2e4\ub294 \uc758\uacac\ub4e4\uc774 \ub9ce\uc558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub204\uac00 \uc88b\uc544\uc694\ub97c \ub20c\ub800\ub294\uc9c0, \uc5b4\ub5a4 \ucc44\ud305\uc774 \uc88b\uc544\uc694\ub97c \uac00\uc7a5 \ub9ce\uc774 \ubc1b\uc558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub610\ud55c \ub313\uae00 \ucd94\uac00 \ubc0f \uc0ad\uc81c \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ud0a4\uc6cc\ub4dc-\ucd94\ucd9c",children:"\ud0a4\uc6cc\ub4dc \ucd94\ucd9c"}),"\n",(0,n.jsxs)(t.p,{children:["\uc5b4\ub5bb\uac8c \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\uc744 \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub294\ub370, \uc77c\ub2e8 GPT\ub97c \uc774\uc6a9\ud574\uc11c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\uae30\ub85c \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud574\ub2f9 \ubd80\ubd84\uc740 \uccab \uc9c8\ubb38\uc5d0 \ub300\ud55c \ud0a4\uc6cc\ub4dc\ub9cc \ucd94\ucd9c\ud558\ub3c4\ub85d \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ubc31\uc5d4\ub4dc\uc5d0\uc120 \ub9d0\ub791\uc774 \uc774\ubca4\ud2b8 \uc774\uc6a9\ud574\uc11c \uccab \ucc44\ud305 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74, \ube44\ub3d9\uae30\ub85c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\ub294 \uc9c8\ubb38\uc744 \ucd94\uac00\ub85c \ub0a0\ub9ac\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4.",(0,n.jsx)(t.br,{}),"\n","CSV \ud615\uc2dd\uc73c\ub85c GPT\uc5d0\uac8c \ub2f5\ubcc0\uc744 \uc785\ub825\ud574\ub2ec\ub77c\uace0 \uc694\uccad\ubc1b\ub294\ub370, \uc774 \ubd80\ubd84\uc774 \ubb38\uc81c(\ud504\ub86c\ud504\ud2b8 \uc5d4\uc9c0\ub2c8\uc5b4\ub9c1 \ubd80\ubd84\uc774 \ubc18\ud658\ub41c\ub2e4.)\uac00 \uc880 \uc788\ub294 \uac83 \uac19\uc544\uc11c \uac1c\uc120\uc774 \ud544\uc694\ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat2",src:r(50885).Z+"",width:"2394",height:"1048"})}),"\n",(0,n.jsx)(t.h3,{id:"\ub2e4\ub978-\ud06c\ub8e8\uc758-\ucc44\ud305-\ubcf5\uc0ac\ud574\uc11c-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",children:"\ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["\ub2e4\ub978 \ud06c\ub8e8\ub4e4\uc758 \ucc44\ud305\uc744 \uc77d\ub2e4\uac00 \uad81\uae08\ud55c \uc810\uc774 \uc788\ub2e4\uba74 \ubcf5\uc0ac\ud574\uc11c \ubc14\ub85c \uc9c8\ubb38\uc744 \ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ucc44\ud305\uc774 \ubcf5\uc0ac\ub41c \ud6c4 \ubc14\ub85c GPT\uc640 \ub300\ud654\ub97c \ud560 \uc218 \uc788\ub294 \uba54\uc778 \ud654\uba74\uc73c\ub85c \uc774\ub3d9\ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\uc0ac\uc6a9\uc131-\uace0\ub824\ud558\uae30",children:"\uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat3",src:r(15153).Z+"",width:"1668",height:"718"})}),"\n",(0,n.jsxs)(t.p,{children:["\uc704 \ud654\uba74\uc740 \ud68c\uc6d0\uac00\uc785 \ucc3d\uc774\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc0ac\uc2e4 \uac00\uc7a5 \ub9c8\uc74c\uc5d0 \ub4dc\ub294 \ubd80\ubd84\uc774\uace0, \ud68c\uc6d0\uac00\uc785(\ub2c9\ub124\uc784\ub9cc \uc785\ub825\ud558\uc9c0\ub9cc)\ud560 \ub54c \uc775\uba85\uc744 \uc6d0\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uace0\ubbfc\uc744 \ub3c4\uc640\uc8fc\uac8c \ub054 \uc74c\uc2dd, \uacfc\uc77c, \uacfc\uc790 \ub4f1\uc758 \uc694\uc18c\ub4e4\uc744 \uc785\ub825\ud558\ub3c4\ub85d \uc720\ub3c4\ud588\ub2e4!\n\ucd94\uac00\ub85c GPT\uc758 \ub2f5\ubcc0\uc774 \uc624\uba74 \uc790\ub3d9\uc73c\ub85c \ud654\uba74\uc744 \uc2a4\ud06c\ub864 \ud574\uc8fc\ub294 \uac83\uacfc \uac19\uc774 \uc0ac\uc6a9\uc131\uc744 \uac1c\uc120\ud574 \ubcf4\ub824\uace0 \ub178\ub825\ud588\uc9c0\ub9cc \uc27d\uc9c0 \uc54a\uc558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc81c\uc77c \ud558\uace0 \uc2f6\uc740 \uac83\uc740 \uc2e4\uc81c GPT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ucc98\ub7fc stream/text \uac12\uc744 \ucc98\ub9ac\ud558\uace0 \uc2f6\uc740\ub370 \uc774 \ubd80\ubd84\uc740 \ubc29\ud559 \ub54c \uae30\ud68c\uac00 \ub418\uba74 \ub3c4\uc804\ud574 \ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ud5a5\ud6c4-\uacc4\ud68d",children:"\ud5a5\ud6c4 \uacc4\ud68d"}),"\n",(0,n.jsxs)(t.p,{children:["\uc2e4\uc81c \ud06c\ub8e8\ub4e4\uc774 \uc0ac\uc6a9\ud574 \uc8fc\ub294 \uc11c\ube44\uc2a4\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\ubcf4\uba74\uc11c \uc0ac\uc6a9\uc790\uc758 \uc785\uc7a5\uc5d0\uc11c \uace0\ubbfc\ub3c4 \ud558\uac8c \ub418\ub294 \uac83 \uac19\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud06c\ub8e8\ub4e4\uc774 \uc9c1\uc811 \uc0ac\uc6a9\ud574 \uc8fc\ub2c8\uae4c \ub108\ubb34 \uace0\ub9d9\uace0, \ud55c\ud3b8\uc73c\ub85c\ub294 \uc2e0\uae30\ud558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc77c\ub2e8 \ubc29\ud559 \ub54c stream/text \uad00\ub828\ub41c \ubd80\ubd84 \ub3d9\uc791\ub418\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\ub824\uace0 \ud558\uace0, \uadf8 \uc678\uc758 \ubd80\ubd84\uc740 \uc870\uae08 \ub354 \uace0\ubbfc\ud574\uc57c\ub420 \uac83 \uac19\ub2e4."]})]})}function d(e={}){const{wrapper:t}={...(0,c.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function c(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function s(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(c[r]=e[r]);return c}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var o=n.createContext({}),l=function(e){var t=n.useContext(o),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,c=e.mdxType,s=e.originalType,o=e.parentName,d=a(e,["components","mdxType","originalType","parentName"]),h=l(r),b=c,u=h["".concat(o,".").concat(b)]||h[b]||p[b]||s;return r?n.createElement(u,i(i({ref:t},d),{},{components:r})):n.createElement(u,i({ref:t},d))}));d.displayName="MDXCreateElement"},49483:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat1-e9408e2e2f13bb192541de194ffccc6a.png"},50885:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat2-4b3b653eb2b23b88f19e8cb4177a786c.png"},15153:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat3-12a510067e4d210c13e46b7b99313307.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7328],{50973:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>o,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var n=r(85893),c=r(3905);const s={title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",slug:"tecochat-retrospective-3",tags:["TecoChat","Retrospective"]},i=void 0,a={permalink:"/tecochat-retrospective-3",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",source:"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",description:"\uac1c\uc694",date:"2023-06-01T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 1\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.005,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",slug:"tecochat-retrospective-3",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",permalink:"/composite"},nextItem:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",permalink:"/order-retrospective"}},o={authorsImageUrls:[]},l=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5",id:"\ub098\uc758-\ucc44\ud305-\ud655\uc778\ud558\uace0-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",level:3},{value:"\uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5",id:"\uc88b\uc544\uc694\uc640-\ub313\uae00-\uae30\ub2a5",level:3},{value:"\ud0a4\uc6cc\ub4dc \ucd94\ucd9c",id:"\ud0a4\uc6cc\ub4dc-\ucd94\ucd9c",level:3},{value:"\ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5",id:"\ub2e4\ub978-\ud06c\ub8e8\uc758-\ucc44\ud305-\ubcf5\uc0ac\ud574\uc11c-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",level:3},{value:"\uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30",id:"\uc0ac\uc6a9\uc131-\uace0\ub824\ud558\uae30",level:3},{value:"\ud5a5\ud6c4 \uacc4\ud68d",id:"\ud5a5\ud6c4-\uacc4\ud68d",level:3}];function p(e){const t={br:"br",code:"code",h3:"h3",img:"img",p:"p",...(0,c.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,n.jsxs)(t.p,{children:["\uc6d0\ub798 \ubaa9\uc801\uc778 ",(0,n.jsx)(t.code,{children:"\ud06c\ub8e8\ub4e4\uc758 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0"}),"\uc744 \uc8fc\uae30 \uc704\ud574 \uc5b4\ub5a4 \uae30\ub2a5\uc744 \ucd94\uac00\ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub808\ubca8 2\uac00 \uac70\uc758 \ub05d\ub098\uac00\ub294 \uc2dc\uc810, \uadf8\ub3d9\uc548 \ud588\ub358 \uac83\uc744 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ub098\uc758-\ucc44\ud305-\ud655\uc778\ud558\uace0-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",children:"\ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["GPT\uc5d0\ub3c4 \uc788\ub294 \uae30\ub2a5\uc778\ub370, \ub0b4\uac00 \uc774\uc804\uc5d0 \ud588\ub358 \ucc44\ud305\uc744 \uc774\uc5b4\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc608\uc804\uc5d0 \uc5b4\ub5a4 \uc9c8\ubb38\uc744 \ub0a8\uacbc\ub294\uc9c0, \ub610\ud55c \ud574\ub2f9 \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat1",src:r(49483).Z+"",width:"2878",height:"1316"})}),"\n",(0,n.jsx)(t.h3,{id:"\uc88b\uc544\uc694\uc640-\ub313\uae00-\uae30\ub2a5",children:"\uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc5d0 \ubc18\uc751\ud560 \uc218 \uc788\ub294 \ubb34\uc5b8\uac00\uac00 \uc788\uc5c8\uc73c\uba74 \uc88b\uaca0\ub2e4\ub294 \uc758\uacac\ub4e4\uc774 \ub9ce\uc558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub204\uac00 \uc88b\uc544\uc694\ub97c \ub20c\ub800\ub294\uc9c0, \uc5b4\ub5a4 \ucc44\ud305\uc774 \uc88b\uc544\uc694\ub97c \uac00\uc7a5 \ub9ce\uc774 \ubc1b\uc558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub610\ud55c \ub313\uae00 \ucd94\uac00 \ubc0f \uc0ad\uc81c \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ud0a4\uc6cc\ub4dc-\ucd94\ucd9c",children:"\ud0a4\uc6cc\ub4dc \ucd94\ucd9c"}),"\n",(0,n.jsxs)(t.p,{children:["\uc5b4\ub5bb\uac8c \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\uc744 \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub294\ub370, \uc77c\ub2e8 GPT\ub97c \uc774\uc6a9\ud574\uc11c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\uae30\ub85c \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud574\ub2f9 \ubd80\ubd84\uc740 \uccab \uc9c8\ubb38\uc5d0 \ub300\ud55c \ud0a4\uc6cc\ub4dc\ub9cc \ucd94\ucd9c\ud558\ub3c4\ub85d \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ubc31\uc5d4\ub4dc\uc5d0\uc120 \ub9d0\ub791\uc774 \uc774\ubca4\ud2b8 \uc774\uc6a9\ud574\uc11c \uccab \ucc44\ud305 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74, \ube44\ub3d9\uae30\ub85c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\ub294 \uc9c8\ubb38\uc744 \ucd94\uac00\ub85c \ub0a0\ub9ac\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4.",(0,n.jsx)(t.br,{}),"\n","CSV \ud615\uc2dd\uc73c\ub85c GPT\uc5d0\uac8c \ub2f5\ubcc0\uc744 \uc785\ub825\ud574\ub2ec\ub77c\uace0 \uc694\uccad\ubc1b\ub294\ub370, \uc774 \ubd80\ubd84\uc774 \ubb38\uc81c(\ud504\ub86c\ud504\ud2b8 \uc5d4\uc9c0\ub2c8\uc5b4\ub9c1 \ubd80\ubd84\uc774 \ubc18\ud658\ub41c\ub2e4.)\uac00 \uc880 \uc788\ub294 \uac83 \uac19\uc544\uc11c \uac1c\uc120\uc774 \ud544\uc694\ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat2",src:r(50885).Z+"",width:"2394",height:"1048"})}),"\n",(0,n.jsx)(t.h3,{id:"\ub2e4\ub978-\ud06c\ub8e8\uc758-\ucc44\ud305-\ubcf5\uc0ac\ud574\uc11c-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",children:"\ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["\ub2e4\ub978 \ud06c\ub8e8\ub4e4\uc758 \ucc44\ud305\uc744 \uc77d\ub2e4\uac00 \uad81\uae08\ud55c \uc810\uc774 \uc788\ub2e4\uba74 \ubcf5\uc0ac\ud574\uc11c \ubc14\ub85c \uc9c8\ubb38\uc744 \ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ucc44\ud305\uc774 \ubcf5\uc0ac\ub41c \ud6c4 \ubc14\ub85c GPT\uc640 \ub300\ud654\ub97c \ud560 \uc218 \uc788\ub294 \uba54\uc778 \ud654\uba74\uc73c\ub85c \uc774\ub3d9\ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\uc0ac\uc6a9\uc131-\uace0\ub824\ud558\uae30",children:"\uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat3",src:r(15153).Z+"",width:"1668",height:"718"})}),"\n",(0,n.jsxs)(t.p,{children:["\uc704 \ud654\uba74\uc740 \ud68c\uc6d0\uac00\uc785 \ucc3d\uc774\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc0ac\uc2e4 \uac00\uc7a5 \ub9c8\uc74c\uc5d0 \ub4dc\ub294 \ubd80\ubd84\uc774\uace0, \ud68c\uc6d0\uac00\uc785(\ub2c9\ub124\uc784\ub9cc \uc785\ub825\ud558\uc9c0\ub9cc)\ud560 \ub54c \uc775\uba85\uc744 \uc6d0\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uace0\ubbfc\uc744 \ub3c4\uc640\uc8fc\uac8c \ub054 \uc74c\uc2dd, \uacfc\uc77c, \uacfc\uc790 \ub4f1\uc758 \uc694\uc18c\ub4e4\uc744 \uc785\ub825\ud558\ub3c4\ub85d \uc720\ub3c4\ud588\ub2e4!\n\ucd94\uac00\ub85c GPT\uc758 \ub2f5\ubcc0\uc774 \uc624\uba74 \uc790\ub3d9\uc73c\ub85c \ud654\uba74\uc744 \uc2a4\ud06c\ub864 \ud574\uc8fc\ub294 \uac83\uacfc \uac19\uc774 \uc0ac\uc6a9\uc131\uc744 \uac1c\uc120\ud574 \ubcf4\ub824\uace0 \ub178\ub825\ud588\uc9c0\ub9cc \uc27d\uc9c0 \uc54a\uc558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc81c\uc77c \ud558\uace0 \uc2f6\uc740 \uac83\uc740 \uc2e4\uc81c GPT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ucc98\ub7fc stream/text \uac12\uc744 \ucc98\ub9ac\ud558\uace0 \uc2f6\uc740\ub370 \uc774 \ubd80\ubd84\uc740 \ubc29\ud559 \ub54c \uae30\ud68c\uac00 \ub418\uba74 \ub3c4\uc804\ud574 \ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ud5a5\ud6c4-\uacc4\ud68d",children:"\ud5a5\ud6c4 \uacc4\ud68d"}),"\n",(0,n.jsxs)(t.p,{children:["\uc2e4\uc81c \ud06c\ub8e8\ub4e4\uc774 \uc0ac\uc6a9\ud574 \uc8fc\ub294 \uc11c\ube44\uc2a4\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\ubcf4\uba74\uc11c \uc0ac\uc6a9\uc790\uc758 \uc785\uc7a5\uc5d0\uc11c \uace0\ubbfc\ub3c4 \ud558\uac8c \ub418\ub294 \uac83 \uac19\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud06c\ub8e8\ub4e4\uc774 \uc9c1\uc811 \uc0ac\uc6a9\ud574 \uc8fc\ub2c8\uae4c \ub108\ubb34 \uace0\ub9d9\uace0, \ud55c\ud3b8\uc73c\ub85c\ub294 \uc2e0\uae30\ud558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc77c\ub2e8 \ubc29\ud559 \ub54c stream/text \uad00\ub828\ub41c \ubd80\ubd84 \ub3d9\uc791\ub418\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\ub824\uace0 \ud558\uace0, \uadf8 \uc678\uc758 \ubd80\ubd84\uc740 \uc870\uae08 \ub354 \uace0\ubbfc\ud574\uc57c\ub420 \uac83 \uac19\ub2e4."]})]})}function d(e={}){const{wrapper:t}={...(0,c.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function c(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function s(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(c[r]=e[r]);return c}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var o=n.createContext({}),l=function(e){var t=n.useContext(o),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,c=e.mdxType,s=e.originalType,o=e.parentName,d=a(e,["components","mdxType","originalType","parentName"]),h=l(r),b=c,u=h["".concat(o,".").concat(b)]||h[b]||p[b]||s;return r?n.createElement(u,i(i({ref:t},d),{},{components:r})):n.createElement(u,i({ref:t},d))}));d.displayName="MDXCreateElement"},49483:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat1-e9408e2e2f13bb192541de194ffccc6a.png"},50885:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat2-4b3b653eb2b23b88f19e8cb4177a786c.png"},15153:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat3-12a510067e4d210c13e46b7b99313307.png"}}]); \ No newline at end of file diff --git a/assets/js/4a1c8300.cdb79bf0.js b/assets/js/4a1c8300.e8eaab32.js similarity index 97% rename from assets/js/4a1c8300.cdb79bf0.js rename to assets/js/4a1c8300.e8eaab32.js index 665badcd2..e2ff335cf 100644 --- a/assets/js/4a1c8300.cdb79bf0.js +++ b/assets/js/4a1c8300.e8eaab32.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3324],{74122:(A,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>s,default:()=>o,frontMatter:()=>I,metadata:()=>j,toc:()=>w});var r=n(85893),t=n(3905),E=n(17779);const I={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",slug:"woowacourse-level3-retrospective",tags:["Woowahan Techcourse","Retrospective"]},s=void 0,j={permalink:"/woowacourse-level3-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",description:"\ud68c\uace0",date:"2023-08-19T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 19\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.945,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",slug:"woowacourse-level3-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",permalink:"/db-replication"},nextItem:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/cloudwatch"}},c={authorsImageUrls:[]},w=[{value:"\ud68c\uace0",id:"\ud68c\uace0",level:3},{value:"\uc544\uc26c\uc6b4 \uc810",id:"\uc544\uc26c\uc6b4-\uc810",level:3},{value:"\uc88b\uc558\ub358 \uc810",id:"\uc88b\uc558\ub358-\uc810",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3}];function l(A){const e={a:"a",br:"br",h3:"h3",p:"p",strong:"strong",...(0,t.ah)(),...A.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(e.h3,{id:"\ud68c\uace0",children:"\ud68c\uace0"}),"\n",(0,r.jsxs)(e.p,{children:["\uc9c0\ub09c 8\uc8fc\ub294 \ub808\ubca8 1, 2 \ub54c\ubcf4\ub2e4 5\ubc30 \uc815\ub3c4 \ube60\ub974\uac8c \uc9c0\ub098\uac04 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub808\ubca8 3\uc5d0\ub294 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4, \uae30\uc220 \uc678\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4 \ubd80\uc871\ud568\uc774 \ub9ce\uc774 \ubcf4\uc600\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubd80\uc871\ud55c \ubd80\ubd84\uc744 \uc54c\uc558\uae30\uc5d0, \uc55e\uc73c\ub85c \ub354\uc6b1 \uc131\uc7a5\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub0b4\uac00 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \ud300\uc6d0\ub4e4\uc774 \uc798 \ubcf4\ucda9\ud574 \uc918\uc11c \ub4e0\ub4e0\ud588\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\uc544\uc26c\uc6b4-\uc810",children:"\uc544\uc26c\uc6b4 \uc810"}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ubb38\uc11c\ud654"})}),"\n",(0,r.jsxs)(e.p,{children:["\uac1c\uc778\uc801\uc73c\ub85c\ub294 \uae30\uc220 \uc678\uc801\uc73c\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ub0b4\uac00 \ud55c \ubd80\ubd84\uc744 \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c, \uc774\ud574\ud558\uae30 \uc27d\uac8c \ubb38\uc11c\ud654\ub97c \ud588\ub354\ub77c\uba74 \ud300\uc6d0\ub4e4\uc5d0\uac8c \ub354\uc6b1 \ub3c4\uc6c0\uc774 \ub418\uc5c8\uc744 \ud150\ub370 \uc774 \ubd80\ubd84\uc5d0 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ud22c\uc790\ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc5d0\uc11c \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubc29\ud559 \uae30\uac04 \ub3d9\uc548 \ubb38\uc11c\ud654\ub97c \ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc778 \ube14\ub85c\uadf8 \uc62c\ub9ac\uba74\uc11c \uc870\uae08 \ub354 \ucc44\uc6cc\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ub0b4\uac00 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc774\uc790"})}),"\n",(0,r.jsxs)(e.p,{children:["\uc798 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc5ec\uc11c\ub77c\ub3c4 \uc911\uac04\uc740 \uac00\ub3c4\ub85d \ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub9d0\uc744 \ud558\uae30 \uc804\uc5d0 \uc815\ub9ac\ud574\uc11c \uc758\uacac\uc744 \ub0b4\ub294 \uac83, \ubc1c\ud45c \uc900\ube44, \uac10\uc815 \uc870\uc808 \ub4f1\ub4f1\n\ubabb\ud558\ub294 \ubd80\ubd84\uc744 \uc778\uc9c0\ud558\uace0, \uac1c\uc120\ud558\uc790."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ucef4\ud3ec\ud2b8 \uc874 \ubc97\uc5b4\ub098\uae30"})}),"\n",(0,r.jsxs)(e.p,{children:["\uc870\uae08 \ub354 \ub3c4\uc804\uc801\uc73c\ub85c \ubaa9\ud45c\ub97c \uc7a1\uc558\uc73c\uba74 \uc88b\uc558\uc744 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub9e4\ubc88 \uadfc\uac70\ub97c \uac00\uc9c0\uace0 \uae30\uc220\uc744 \ub3c4\uc785\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud558\uc9c0\ub9cc \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub824\uace0 \ud558\ub294 \ubd80\ubd84\uc774 \ub2e4\uc18c \ubd80\uc871\ud588\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\uc88b\uc558\ub358-\uc810",children:"\uc88b\uc558\ub358 \uc810"}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\uc88b\uc558\ub358 \uc810\ub3c4 \ubb38\uc11c\ud654"})}),"\n",(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.a,{href:"https://tripdraw.blog",children:"\ud300 \ube14\ub85c\uadf8"}),"\ub3c4 \uba3c\uc800 \ub3c4\uc785\ud558\uc790\uace0 \uc81c\uc548\ud558\uace0, \ub0b4\uac00 \ud588\ub358 \ubd80\ubd84\uc740 \ubb38\uc11c\ud654\ub97c \uaf64 \ub9ce\uc774 \ud574\uc11c \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubc31\uc5d4\ub4dc \ud06c\ub8e8 4\uba85\uc774\uc11c \uac19\uc774 \ud55c \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c\ub294 \uae30\ub2a5 \uad6c\ud604\ud55c\ub2e4\uace0 \ubb38\uc11c\ud654\uac00 \uc870\uae08 \ubbf8\ud761\ud574\uc11c \ubcf4\ucda9\uc744 \ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ub0b4\uac00 \ub514\uc790\uc778\ud55c \ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0"})}),"\n",(0,r.jsx)("img",{src:E.Z,width:"100"}),"\n",(0,r.jsxs)(e.p,{children:["\ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0\ub97c \ub9cc\ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud300\uc6d0\ub4e4\uc774 \ub300\ud45c \uc0c9\uc0c1(\ud30c\ub780\uc0c9)\uc744 \uc815\ud574\uc92c\uace0, \uc8fc\ub9d0 \ub3d9\uc548 \uc2e0\ub098\uac8c \ub85c\uace0 \ub514\uc790\uc778\uc744 \ud588\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\uc544\ub798\uc758 D \ubd80\ubd84\uc740 \uc720\ud29c\ube0c \uac15\uc758 \ub4e4\uc73c\uba74\uc11c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\uc11c \ubfcc\ub4ef\ud558\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\uae30\uc220 \uc120\ud0dd\uc758 \uc774\uc720"})}),"\n",(0,r.jsxs)(e.p,{children:["\uae30\uc220\uc758 \ud559\uc2b5 \ube44\uc6a9, \ud604\uc7ac \uad6c\uc870\uc5d0 \uc801\ud569\ud55c\uc9c0, \uc2e4\uc81c \uac00\uc9c0\uace0 \uc788\ub294 \ub9ac\uc18c\uc2a4\ub97c \uace0\ub824\ud574\uc11c \uae30\uc220 \uc120\ud0dd\uc744 \ud558\uace0, \ub3c4\uc785\ud588\ub358 \ubd80\ubd84\uc774 \uc88b\uc558\ub2e4.",(0,r.jsx)(e.br,{}),"\n","100% \uc88b\uc740 \uc120\ud0dd\uc77c \uc21c \uc5c6\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \uc120\ud0dd\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \uc874\uc7ac\ud55c\ub2e4\uba74 \ud655\ub960\uc744 \ub192\ud600\uc8fc\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,r.jsxs)(e.p,{children:["\ud50c\ub808\uc774\uc2a4\ud1a0\uc5b4\uc5d0 \uc571\uc774 \uc62c\ub77c\uac00 \uc788\ub294 \uac70 \ub108\ubb34 \uc2e0\uae30\ud558\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\uc548\ub4dc\ub85c\uc774\ub4dc \ube0c\ub808\uba58 \uc74c\uc545\ub300(\uba67\ub3fc\uc9c0, \uc218\ub2ec, \ud551\uad6c), \uadf8\ub9ac\uace0 \ubc31\uc5d4\ub4dc \ud300\uc6d0\ub4e4(\uccb4\uc778\uc800, \ud6c4\ucd94, \ub9ac\uc624) \ub108\ubb34 \uace0\uc0dd\uc774 \ub9ce\uc558\ub2e4."]})]})}function o(A={}){const{wrapper:e}={...(0,t.ah)(),...A.components};return e?(0,r.jsx)(e,{...A,children:(0,r.jsx)(l,{...A})}):l(A)}},3905:(A,e,n)=>{n.d(e,{ah:()=>c});var r=n(67294);function t(A,e,n){return e in A?Object.defineProperty(A,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):A[e]=n,A}function E(A,e){var n=Object.keys(A);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(A);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(A,e).enumerable}))),n.push.apply(n,r)}return n}function I(A){for(var e=1;e=0||(t[n]=A[n]);return t}(A,e);if(Object.getOwnPropertySymbols){var E=Object.getOwnPropertySymbols(A);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(A,n)&&(t[n]=A[n])}return t}var j=r.createContext({}),c=function(A){var e=r.useContext(j),n=e;return A&&(n="function"==typeof A?A(e):I(I({},e),A)),n},w={inlineCode:"code",wrapper:function(A){var e=A.children;return r.createElement(r.Fragment,{},e)}},l=r.forwardRef((function(A,e){var n=A.components,t=A.mdxType,E=A.originalType,j=A.parentName,l=s(A,["components","mdxType","originalType","parentName"]),o=c(n),i=t,h=o["".concat(j,".").concat(i)]||o[i]||w[i]||E;return n?r.createElement(h,I(I({ref:e},l),{},{components:n})):r.createElement(h,I({ref:e},l))}));l.displayName="MDXCreateElement"},17779:(A,e,n)=>{n.d(e,{Z:()=>r});const r="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAbAAAAGwCAYAAADITjAqAAAACXBIWXMAACxLAAAsSwGlPZapAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAABauSURBVHgB7d1viF3lncDx59yJsZpWU6wxoqmjLthGS2vBP4u7dEqb7FIXVKIFX9Qa3xTqiyisfWeNyEKphWZgLesbxyqLi4m0wiprXHCWIlUD1bKaRljt1CjGfzSmjdaYzNn73Dg2f5wkk8w95/nd+/nANCaZ0HHM3O/8nuc551SpRYvHJhYvXLhgrJquR+sqfblK9WiqqtGPfns0AdC6uk7bq6qaSvX09jpVU52q/kOanp78y+703PbJ1dtTS6rUoI+DVU2Ppbq6IokUQHRT3QFksvua/vCuXbsnmwxaIwFb+s2JsbozsqZb8W680uIEwEDqxuzeHLM3N37nl6nP+hawj6atNd3Z8ybRAhg6U1Wdbk8f7pncNrl6KvXBvAdMuADYx1R33+ze7kR2e5pn8xqwpSvuu747Pt6W7G0BsL/eRLbt8evuTfNkXgK2dGxitD5uwUSq6rEEALP7ZbVrz83zsazYScfotBX3r5k+buRZ8QLgCFxZLxx5Nq/YpWN01BNY3us6fuFIXi68KQHAXFVp3RuPXXdzOkpHFbDekuHCkXxE8ssJAI5a9Vy1a/dVR7OkOOeAfRSvJ5KDGgDMj6nuvtjX5xqxOQVMvADokzlH7IgDJl4A9NmcInZEARMvABpyxBE7omP0Hx3YGE0A0F/dgWnBL/JJ98O942EDdtrK+36anDYEoDH1V44/vneZ1iGNHOo3exeaVelHCQCademn/+aqd3e+9IunZnuHWffA8r5XvsOGG/IC0JLt3f2wC2fbD5t1CbG77/VT8QKgRYvr4zsTs/3mJwbso3tUXZkAoE11NTbbfRM7n/z+6bCbZwDQhNykTzqVeFDAlqy83/O8ACjJ6KcWdg66cfx+hzhcsAxAobZ/sGvP2dsnV2+f+YX9J7DjRsaSeAFQnsUHTmH7BczeFwClqlO1Zt+ffxywJd+4P586HE0AUKbFS785MTbzk79OYCPTjs0DULS6M/LxFNY7xJGPJx6/cOSPCQDK9vFhjt4EtnBkwVgCgPItPmHh3mbtXUK0fAhAENNVGss/9gJWpeprCQAiqOsr8g+V/S8Aounug32286kF6SsJAALJ+2Cd1OmMJQAIZLqqR/Me2GgCgECqlL7cqevOWQkAAqmnuxNYnTx1GYBgqiovIdajCQCC6VSVCQyAcEY7CQACEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQlqQAPrkzCUnpi+edXI6adFx3X8+IZ104nHp5EULP/F93925K+1478P0p50fps1TO9KO3o/vJpiNgLUkf0FfPbYsrbjo9HTmqSf2vtCJ49U33+u9uD6+6fW0YXJrIqVLz/9cWj56Uvdtcbpk+Snz9nc6f57z5/vpzW/3wvbUC28nyKrTVt5XJxqVv7AfWHtZL1zEl19gv3fnM70X2WGS/x6vvGhp75uw5aN7p6ym5Ijlbx42bto2dJ93/krAGiZegym/oF679sk06PLf31VfW9ZdPfh8MasG+RuIiUdeSk9tfkfMhowlxIb1llbEa+Dk5bM8jeSJYNDsu9yd/z1Lk6e/O2/8au+fNz6zd0k3T2cMPgFr2DVjZyUG06ruVDJIAcvhWv2tc9INl5/b6PLgsVh58em9t1ffei+NP7jF/uSAE7CGfbG7yc1gWn72yWkQ5KXBNdec11smjCqvcuSpbM23vyBkA8weWMN+v/6KxOA6+5qHU1SDEK7Z5InslruedYJxwJjAYMhFXCqcqzyR5cNTeRIbX7/FYY8BIWAwxFaNLUs/vP5LAxuuA+XDKJeef4plxQEhYDCE8nLhnd+/sMhThf02sz92yfmnmsaCcy9EGDJ5qfCRH48NZbz2laex3jWZ7oITloDBkMjLhLdef0HvbViWDA8nT2O/umtFbw+QeCwhwhDIU8bdt1zcu+iXg/1w9d59wPH1LybiMIHBgMvRyktl4nVoN337C929sQsTcZjAYIDNxMuS4ZHJ18DlR77ka8byo10omwkMBpR4HZ18K6oHbr+sFzLKJmAwgMTr2OTP362rL0iUTcBgwMw8ske8jk1eTrQnVjYBgwEiXvMrRyzfH5IyCRgMiBwtD0udf/l04iDe4HgQCBgMiHyBsnj1R/7cugyhPAIGA+Cma0wJ/ZSn27t/cLGTiYURMAiu9xyvb9un6bc83eYHZFIOAYPg8r4Xzbjh8nPSiotOT5RBwCCwvHRo36tZP7nxQkuJhRAwCMrSYTvyfpilxDIIGARl6bA9eSlx2J+nVgIBg4DyQyktHbbLBc7tEzAIJi8drr7cAxjblicwU1i7BAyCyd/5m77K4F6J7RIwCCRPXy5YLkf+RuLqsWWJdggYBGLfpTyrfEPRGgGDebJjZ3+f4Gv6KpO9sPYIWMNefeu9xGDq939b01e5/Ldpx4JEozZPvWsDfkBtntqR+iXy9JUn0xz3P+3cvd+vf2bRgoG5w3uewPLdOXa8198pnP0JWMMemtyaVrqX2kAaf3BL6pdI3+HnYG2YfCU9vfmd3jdsr7556Mk0RywHIH9dXHL+KSmq1f90TvfvwIuJ5lSnrbyvTjTqP9b+XegvVA52zyMvpTvufT71Q56+fnXXilS6p154O42vf7H349HKqxM5ZvkWWdFWKvKU+ffffzzRnJFPn3vV2kSj8hd4vp+aB+TFl6eNf3v4/9KP/31z6pcVFy1NKy8ud2rfuGlbuv5ffp0mHn35mPcB8xJcntomHnk5vfbW+2n52Sf3vlYiyB9nnjrtczfHBNai/B1m/gL94uhJadmpi1IbzlhyQrp0ecwTVE9tfju99ub7qQ1b39rZXRp7Pz3+zOt93/f41c9WFDmN5BfqW+569pgmrsPZ+wyu88Ls/61bv8UyYoPsgbUovwDkt43dF8G2rBpbFjZgG554pbenOMjyclqJ8cp7XHdMPN/3eM9E8ndTO9Kt11+QSpe/lsaTgDXFMXoo2KoC7/KQp4wclSZP3OU9xstvmez7tXbHauY0Is0QMChUiUfn21wiy3tj1659sviIrbh4aaIZAgaFumR5WSdVS9jfyRH73p3PpJI5nNUcAYNCXTN2VipFXsIr5XBCPjTSr0sW5kPJJ0YHjYBBgfLyYSnXCuaDFKUFIwf16RfeSSXKh27sgzVDwKBAJd2t5drbnkwl+ue7flPsflj+BoT+EzAoUCkBy/tepV6Ymz+ufPF0ifK1nfSfgEFhSlk+zIF46Imyr7PLS4klTmEOcjRDwKAwpZw+zIc2Sr8tUo5XiVOYJ040Q8CgMKWcPuznLaLmU57CSmMPrBkCBgXJN4QtYflww+TWMDelzVNYaScSTWDNEDAoSCl7J4+3eH/Oo5Fv7FySKHfQj07AoCCl3IZo46ZgAStwudMU1n8CBgUp4ckAUfa+9pVvMcXwETAoRN74L2EJMWIM8j6YB0kOHwGDQpRy8WvUELT1cNPZOInYfwIGhSjl7hv54ZER5adkM1wEDArh7g0wNwIGBcjHrksJ2Ktv2ksiBgGDApi+jt2yUxelkvhGoP8EDApQyrO/MocPiELAoAB/u/zUVIqoD2Ms7REmjvX3n4BBAUp68T1jyQkpmjw1un3T8BEwaFlpL74R9+NMX8NJwKBlpb34Xnp++7ezmqtSrqGb4QBHMwQMWlbaxJNvQhttH6y06JrAmiFg0LISl+xWfX1ZiiLHq7Q7vwtYMwQMWlbiYzdKW5I7lFVj5cX2d7+PeTuuaAQMWlbiBJanmgh7YfkAzNVjn0+lMYE1Q8CgRcvPLvfE35przkulK/Vj9HyyZggYtOiMU8u95qr0KSxPriVOXxEfCBqVgEGLSr/mquQp7O4fXJxKZPpqjoBBi0oPWJ7AVn/rnFSaW6+/oMjDL9nTL7yTaIaAQYtOPnFhKt0PV3+pqKXEGy4/t/dWKhNYcwQMWlTaXThmc/ctFxdxl/q855Wnr1LleDmB2BwBg5bk+x9GuQFt/jgfWHtZqxHL8brzxgtTyRzgaJaAQUuiPXcr7znliLWxb5eXDEuPV/b4pm2J5ggYtCTic7dyxB65c6yxgx158rvz+xcWvWw4Iy8dmsCatSABrYj42JIZ+WDH8rMXp/H1W/p25/V8cCRPXaWeNjzQU04fNk7AoCWfWRT7y+/qsWW9t3seeSlNPPryvIUshytffxbtsS7jD25JNEvAoCWRJ7B9zRxr3zC5NT00+cpRLaPlpcIcwxUXnR7yeWT539npw+YJGLQkwjVgczEzke3Y+WHvBf3pzW+nzVM7ej/f8d6H+71vXhY8o/u2fPSkXrCix3x8/YuJ5gkYtCT6EuJs8jS18uLTe2/DwOGN9jiFCC2JcjiBQxt/0PTVFgGDFkS6iJnZ5elrQ3ffj3YIGLQg4jVgHOyWu55NtEfAoAXR7sLBwfKpS3tf7RIwgDnKJytd99U+AYMWlPwkZg7vnkdfct1XAQQMWmAJMa4cLicPyyBgAEcoLx1ee9uTiTIIGLTANWAx5TtuWDosh4ABHIF80+L8RjkEDFqw7NRFiTjse5VJwAAOIccr73sdeENi2idg0IJBvZHvIPrej5+x71UoAYMWuA9iDLf87Nm0eerdRJkEDOATrFu/JW14wo16SyZg0ALH6MuW4+XQRvkEDGAf4hWHgAF8RLxiETCAJF4ROcsLDbP/VZ477n3eXTYCEjBgaOWb8+anKm/c9HoiHgEDhlK+ODlfpOw6r7gEDBg6OVrusBGfgAFDZcPkK+mOiefd23AACBgwNBzWGCwCBgy8vFSYD2s89cLbicEhYMBA27hpW7rlX39jyXAACRg07MwlrgNrQj4iP77+RUuGA0zAoGEmgf7LS4V5ydApw8EmYNCwHX8WsH7KU9e6B7ckBp+AAQPB1DV8BAwIzV7X8BIwIKx8wvCOif81dQ0pAQPCcV0XmYABYeTlwolHX3ZIgx4BA0LIe1z5gZMuQ2CGgAFFc7qQ2QgYNMwL8ZHJ4cqnC+1zMRsBA4oiXBwpAQOKIFzMlYABrRIujpaAQQvyPtiZpw73XemFi2MlYECjNkxuTQ9NviJcHDMBA/pu5gLke/7zJddxMW8EDFrw2pvvD8US4uapd7vT1ta04YlXhIt5J2DAvLO/RRMEDFqw9a2d6ZJ0ShoklglpmoABx8S0RVsEDFoQfULJe1uPb9pm2qJVAgYtyMtt0eSPecPkK71wmbYogYBBC/60c3eKIEcrT1t5iXDz7981bVEUAYMWvLtzVypZnrDypOX4OyUTMGhBiVEQLaIRMGjBa2+9n9o2szwoWkQlYNCCHX9uJxY5WjlYv87T1jOvixahCRhhlTDFHK18N/qm7kj/6pvvpY2bXnd6kIEjYEPu6RfeSVHlU3GR5XsErrnmvDTf9l0azOHKAYNBJGBDLk8B+QXvpEXHpUjyJBF9+eueR15Kq8aWzcsUloM1cwjDcXeGhYDRu8bn1usvSJHk6SW6/I3Dtbc9mR64/bI5R2xmWXDz1A57WQyt6rSV99WJoXfr6gvSDd86N0Wwbv2WNP7gi2lQ5Hj95MavpkvOn/3mvjlYT29+p3f44unNb1sWhCRg7OPS8z/XW9JaPnpy70W1lGXFPKnkpc6ZJbJBPYiQP/8rLlqali1Z1Pv51jd3mrDgEAQMgJA6CQACEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAELKAZtKABDLdhMYAAFVU51UV1MJACKpp7d3qmr6DwkAAqk63Qmsnq6eSwAQSV3/oVNbQgQgmunpyc6uPbsnEwAE8pfd6bnO9snV25Oj9ABEUaWp3K69x+jr+uEEAAFUKU3mH3sBq6c7kwkAAqjqqjd09QKW98HqOm1PAFC493ftPbvRC1heS6yq+n8SABSsqtK9H53d+OvNfKvp6XUJAAo2s3zY++d9f2PJivv+2K3b4gQApanS1BuPXXf2zE/3u5lvp6rHEwAUqJpOt+/78/0C9pdd0+sc5gCgON3pK43smdz3l/YLWO/CMFMYAIWp6vrn2/5r9dS+v3bQ88DyFNYrHQCUoNukbRu/u/bAXz4oYL0j9QesMwJAW2ZrUjXbHzjtH+5/ItX1WAKA1lS/fGPjd676pN/pzPpHqt2rHegAoC11d1Gw6uy+ebbfnzVgebOsqi0lAtCOTp1uPvDgxr5GDvWHd778i6c+fc6Vn+2OY5cmAGhKVY2/sfG6Hx3qXTrpMD74cHptnarnEgA047dvPPadmw73TocNWO/asM7uqxytB6Dvuq2pOnuuPLJ3PUJL/3FitK5Hnujuqo0mAJhvOV7Vnq8fat9r/3efAxEDoC/mGK+9f2SORAyAeXUU8coOuwd2oN7x+u7/kYMdAMyD3x5NvLI5T2D7Om3Fz9elqlqTAGCuqmr8gw92r515wvKc/3g6RktX3Hf9dEo/9SBMAI5E7w4bVbr9jceuW5eOwTEHLOvti013uh9IdUUCgNnU1WQ1snv10SwZHmheAjYjT2N1J93mgAcA+8kHNabT7dsev+7eNE/mNWAzlq78+dq6qr4rZADDLS8XdlI9np81ebR7XbPpS8CyvKyY9oyMmcgAhk8/wzWjbwHb15JvTFzZGelcWafuVAbAQOodzkjdPa7p3ePb/nv1ZOqzRgI2Y/HYxOKFI2msF7Oq+prJDCC8qVTVD9e7pyd37UmT/Zq2PkmjATtQDtqnFqSvpE5nbLquzuqWe7Rb8MXdT8ZolRzLByjEVO9/62qqTnV+VuRv63rPVNPBOtD/A6oeNVega6lDAAAAAElFTkSuQmCC"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3324],{74122:(A,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>s,default:()=>o,frontMatter:()=>I,metadata:()=>j,toc:()=>w});var r=n(85893),t=n(3905),E=n(17779);const I={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",slug:"woowacourse-level3-retrospective",tags:["Woowahan Techcourse","Retrospective"]},s=void 0,j={permalink:"/woowacourse-level3-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",description:"\ud68c\uace0",date:"2023-08-19T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 19\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.945,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",slug:"woowacourse-level3-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/cloudwatch"},nextItem:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",permalink:"/db-replication"}},c={authorsImageUrls:[]},w=[{value:"\ud68c\uace0",id:"\ud68c\uace0",level:3},{value:"\uc544\uc26c\uc6b4 \uc810",id:"\uc544\uc26c\uc6b4-\uc810",level:3},{value:"\uc88b\uc558\ub358 \uc810",id:"\uc88b\uc558\ub358-\uc810",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3}];function l(A){const e={a:"a",br:"br",h3:"h3",p:"p",strong:"strong",...(0,t.ah)(),...A.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(e.h3,{id:"\ud68c\uace0",children:"\ud68c\uace0"}),"\n",(0,r.jsxs)(e.p,{children:["\uc9c0\ub09c 8\uc8fc\ub294 \ub808\ubca8 1, 2 \ub54c\ubcf4\ub2e4 5\ubc30 \uc815\ub3c4 \ube60\ub974\uac8c \uc9c0\ub098\uac04 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub808\ubca8 3\uc5d0\ub294 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4, \uae30\uc220 \uc678\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4 \ubd80\uc871\ud568\uc774 \ub9ce\uc774 \ubcf4\uc600\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubd80\uc871\ud55c \ubd80\ubd84\uc744 \uc54c\uc558\uae30\uc5d0, \uc55e\uc73c\ub85c \ub354\uc6b1 \uc131\uc7a5\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub0b4\uac00 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \ud300\uc6d0\ub4e4\uc774 \uc798 \ubcf4\ucda9\ud574 \uc918\uc11c \ub4e0\ub4e0\ud588\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\uc544\uc26c\uc6b4-\uc810",children:"\uc544\uc26c\uc6b4 \uc810"}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ubb38\uc11c\ud654"})}),"\n",(0,r.jsxs)(e.p,{children:["\uac1c\uc778\uc801\uc73c\ub85c\ub294 \uae30\uc220 \uc678\uc801\uc73c\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ub0b4\uac00 \ud55c \ubd80\ubd84\uc744 \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c, \uc774\ud574\ud558\uae30 \uc27d\uac8c \ubb38\uc11c\ud654\ub97c \ud588\ub354\ub77c\uba74 \ud300\uc6d0\ub4e4\uc5d0\uac8c \ub354\uc6b1 \ub3c4\uc6c0\uc774 \ub418\uc5c8\uc744 \ud150\ub370 \uc774 \ubd80\ubd84\uc5d0 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ud22c\uc790\ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc5d0\uc11c \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubc29\ud559 \uae30\uac04 \ub3d9\uc548 \ubb38\uc11c\ud654\ub97c \ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc778 \ube14\ub85c\uadf8 \uc62c\ub9ac\uba74\uc11c \uc870\uae08 \ub354 \ucc44\uc6cc\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ub0b4\uac00 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc774\uc790"})}),"\n",(0,r.jsxs)(e.p,{children:["\uc798 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc5ec\uc11c\ub77c\ub3c4 \uc911\uac04\uc740 \uac00\ub3c4\ub85d \ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub9d0\uc744 \ud558\uae30 \uc804\uc5d0 \uc815\ub9ac\ud574\uc11c \uc758\uacac\uc744 \ub0b4\ub294 \uac83, \ubc1c\ud45c \uc900\ube44, \uac10\uc815 \uc870\uc808 \ub4f1\ub4f1\n\ubabb\ud558\ub294 \ubd80\ubd84\uc744 \uc778\uc9c0\ud558\uace0, \uac1c\uc120\ud558\uc790."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ucef4\ud3ec\ud2b8 \uc874 \ubc97\uc5b4\ub098\uae30"})}),"\n",(0,r.jsxs)(e.p,{children:["\uc870\uae08 \ub354 \ub3c4\uc804\uc801\uc73c\ub85c \ubaa9\ud45c\ub97c \uc7a1\uc558\uc73c\uba74 \uc88b\uc558\uc744 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ub9e4\ubc88 \uadfc\uac70\ub97c \uac00\uc9c0\uace0 \uae30\uc220\uc744 \ub3c4\uc785\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud558\uc9c0\ub9cc \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub824\uace0 \ud558\ub294 \ubd80\ubd84\uc774 \ub2e4\uc18c \ubd80\uc871\ud588\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\uc88b\uc558\ub358-\uc810",children:"\uc88b\uc558\ub358 \uc810"}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\uc88b\uc558\ub358 \uc810\ub3c4 \ubb38\uc11c\ud654"})}),"\n",(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.a,{href:"https://tripdraw.blog",children:"\ud300 \ube14\ub85c\uadf8"}),"\ub3c4 \uba3c\uc800 \ub3c4\uc785\ud558\uc790\uace0 \uc81c\uc548\ud558\uace0, \ub0b4\uac00 \ud588\ub358 \ubd80\ubd84\uc740 \ubb38\uc11c\ud654\ub97c \uaf64 \ub9ce\uc774 \ud574\uc11c \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ubc31\uc5d4\ub4dc \ud06c\ub8e8 4\uba85\uc774\uc11c \uac19\uc774 \ud55c \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c\ub294 \uae30\ub2a5 \uad6c\ud604\ud55c\ub2e4\uace0 \ubb38\uc11c\ud654\uac00 \uc870\uae08 \ubbf8\ud761\ud574\uc11c \ubcf4\ucda9\uc744 \ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\ub0b4\uac00 \ub514\uc790\uc778\ud55c \ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0"})}),"\n",(0,r.jsx)("img",{src:E.Z,width:"100"}),"\n",(0,r.jsxs)(e.p,{children:["\ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0\ub97c \ub9cc\ub4e4\uc5c8\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\ud300\uc6d0\ub4e4\uc774 \ub300\ud45c \uc0c9\uc0c1(\ud30c\ub780\uc0c9)\uc744 \uc815\ud574\uc92c\uace0, \uc8fc\ub9d0 \ub3d9\uc548 \uc2e0\ub098\uac8c \ub85c\uace0 \ub514\uc790\uc778\uc744 \ud588\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\uc544\ub798\uc758 D \ubd80\ubd84\uc740 \uc720\ud29c\ube0c \uac15\uc758 \ub4e4\uc73c\uba74\uc11c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\uc11c \ubfcc\ub4ef\ud558\ub2e4."]}),"\n",(0,r.jsx)(e.p,{children:(0,r.jsx)(e.strong,{children:"\uae30\uc220 \uc120\ud0dd\uc758 \uc774\uc720"})}),"\n",(0,r.jsxs)(e.p,{children:["\uae30\uc220\uc758 \ud559\uc2b5 \ube44\uc6a9, \ud604\uc7ac \uad6c\uc870\uc5d0 \uc801\ud569\ud55c\uc9c0, \uc2e4\uc81c \uac00\uc9c0\uace0 \uc788\ub294 \ub9ac\uc18c\uc2a4\ub97c \uace0\ub824\ud574\uc11c \uae30\uc220 \uc120\ud0dd\uc744 \ud558\uace0, \ub3c4\uc785\ud588\ub358 \ubd80\ubd84\uc774 \uc88b\uc558\ub2e4.",(0,r.jsx)(e.br,{}),"\n","100% \uc88b\uc740 \uc120\ud0dd\uc77c \uc21c \uc5c6\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \uc120\ud0dd\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \uc874\uc7ac\ud55c\ub2e4\uba74 \ud655\ub960\uc744 \ub192\ud600\uc8fc\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(e.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,r.jsxs)(e.p,{children:["\ud50c\ub808\uc774\uc2a4\ud1a0\uc5b4\uc5d0 \uc571\uc774 \uc62c\ub77c\uac00 \uc788\ub294 \uac70 \ub108\ubb34 \uc2e0\uae30\ud558\ub2e4.",(0,r.jsx)(e.br,{}),"\n","\uc548\ub4dc\ub85c\uc774\ub4dc \ube0c\ub808\uba58 \uc74c\uc545\ub300(\uba67\ub3fc\uc9c0, \uc218\ub2ec, \ud551\uad6c), \uadf8\ub9ac\uace0 \ubc31\uc5d4\ub4dc \ud300\uc6d0\ub4e4(\uccb4\uc778\uc800, \ud6c4\ucd94, \ub9ac\uc624) \ub108\ubb34 \uace0\uc0dd\uc774 \ub9ce\uc558\ub2e4."]})]})}function o(A={}){const{wrapper:e}={...(0,t.ah)(),...A.components};return e?(0,r.jsx)(e,{...A,children:(0,r.jsx)(l,{...A})}):l(A)}},3905:(A,e,n)=>{n.d(e,{ah:()=>c});var r=n(67294);function t(A,e,n){return e in A?Object.defineProperty(A,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):A[e]=n,A}function E(A,e){var n=Object.keys(A);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(A);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(A,e).enumerable}))),n.push.apply(n,r)}return n}function I(A){for(var e=1;e=0||(t[n]=A[n]);return t}(A,e);if(Object.getOwnPropertySymbols){var E=Object.getOwnPropertySymbols(A);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(A,n)&&(t[n]=A[n])}return t}var j=r.createContext({}),c=function(A){var e=r.useContext(j),n=e;return A&&(n="function"==typeof A?A(e):I(I({},e),A)),n},w={inlineCode:"code",wrapper:function(A){var e=A.children;return r.createElement(r.Fragment,{},e)}},l=r.forwardRef((function(A,e){var n=A.components,t=A.mdxType,E=A.originalType,j=A.parentName,l=s(A,["components","mdxType","originalType","parentName"]),o=c(n),i=t,h=o["".concat(j,".").concat(i)]||o[i]||w[i]||E;return n?r.createElement(h,I(I({ref:e},l),{},{components:n})):r.createElement(h,I({ref:e},l))}));l.displayName="MDXCreateElement"},17779:(A,e,n)=>{n.d(e,{Z:()=>r});const r="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAbAAAAGwCAYAAADITjAqAAAACXBIWXMAACxLAAAsSwGlPZapAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAABauSURBVHgB7d1viF3lncDx59yJsZpWU6wxoqmjLthGS2vBP4u7dEqb7FIXVKIFX9Qa3xTqiyisfWeNyEKphWZgLesbxyqLi4m0wiprXHCWIlUD1bKaRljt1CjGfzSmjdaYzNn73Dg2f5wkk8w95/nd+/nANCaZ0HHM3O/8nuc551SpRYvHJhYvXLhgrJquR+sqfblK9WiqqtGPfns0AdC6uk7bq6qaSvX09jpVU52q/kOanp78y+703PbJ1dtTS6rUoI+DVU2Ppbq6IokUQHRT3QFksvua/vCuXbsnmwxaIwFb+s2JsbozsqZb8W680uIEwEDqxuzeHLM3N37nl6nP+hawj6atNd3Z8ybRAhg6U1Wdbk8f7pncNrl6KvXBvAdMuADYx1R33+ze7kR2e5pn8xqwpSvuu747Pt6W7G0BsL/eRLbt8evuTfNkXgK2dGxitD5uwUSq6rEEALP7ZbVrz83zsazYScfotBX3r5k+buRZ8QLgCFxZLxx5Nq/YpWN01BNY3us6fuFIXi68KQHAXFVp3RuPXXdzOkpHFbDekuHCkXxE8ssJAI5a9Vy1a/dVR7OkOOeAfRSvJ5KDGgDMj6nuvtjX5xqxOQVMvADokzlH7IgDJl4A9NmcInZEARMvABpyxBE7omP0Hx3YGE0A0F/dgWnBL/JJ98O942EDdtrK+36anDYEoDH1V44/vneZ1iGNHOo3exeaVelHCQCademn/+aqd3e+9IunZnuHWffA8r5XvsOGG/IC0JLt3f2wC2fbD5t1CbG77/VT8QKgRYvr4zsTs/3mJwbso3tUXZkAoE11NTbbfRM7n/z+6bCbZwDQhNykTzqVeFDAlqy83/O8ACjJ6KcWdg66cfx+hzhcsAxAobZ/sGvP2dsnV2+f+YX9J7DjRsaSeAFQnsUHTmH7BczeFwClqlO1Zt+ffxywJd+4P586HE0AUKbFS785MTbzk79OYCPTjs0DULS6M/LxFNY7xJGPJx6/cOSPCQDK9vFhjt4EtnBkwVgCgPItPmHh3mbtXUK0fAhAENNVGss/9gJWpeprCQAiqOsr8g+V/S8Aounug32286kF6SsJAALJ+2Cd1OmMJQAIZLqqR/Me2GgCgECqlL7cqevOWQkAAqmnuxNYnTx1GYBgqiovIdajCQCC6VSVCQyAcEY7CQACEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQlqQAPrkzCUnpi+edXI6adFx3X8+IZ104nHp5EULP/F93925K+1478P0p50fps1TO9KO3o/vJpiNgLUkf0FfPbYsrbjo9HTmqSf2vtCJ49U33+u9uD6+6fW0YXJrIqVLz/9cWj56Uvdtcbpk+Snz9nc6f57z5/vpzW/3wvbUC28nyKrTVt5XJxqVv7AfWHtZL1zEl19gv3fnM70X2WGS/x6vvGhp75uw5aN7p6ym5Ijlbx42bto2dJ93/krAGiZegym/oF679sk06PLf31VfW9ZdPfh8MasG+RuIiUdeSk9tfkfMhowlxIb1llbEa+Dk5bM8jeSJYNDsu9yd/z1Lk6e/O2/8au+fNz6zd0k3T2cMPgFr2DVjZyUG06ruVDJIAcvhWv2tc9INl5/b6PLgsVh58em9t1ffei+NP7jF/uSAE7CGfbG7yc1gWn72yWkQ5KXBNdec11smjCqvcuSpbM23vyBkA8weWMN+v/6KxOA6+5qHU1SDEK7Z5InslruedYJxwJjAYMhFXCqcqzyR5cNTeRIbX7/FYY8BIWAwxFaNLUs/vP5LAxuuA+XDKJeef4plxQEhYDCE8nLhnd+/sMhThf02sz92yfmnmsaCcy9EGDJ5qfCRH48NZbz2laex3jWZ7oITloDBkMjLhLdef0HvbViWDA8nT2O/umtFbw+QeCwhwhDIU8bdt1zcu+iXg/1w9d59wPH1LybiMIHBgMvRyktl4nVoN337C929sQsTcZjAYIDNxMuS4ZHJ18DlR77ka8byo10omwkMBpR4HZ18K6oHbr+sFzLKJmAwgMTr2OTP362rL0iUTcBgwMw8ske8jk1eTrQnVjYBgwEiXvMrRyzfH5IyCRgMiBwtD0udf/l04iDe4HgQCBgMiHyBsnj1R/7cugyhPAIGA+Cma0wJ/ZSn27t/cLGTiYURMAiu9xyvb9un6bc83eYHZFIOAYPg8r4Xzbjh8nPSiotOT5RBwCCwvHRo36tZP7nxQkuJhRAwCMrSYTvyfpilxDIIGARl6bA9eSlx2J+nVgIBg4DyQyktHbbLBc7tEzAIJi8drr7cAxjblicwU1i7BAyCyd/5m77K4F6J7RIwCCRPXy5YLkf+RuLqsWWJdggYBGLfpTyrfEPRGgGDebJjZ3+f4Gv6KpO9sPYIWMNefeu9xGDq939b01e5/Ldpx4JEozZPvWsDfkBtntqR+iXy9JUn0xz3P+3cvd+vf2bRgoG5w3uewPLdOXa8198pnP0JWMMemtyaVrqX2kAaf3BL6pdI3+HnYG2YfCU9vfmd3jdsr7556Mk0RywHIH9dXHL+KSmq1f90TvfvwIuJ5lSnrbyvTjTqP9b+XegvVA52zyMvpTvufT71Q56+fnXXilS6p154O42vf7H349HKqxM5ZvkWWdFWKvKU+ffffzzRnJFPn3vV2kSj8hd4vp+aB+TFl6eNf3v4/9KP/31z6pcVFy1NKy8ud2rfuGlbuv5ffp0mHn35mPcB8xJcntomHnk5vfbW+2n52Sf3vlYiyB9nnjrtczfHBNai/B1m/gL94uhJadmpi1IbzlhyQrp0ecwTVE9tfju99ub7qQ1b39rZXRp7Pz3+zOt93/f41c9WFDmN5BfqW+569pgmrsPZ+wyu88Ls/61bv8UyYoPsgbUovwDkt43dF8G2rBpbFjZgG554pbenOMjyclqJ8cp7XHdMPN/3eM9E8ndTO9Kt11+QSpe/lsaTgDXFMXoo2KoC7/KQp4wclSZP3OU9xstvmez7tXbHauY0Is0QMChUiUfn21wiy3tj1659sviIrbh4aaIZAgaFumR5WSdVS9jfyRH73p3PpJI5nNUcAYNCXTN2VipFXsIr5XBCPjTSr0sW5kPJJ0YHjYBBgfLyYSnXCuaDFKUFIwf16RfeSSXKh27sgzVDwKBAJd2t5drbnkwl+ue7flPsflj+BoT+EzAoUCkBy/tepV6Ymz+ufPF0ifK1nfSfgEFhSlk+zIF46Imyr7PLS4klTmEOcjRDwKAwpZw+zIc2Sr8tUo5XiVOYJ040Q8CgMKWcPuznLaLmU57CSmMPrBkCBgXJN4QtYflww+TWMDelzVNYaScSTWDNEDAoSCl7J4+3eH/Oo5Fv7FySKHfQj07AoCCl3IZo46ZgAStwudMU1n8CBgUp4ckAUfa+9pVvMcXwETAoRN74L2EJMWIM8j6YB0kOHwGDQpRy8WvUELT1cNPZOInYfwIGhSjl7hv54ZER5adkM1wEDArh7g0wNwIGBcjHrksJ2Ktv2ksiBgGDApi+jt2yUxelkvhGoP8EDApQyrO/MocPiELAoAB/u/zUVIqoD2Ms7REmjvX3n4BBAUp68T1jyQkpmjw1un3T8BEwaFlpL74R9+NMX8NJwKBlpb34Xnp++7ezmqtSrqGb4QBHMwQMWlbaxJNvQhttH6y06JrAmiFg0LISl+xWfX1ZiiLHq7Q7vwtYMwQMWlbiYzdKW5I7lFVj5cX2d7+PeTuuaAQMWlbiBJanmgh7YfkAzNVjn0+lMYE1Q8CgRcvPLvfE35przkulK/Vj9HyyZggYtOiMU8u95qr0KSxPriVOXxEfCBqVgEGLSr/mquQp7O4fXJxKZPpqjoBBi0oPWJ7AVn/rnFSaW6+/oMjDL9nTL7yTaIaAQYtOPnFhKt0PV3+pqKXEGy4/t/dWKhNYcwQMWlTaXThmc/ctFxdxl/q855Wnr1LleDmB2BwBg5bk+x9GuQFt/jgfWHtZqxHL8brzxgtTyRzgaJaAQUuiPXcr7znliLWxb5eXDEuPV/b4pm2J5ggYtCTic7dyxB65c6yxgx158rvz+xcWvWw4Iy8dmsCatSABrYj42JIZ+WDH8rMXp/H1W/p25/V8cCRPXaWeNjzQU04fNk7AoCWfWRT7y+/qsWW9t3seeSlNPPryvIUshytffxbtsS7jD25JNEvAoCWRJ7B9zRxr3zC5NT00+cpRLaPlpcIcwxUXnR7yeWT539npw+YJGLQkwjVgczEzke3Y+WHvBf3pzW+nzVM7ej/f8d6H+71vXhY8o/u2fPSkXrCix3x8/YuJ5gkYtCT6EuJs8jS18uLTe2/DwOGN9jiFCC2JcjiBQxt/0PTVFgGDFkS6iJnZ5elrQ3ffj3YIGLQg4jVgHOyWu55NtEfAoAXR7sLBwfKpS3tf7RIwgDnKJytd99U+AYMWlPwkZg7vnkdfct1XAQQMWmAJMa4cLicPyyBgAEcoLx1ee9uTiTIIGLTANWAx5TtuWDosh4ABHIF80+L8RjkEDFqw7NRFiTjse5VJwAAOIccr73sdeENi2idg0IJBvZHvIPrej5+x71UoAYMWuA9iDLf87Nm0eerdRJkEDOATrFu/JW14wo16SyZg0ALH6MuW4+XQRvkEDGAf4hWHgAF8RLxiETCAJF4ROcsLDbP/VZ477n3eXTYCEjBgaOWb8+anKm/c9HoiHgEDhlK+ODlfpOw6r7gEDBg6OVrusBGfgAFDZcPkK+mOiefd23AACBgwNBzWGCwCBgy8vFSYD2s89cLbicEhYMBA27hpW7rlX39jyXAACRg07MwlrgNrQj4iP77+RUuGA0zAoGEmgf7LS4V5ydApw8EmYNCwHX8WsH7KU9e6B7ckBp+AAQPB1DV8BAwIzV7X8BIwIKx8wvCOif81dQ0pAQPCcV0XmYABYeTlwolHX3ZIgx4BA0LIe1z5gZMuQ2CGgAFFc7qQ2QgYNMwL8ZHJ4cqnC+1zMRsBA4oiXBwpAQOKIFzMlYABrRIujpaAQQvyPtiZpw73XemFi2MlYECjNkxuTQ9NviJcHDMBA/pu5gLke/7zJddxMW8EDFrw2pvvD8US4uapd7vT1ta04YlXhIt5J2DAvLO/RRMEDFqw9a2d6ZJ0ShoklglpmoABx8S0RVsEDFoQfULJe1uPb9pm2qJVAgYtyMtt0eSPecPkK71wmbYogYBBC/60c3eKIEcrT1t5iXDz7981bVEUAYMWvLtzVypZnrDypOX4OyUTMGhBiVEQLaIRMGjBa2+9n9o2szwoWkQlYNCCHX9uJxY5WjlYv87T1jOvixahCRhhlTDFHK18N/qm7kj/6pvvpY2bXnd6kIEjYEPu6RfeSVHlU3GR5XsErrnmvDTf9l0azOHKAYNBJGBDLk8B+QXvpEXHpUjyJBF9+eueR15Kq8aWzcsUloM1cwjDcXeGhYDRu8bn1usvSJHk6SW6/I3Dtbc9mR64/bI5R2xmWXDz1A57WQyt6rSV99WJoXfr6gvSDd86N0Wwbv2WNP7gi2lQ5Hj95MavpkvOn/3mvjlYT29+p3f44unNb1sWhCRg7OPS8z/XW9JaPnpy70W1lGXFPKnkpc6ZJbJBPYiQP/8rLlqali1Z1Pv51jd3mrDgEAQMgJA6CQACEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAEISMABCEjAAQhIwAELKAZtKABDLdhMYAAFVU51UV1MJACKpp7d3qmr6DwkAAqk63Qmsnq6eSwAQSV3/oVNbQgQgmunpyc6uPbsnEwAE8pfd6bnO9snV25Oj9ABEUaWp3K69x+jr+uEEAAFUKU3mH3sBq6c7kwkAAqjqqjd09QKW98HqOm1PAFC493ftPbvRC1heS6yq+n8SABSsqtK9H53d+OvNfKvp6XUJAAo2s3zY++d9f2PJivv+2K3b4gQApanS1BuPXXf2zE/3u5lvp6rHEwAUqJpOt+/78/0C9pdd0+sc5gCgON3pK43smdz3l/YLWO/CMFMYAIWp6vrn2/5r9dS+v3bQ88DyFNYrHQCUoNukbRu/u/bAXz4oYL0j9QesMwJAW2ZrUjXbHzjtH+5/ItX1WAKA1lS/fGPjd676pN/pzPpHqt2rHegAoC11d1Gw6uy+ebbfnzVgebOsqi0lAtCOTp1uPvDgxr5GDvWHd778i6c+fc6Vn+2OY5cmAGhKVY2/sfG6Hx3qXTrpMD74cHptnarnEgA047dvPPadmw73TocNWO/asM7uqxytB6Dvuq2pOnuuPLJ3PUJL/3FitK5Hnujuqo0mAJhvOV7Vnq8fat9r/3efAxEDoC/mGK+9f2SORAyAeXUU8coOuwd2oN7x+u7/kYMdAMyD3x5NvLI5T2D7Om3Fz9elqlqTAGCuqmr8gw92r515wvKc/3g6RktX3Hf9dEo/9SBMAI5E7w4bVbr9jceuW5eOwTEHLOvti013uh9IdUUCgNnU1WQ1snv10SwZHmheAjYjT2N1J93mgAcA+8kHNabT7dsev+7eNE/mNWAzlq78+dq6qr4rZADDLS8XdlI9np81ebR7XbPpS8CyvKyY9oyMmcgAhk8/wzWjbwHb15JvTFzZGelcWafuVAbAQOodzkjdPa7p3ePb/nv1ZOqzRgI2Y/HYxOKFI2msF7Oq+prJDCC8qVTVD9e7pyd37UmT/Zq2PkmjATtQDtqnFqSvpE5nbLquzuqWe7Rb8MXdT8ZolRzLByjEVO9/62qqTnV+VuRv63rPVNPBOtD/A6oeNVega6lDAAAAAElFTkSuQmCC"}}]); \ No newline at end of file diff --git a/assets/js/4b79a3c9.c3ac845d.js b/assets/js/4b79a3c9.8e3e62d0.js similarity index 98% rename from assets/js/4b79a3c9.c3ac845d.js rename to assets/js/4b79a3c9.8e3e62d0.js index 314e430b1..ffb3b1076 100644 --- a/assets/js/4b79a3c9.c3ac845d.js +++ b/assets/js/4b79a3c9.8e3e62d0.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5838],{261:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>d});var r=t(85893),a=t(3905),i=t(74866),s=t(85162);const o={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",slug:"route-image-async-with-event",tags:["async","event"]},l=void 0,c={permalink:"/route-image-async-with-event",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",description:"\uc774\uc804 \uae00",date:"2023-08-13T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 13\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"event",permalink:"/tags/event"}],readingTime:11.2,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",slug:"route-image-async-with-event",tags:["async","event"]},unlisted:!1,prevItem:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/cloudwatch"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",permalink:"/route-image-implementation"}},u={authorsImageUrls:[]},d=[{value:"\uc774\uc804 \uae00",id:"\uc774\uc804-\uae00",level:2},{value:"\uac1c\uc694",id:"\uac1c\uc694",level:2},{value:"\uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120",id:"\uc8fc\uae30\ub2a5\uc758-\uc751\ub2f5\uc18d\ub3c4-\uac1c\uc120",level:3},{value:"\ud655\uc7a5\uc131 \ub300\ube44",id:"\ud655\uc7a5\uc131-\ub300\ube44",level:3},{value:"\ube44\ub3d9\uae30 \ucc98\ub9ac",id:"\ube44\ub3d9\uae30-\ucc98\ub9ac",level:2},{value:"\ube44\ub3d9\uae30 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc124\uc815",level:3},{value:"@Async \uc801\uc6a9",id:"async-\uc801\uc6a9",level:3},{value:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810",id:"\ube44\ub3d9\uae30-\ucc98\ub9ac\uc2dc-\ubb38\uc81c\uc810",level:3},{value:"\uc774\ubca4\ud2b8 \uc0ac\uc6a9",id:"\uc774\ubca4\ud2b8-\uc0ac\uc6a9",level:2},{value:"\uc774\ubca4\ud2b8 \ubc1c\ud589",id:"\uc774\ubca4\ud2b8-\ubc1c\ud589",level:3},{value:"\uc774\ubca4\ud2b8 \uad6c\ub3c5",id:"\uc774\ubca4\ud2b8-\uad6c\ub3c5",level:3},{value:"\ud14c\uc2a4\ud2b8",id:"\ud14c\uc2a4\ud2b8",level:3},{value:"\uacb0\uacfc",id:"\uacb0\uacfc",level:2},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",mermaid:"mermaid",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"\uc774\uc804-\uae00",children:"\uc774\uc804 \uae00"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"./route-image-intro",children:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"./route-image-implementation",children:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604"})]}),"\n",(0,r.jsx)(n.h2,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac \uc5ec\ud589\uc744 \ub9c8\uce58\ub294 \uacbd\uc6b0, \uac10\uc0c1\uc744 \uc0dd\uc131\ud558\ub294 \uacbd\uc6b0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \uc704\uce58 \uc815\ubcf4\uc758 \uac1c\uc218\uc5d0 \uc815\ube44\ub840\ud558\uc5ec \uc0dd\uc131 \uc2dc\uac04\uc774 \uc99d\uac00\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ube44\ub3d9\uae30\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uc5ec \uc0ac\uc6a9\uc790\uc758 \uacbd\ud5d8\uc744 \uac1c\uc120\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc8fc\uae30\ub2a5\uc758-\uc751\ub2f5\uc18d\ub3c4-\uac1c\uc120",children:"\uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120"}),"\n",(0,r.jsxs)(n.p,{children:["\uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc774 \uc8fc\uae30\ub2a5\uc774\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ubd80\uae30\ub2a5\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ud604\uc7ac \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc758 \uc751\ub2f5 \uc18d\ub3c4\uac00 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uc5ec\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc18c\uc694 \uc2dc\uac04\uc774 1\ucd08 \uc774\uc0c1 \uac78\ub9ac\ub294 \uacbd\uc6b0\uac00 \uc874\uc7ac\ud558\uae30\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uace0 \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131 \uae30\ub2a5\uc758 \uc751\ub2f5 \uc2dc\uac04\uc744 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc911\uc694\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ud655\uc7a5\uc131-\ub300\ube44",children:"\ud655\uc7a5\uc131 \ub300\ube44"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac 10\ubd84 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc11c\ubc84\uc5d0 \uc800\uc7a5\ud558\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc870\uae08 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uadf8\ub9ac\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 \uc5ec\ud589\uc5d0 \ub9ce\uc740 \uc704\uce58 \uc815\ubcf4\uac00 \uc800\uc7a5\ub420 \uc218\ubc16\uc5d0 \uc5c6\uace0 \ub530\ub77c\uc11c \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uac78\ub9ac\ub294 \uc2dc\uac04\uc774 \ub354 \uae38\uc5b4\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ucd94\ud6c4\uc5d0 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0\ub97c \ub300\ube44\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \ud569\ub2f9\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ube44\ub3d9\uae30-\ucc98\ub9ac",children:"\ube44\ub3d9\uae30 \ucc98\ub9ac"}),"\n",(0,r.jsx)(n.p,{children:"@Async\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uba54\uc11c\ub4dc\ub97c \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ub9cc\ub4e4 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\uc124\uc815",children:"\ube44\ub3d9\uae30 \uc124\uc815"}),"\n",(0,r.jsxs)(n.p,{children:["\uc0ac\uc6a9\ud558\uae30 \uc804\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c EnableAsync \uc124\uc815\uc744 \ud574\uc57c\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc124\uc815\uc744 \uc801\uc6a9\ud558\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc\uc5d0 @Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uae30\ub9cc \ud558\uba74 \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="AsyncConfig"',children:"@EnableAsync\n@Configuration\npublic class AsyncConfig {\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud560 \ub54c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ub808\ub4dc \ud480 \uc124\uc815\uc744 \ub530\ub85c \ud574\uc918\uc57c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ThreadPoolTaskExecutor\ub97c \ub530\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \uae30\ubcf8\uc801\uc73c\ub85c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uac00 \uc0dd\uc131\uc744 \ub3c4\uc640\uc900\ub2e4."}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.\n7.7. Task Execution and Scheduling, Spring Boot Docs"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"async-\uc801\uc6a9",children:"@Async \uc801\uc6a9"}),"\n",(0,r.jsx)(n.p,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\uc5d0 Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageGenerator"',children:"@Async\npublic void generate(\n List latitudes,\n List longitudes,\n List pointedLatitudes,\n List pointedLongitudes,\n Long tripId\n) {\n // \uc774\ubbf8\uc9c0 \uc0dd\uc131\n RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);\n Coordinates coordinates = Coordinates.of(latitudes, longitudes);\n Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);\n drawImage(coordinates, routeImageDrawer, pointedCoordinates);\n\n // \uc774\ubbf8\uc9c0 \uc800\uc7a5\n String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());\n\n // \uc790\uc6d0 \ud560\ub2f9 \ud574\uc81c\n routeImageDrawer.dispose();\n\n // \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac12 \ubcc0\uacbd\n Trip trip = tripRepository.findById(tripId)\n .orElseThrow();\n trip.changeRouteImageUrl(imageUrl);\n tripRepository.save(trip);\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\ucc98\ub9ac\uc2dc-\ubb38\uc81c\uc810",children:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uace0 \uc800\uc7a5 \ud6c4, \uc800\uc7a5 \uacbd\ub85c\ub97c DB\uc5d0 \ubc18\uc601\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ud615\ud0dc\uac00 \ub418\uba70 \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n trip[trip: \uc5ec\ud589 \uad00\ub828 \ud328\ud0a4\uc9c0] --\x3e draw[draw: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294 \ud328\ud0a4\uc9c0]\n draw --\x3e trip"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uacfc \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph draw\n\t\tdirection LR\n\t\tRG[RouteImageGenerator] -- DB \ubc18\uc601 \uc694\uccad --\x3e ILR[ImageLinkTripRepository]\n\tend\n subgraph trip\n\t\tdirection LR\n\t\tTS[TripService] -- \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e RG\n\t\tILRI[ImageLinkTripRepositoryImpl] -- \uad6c\ud604 --\x3e ILR\n\tend\n\n\ttrip --\x3e draw"}),"\n",(0,r.jsxs)(n.p,{children:["\ud328\ud0a4\uc9c0 \uac04 \uc758\uc874\uc131\uc740 \ud574\uacb0\ub418\uc5c8\uc9c0\ub9cc, \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5\uc744 \uc704\ud574 tripId\ub97c \ubc1b\uc544\uc57c\ud558\ub294 \ub4f1\uc758 \ub17c\ub9ac\uc801\uc778 \uc758\uc874\uc131\uc740 \uc544\uc9c1 \ud574\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uc774\ubca4\ud2b8-\uc0ac\uc6a9",children:"\uc774\ubca4\ud2b8 \uc0ac\uc6a9"}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uba74 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ube44\uad00\uc2ec\uc0ac(ex. \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131)\uc744 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\uc774\ubca4\ud2b8-\ubc1c\ud589",children:"\uc774\ubca4\ud2b8 \ubc1c\ud589"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 ApplicationEventPublisher \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c ApplicationContext\uac00 \uad6c\ud604\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="TripService & TripUpdateEvent"',children:"public void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {\n ...\n\n // \uc774\ubca4\ud2b8 \ubc1c\ud589\n applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));\n}\n\npublic record TripUpdateEvent(Long tripId) {\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \ub54c \ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc774 \uc911\uc694\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\ub294 \ub3c4\uba54\uc778\uc758 \ud589\uc704\ub97c \ub2f4\uace0 \uc788\ub294 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589(ex. RouteImageGenerateEvent)\ud55c\ub2e4\uba74 \ub17c\ub9ac\uc801\uc778 \uc758\uc874 \uad00\uacc4\uac00 \ub0a8\uc544\uc788\uae30\uc5d0 \uc774\ubca4\ud2b8\ub97c \uc801\uc808\ud788 \uc0ac\uc6a9\ud588\ub2e4\uace0 \ubcf4\uae30 \uc5b4\ub835\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc740 \uc8fc\uae30\ub2a5\uc774 \uc5b4\ub5a4 \ud589\uc704(ex. TripUpdateEvent)\ub97c \ud588\ub294\uc9c0\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 \uc774\ubca4\ud2b8\uba85\uc73c\ub85c \ubc1c\ud589\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc774\ubca4\ud2b8-\uad6c\ub3c5",children:"\uc774\ubca4\ud2b8 \uad6c\ub3c5"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc2e4\ud589\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\uae30 \uc704\ud558\uc5ec ",(0,r.jsx)(n.code,{children:"@Async"})," \uc560\ub108\ud14c\uc774\uc158\uc744 \uc801\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ubca4\ud2b8\uc758 \uad6c\ub3c5\uc740 \uc5ec\ud589\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc\ub420 \ub54c \uc5ec\ud589\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 ",(0,r.jsx)(n.code,{children:"@TransactionalEventListener"}),"\ub97c \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,r.jsxs)(n.admonition,{title:"TransactionPhase \uc124\uc815",type:"note",children:[(0,r.jsx)(n.p,{children:"TransactionPhase\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \uc774\ubca4\ud2b8\ub97c \uc5b4\ub5a4 \ub2e8\uacc4\uc5d0\uc11c \uc218\uc2e0\ud558\uace0 \ucc98\ub9ac\ud560\uc9c0\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),(0,r.jsxs)(n.p,{children:["AFTER_COMMIT(\uae30\ubcf8\uac12): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ucee4\ubc0b \ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","AFTER_ROLLBACK: \ud2b8\ub79c\uc7ad\uc158\uc774 \ub864\ubc31\ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","AFTER_COMPLETION: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub610\ub294 \ub864\ubc31 \ub418\uc5c8\uc744 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","BEFORE_COMMIT: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub418\uae30 \uc804 \uc774\ubca4\ud2b8 \uc2e4\ud589"]})]}),"\n",(0,r.jsx)(n.p,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uae30 \uc704\ud574 @Transactional \uc560\ub108\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="TripUpdateEventHandler"',children:"@Component\npublic class TripUpdateEventHandler {\n\n private final RouteImageGenerator routeImageGenerator;\n private final TripRepository tripRepository;\n\n public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {\n this.routeImageGenerator = routeImageGenerator;\n this.tripRepository = tripRepository;\n }\n\n @Async\n @TransactionalEventListener(phase = AFTER_COMMIT)\n public void handle(TripUpdateEvent tripUpdateEvent) {\n Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());\n\n String imageUrl = routeImageGenerator.generate(\n trip.getLatitudes(),\n trip.getLongitudes(),\n trip.getPointedLatitudes(),\n trip.getPointedLongitudes()\n );\n\n trip.changeRouteImageUrl(imageUrl);\n tripRepository.save(trip);\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c\uc368 \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ubb38\uc81c\uac00 \ub2e4\uc74c\uacfc \uac19\uc774 \ud574\uacb0\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c \uc8fc\uae30\ub2a5\uacfc \ubd80\uae30\ub2a5\uc744 \ubd84\ub9ac\ud568\uc73c\ub85c\uc368 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uc5c8\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n subgraph trip\n TripServcie -- \ubc1c\ud589 --\x3e TripUpdateEvent\n TripRepository\n end\n\n subgraph draw\n TripUpdateEventHandler -- \uad6c\ub3c5 \ud6c4 \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e TripUpdateEvent\n TripUpdateEventHandler -- \uc0dd\uc131\ub41c \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5 --\x3e TripRepository\n end"}),"\n",(0,r.jsx)(n.h3,{id:"\ud14c\uc2a4\ud2b8",children:"\ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsx)(n.p,{children:"\ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \ubc29\ubc95\uc774 \uc788\ub2e4."}),"\n","\n","\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(s.Z,{value:"\ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \uc885\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30 \ud6c4 \uac80\uc99d",label:"\ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \uc885\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30 \ud6c4 \uac80\uc99d",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@SpringBootTest\npublic class TripUpdateEventHandlerIntegrationTest {\n\n ...\n\n @Test\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\n // given\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\n .willReturn(\uc5ec\ud589());\n\n // when\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\n\n // then\n then(routeImageGenerator)\n .should(Mockito.timeout(5000).times(1))\n .generate(any(), any(), any(), any());\n }\n}\n"})})}),(0,r.jsx)(s.Z,{value:"\ud14c\uc2a4\ud2b8 \ud560 \ub54c\ub9cc \ube44\ub3d9\uae30\ub97c \ub3d9\uae30\ub85c \ubcc0\uacbd\ud558\uc5ec \uac80\uc99d",label:"\ud14c\uc2a4\ud2b8 \ud560 \ub54c\ub9cc \ube44\ub3d9\uae30\ub97c \ub3d9\uae30\ub85c \ubcc0\uacbd\ud558\uc5ec \uac80\uc99d",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@ContextConfiguration(classes = TestSyncConfig.class)\n@SpringBootTest\npublic class TripUpdateEventHandlerIntegrationTest {\n\n ...\n\n @Test\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\n // given\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\n .willReturn(\uc5ec\ud589());\n\n // when\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\n\n // then\n then(routeImageGenerator)\n .should(times(1))\n .generate(any(), any(), any(), any());\n }\n}\n"})})})]}),"\n",(0,r.jsxs)(n.p,{children:["\ucc98\uc74c\uc5d0\ub294 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub9cc \ub3d9\uae30\ub85c \uc124\uc815 \ud6c4 \uac80\uc99d\ud558\ub824\uace0 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud1b5\ud569 \ud14c\uc2a4\ud2b8\uc5d0\uc120 ",(0,r.jsx)(n.code,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1 \uc885\ub8cc\ub418\uc5c8\uc744 \ub54c \ube44\ub3d9\uae30\ub85c \uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0"})," \uac80\uc99d\uc774 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc885\uc801\uc73c\ub85c ",(0,r.jsx)(n.code,{children:"Mockito.timeout"})," \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \ud1b5\uacfc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uacb0\uacfc",children:"\uacb0\uacfc"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"./time.png",src:t(89297).Z+"",width:"1682",height:"678"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc704 \uc751\ub2f5 \uc2dc\uac04\uc740 \uc704\uce58 \uc815\ubcf4 1000\uac1c\ub97c \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud55c \uac12\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc751\ub2f5 \uc2dc\uac04\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ud3ec\ud568\ub418\uc9c0 \uc54a\uc544\uc11c \uc131\ub2a5\uc774 \uac1c\uc120\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.task-execution-and-scheduling",children:"7.7. Task Execution and Scheduling, Spring Boot Docs"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.baeldung.com/spring-events",children:"Spring Events, Baeldung"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://techblog.woowahan.com/7835/",children:"\ud68c\uc6d0\uc2dc\uc2a4\ud15c \uc774\ubca4\ud2b8\uae30\ubc18 \uc544\ud0a4\ud14d\ucc98 \uad6c\ucd95\ud558\uae30"})]})]})}function h(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),c=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),p=c(t),h=a,g=p["".concat(l,".").concat(h)]||p[h]||u[h]||i;return t?r.createElement(g,s(s({ref:n},d),{},{components:t})):r.createElement(g,s({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>s});t(67294);var r=t(86010);const a={tabItem:"tabItem_Ymn6"};var i=t(85893);function s(e){let{children:n,hidden:t,className:s}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.Z)(a.tabItem,s),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>T});var r=t(67294),a=t(86010),i=t(12466),s=t(16550),o=t(20469),l=t(91980),c=t(67392),u=t(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:a}}=e;return{value:n,label:t,attributes:r,default:a}}))}(t);return function(e){const n=(0,c.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function g(e){let{queryString:n=!1,groupId:t}=e;const a=(0,s.k6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function m(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=p(e),[s,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[c,d]=g({queryString:t,groupId:a}),[m,b]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,u.Nk)(t);return[a,(0,r.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),v=(()=>{const e=c??m;return h({value:e,tabValues:i})?e:null})();(0,o.Z)((()=>{v&&l(v)}),[v]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!h({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),b(e)}),[d,b,i]),tabValues:i}}var b=t(72389);const v={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=t(85893);function j(e){let{className:n,block:t,selectedValue:r,selectValue:s,tabValues:o}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,i.o5)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),a=o[t].value;a!==r&&(c(n),s(a))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...i,className:(0,a.Z)("tabs__item",v.tabItem,i?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function f(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function y(e){const n=m(e);return(0,x.jsxs)("div",{className:(0,a.Z)("tabs-container",v.tabList),children:[(0,x.jsx)(j,{...e,...n}),(0,x.jsx)(f,{...e,...n})]})}function T(e){const n=(0,b.Z)();return(0,x.jsx)(y,{...e,children:d(e.children)},String(n))}},89297:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/time-8bef9a6cf2dcace85f12ae5624da94f5.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5838],{261:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>d});var r=t(85893),a=t(3905),i=t(74866),s=t(85162);const o={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",slug:"route-image-async-with-event",tags:["async","event"]},l=void 0,c={permalink:"/route-image-async-with-event",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",description:"\uc774\uc804 \uae00",date:"2023-08-13T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 13\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"event",permalink:"/tags/event"}],readingTime:11.2,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",slug:"route-image-async-with-event",tags:["async","event"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",permalink:"/route-image-implementation"},nextItem:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/cloudwatch"}},u={authorsImageUrls:[]},d=[{value:"\uc774\uc804 \uae00",id:"\uc774\uc804-\uae00",level:2},{value:"\uac1c\uc694",id:"\uac1c\uc694",level:2},{value:"\uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120",id:"\uc8fc\uae30\ub2a5\uc758-\uc751\ub2f5\uc18d\ub3c4-\uac1c\uc120",level:3},{value:"\ud655\uc7a5\uc131 \ub300\ube44",id:"\ud655\uc7a5\uc131-\ub300\ube44",level:3},{value:"\ube44\ub3d9\uae30 \ucc98\ub9ac",id:"\ube44\ub3d9\uae30-\ucc98\ub9ac",level:2},{value:"\ube44\ub3d9\uae30 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc124\uc815",level:3},{value:"@Async \uc801\uc6a9",id:"async-\uc801\uc6a9",level:3},{value:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810",id:"\ube44\ub3d9\uae30-\ucc98\ub9ac\uc2dc-\ubb38\uc81c\uc810",level:3},{value:"\uc774\ubca4\ud2b8 \uc0ac\uc6a9",id:"\uc774\ubca4\ud2b8-\uc0ac\uc6a9",level:2},{value:"\uc774\ubca4\ud2b8 \ubc1c\ud589",id:"\uc774\ubca4\ud2b8-\ubc1c\ud589",level:3},{value:"\uc774\ubca4\ud2b8 \uad6c\ub3c5",id:"\uc774\ubca4\ud2b8-\uad6c\ub3c5",level:3},{value:"\ud14c\uc2a4\ud2b8",id:"\ud14c\uc2a4\ud2b8",level:3},{value:"\uacb0\uacfc",id:"\uacb0\uacfc",level:2},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",mermaid:"mermaid",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"\uc774\uc804-\uae00",children:"\uc774\uc804 \uae00"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"./route-image-intro",children:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"./route-image-implementation",children:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604"})]}),"\n",(0,r.jsx)(n.h2,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac \uc5ec\ud589\uc744 \ub9c8\uce58\ub294 \uacbd\uc6b0, \uac10\uc0c1\uc744 \uc0dd\uc131\ud558\ub294 \uacbd\uc6b0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \uc704\uce58 \uc815\ubcf4\uc758 \uac1c\uc218\uc5d0 \uc815\ube44\ub840\ud558\uc5ec \uc0dd\uc131 \uc2dc\uac04\uc774 \uc99d\uac00\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ube44\ub3d9\uae30\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uc5ec \uc0ac\uc6a9\uc790\uc758 \uacbd\ud5d8\uc744 \uac1c\uc120\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc8fc\uae30\ub2a5\uc758-\uc751\ub2f5\uc18d\ub3c4-\uac1c\uc120",children:"\uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120"}),"\n",(0,r.jsxs)(n.p,{children:["\uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc774 \uc8fc\uae30\ub2a5\uc774\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ubd80\uae30\ub2a5\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ud604\uc7ac \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc758 \uc751\ub2f5 \uc18d\ub3c4\uac00 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uc5ec\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc18c\uc694 \uc2dc\uac04\uc774 1\ucd08 \uc774\uc0c1 \uac78\ub9ac\ub294 \uacbd\uc6b0\uac00 \uc874\uc7ac\ud558\uae30\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uace0 \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131 \uae30\ub2a5\uc758 \uc751\ub2f5 \uc2dc\uac04\uc744 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc911\uc694\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ud655\uc7a5\uc131-\ub300\ube44",children:"\ud655\uc7a5\uc131 \ub300\ube44"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac 10\ubd84 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc11c\ubc84\uc5d0 \uc800\uc7a5\ud558\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc870\uae08 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uadf8\ub9ac\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 \uc5ec\ud589\uc5d0 \ub9ce\uc740 \uc704\uce58 \uc815\ubcf4\uac00 \uc800\uc7a5\ub420 \uc218\ubc16\uc5d0 \uc5c6\uace0 \ub530\ub77c\uc11c \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uac78\ub9ac\ub294 \uc2dc\uac04\uc774 \ub354 \uae38\uc5b4\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ucd94\ud6c4\uc5d0 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0\ub97c \ub300\ube44\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \ud569\ub2f9\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ube44\ub3d9\uae30-\ucc98\ub9ac",children:"\ube44\ub3d9\uae30 \ucc98\ub9ac"}),"\n",(0,r.jsx)(n.p,{children:"@Async\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uba54\uc11c\ub4dc\ub97c \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ub9cc\ub4e4 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\uc124\uc815",children:"\ube44\ub3d9\uae30 \uc124\uc815"}),"\n",(0,r.jsxs)(n.p,{children:["\uc0ac\uc6a9\ud558\uae30 \uc804\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c EnableAsync \uc124\uc815\uc744 \ud574\uc57c\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc124\uc815\uc744 \uc801\uc6a9\ud558\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc\uc5d0 @Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uae30\ub9cc \ud558\uba74 \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="AsyncConfig"',children:"@EnableAsync\n@Configuration\npublic class AsyncConfig {\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud560 \ub54c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ub808\ub4dc \ud480 \uc124\uc815\uc744 \ub530\ub85c \ud574\uc918\uc57c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ThreadPoolTaskExecutor\ub97c \ub530\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \uae30\ubcf8\uc801\uc73c\ub85c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uac00 \uc0dd\uc131\uc744 \ub3c4\uc640\uc900\ub2e4."}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.\n7.7. Task Execution and Scheduling, Spring Boot Docs"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"async-\uc801\uc6a9",children:"@Async \uc801\uc6a9"}),"\n",(0,r.jsx)(n.p,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\uc5d0 Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageGenerator"',children:"@Async\npublic void generate(\n List latitudes,\n List longitudes,\n List pointedLatitudes,\n List pointedLongitudes,\n Long tripId\n) {\n // \uc774\ubbf8\uc9c0 \uc0dd\uc131\n RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);\n Coordinates coordinates = Coordinates.of(latitudes, longitudes);\n Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);\n drawImage(coordinates, routeImageDrawer, pointedCoordinates);\n\n // \uc774\ubbf8\uc9c0 \uc800\uc7a5\n String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());\n\n // \uc790\uc6d0 \ud560\ub2f9 \ud574\uc81c\n routeImageDrawer.dispose();\n\n // \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac12 \ubcc0\uacbd\n Trip trip = tripRepository.findById(tripId)\n .orElseThrow();\n trip.changeRouteImageUrl(imageUrl);\n tripRepository.save(trip);\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\ucc98\ub9ac\uc2dc-\ubb38\uc81c\uc810",children:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uace0 \uc800\uc7a5 \ud6c4, \uc800\uc7a5 \uacbd\ub85c\ub97c DB\uc5d0 \ubc18\uc601\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ud615\ud0dc\uac00 \ub418\uba70 \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n trip[trip: \uc5ec\ud589 \uad00\ub828 \ud328\ud0a4\uc9c0] --\x3e draw[draw: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294 \ud328\ud0a4\uc9c0]\n draw --\x3e trip"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uacfc \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph draw\n\t\tdirection LR\n\t\tRG[RouteImageGenerator] -- DB \ubc18\uc601 \uc694\uccad --\x3e ILR[ImageLinkTripRepository]\n\tend\n subgraph trip\n\t\tdirection LR\n\t\tTS[TripService] -- \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e RG\n\t\tILRI[ImageLinkTripRepositoryImpl] -- \uad6c\ud604 --\x3e ILR\n\tend\n\n\ttrip --\x3e draw"}),"\n",(0,r.jsxs)(n.p,{children:["\ud328\ud0a4\uc9c0 \uac04 \uc758\uc874\uc131\uc740 \ud574\uacb0\ub418\uc5c8\uc9c0\ub9cc, \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5\uc744 \uc704\ud574 tripId\ub97c \ubc1b\uc544\uc57c\ud558\ub294 \ub4f1\uc758 \ub17c\ub9ac\uc801\uc778 \uc758\uc874\uc131\uc740 \uc544\uc9c1 \ud574\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uc774\ubca4\ud2b8-\uc0ac\uc6a9",children:"\uc774\ubca4\ud2b8 \uc0ac\uc6a9"}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uba74 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ube44\uad00\uc2ec\uc0ac(ex. \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131)\uc744 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\uc774\ubca4\ud2b8-\ubc1c\ud589",children:"\uc774\ubca4\ud2b8 \ubc1c\ud589"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 ApplicationEventPublisher \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c ApplicationContext\uac00 \uad6c\ud604\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="TripService & TripUpdateEvent"',children:"public void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {\n ...\n\n // \uc774\ubca4\ud2b8 \ubc1c\ud589\n applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));\n}\n\npublic record TripUpdateEvent(Long tripId) {\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \ub54c \ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc774 \uc911\uc694\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\ub294 \ub3c4\uba54\uc778\uc758 \ud589\uc704\ub97c \ub2f4\uace0 \uc788\ub294 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589(ex. RouteImageGenerateEvent)\ud55c\ub2e4\uba74 \ub17c\ub9ac\uc801\uc778 \uc758\uc874 \uad00\uacc4\uac00 \ub0a8\uc544\uc788\uae30\uc5d0 \uc774\ubca4\ud2b8\ub97c \uc801\uc808\ud788 \uc0ac\uc6a9\ud588\ub2e4\uace0 \ubcf4\uae30 \uc5b4\ub835\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc740 \uc8fc\uae30\ub2a5\uc774 \uc5b4\ub5a4 \ud589\uc704(ex. TripUpdateEvent)\ub97c \ud588\ub294\uc9c0\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 \uc774\ubca4\ud2b8\uba85\uc73c\ub85c \ubc1c\ud589\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc774\ubca4\ud2b8-\uad6c\ub3c5",children:"\uc774\ubca4\ud2b8 \uad6c\ub3c5"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc2e4\ud589\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\uae30 \uc704\ud558\uc5ec ",(0,r.jsx)(n.code,{children:"@Async"})," \uc560\ub108\ud14c\uc774\uc158\uc744 \uc801\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ubca4\ud2b8\uc758 \uad6c\ub3c5\uc740 \uc5ec\ud589\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc\ub420 \ub54c \uc5ec\ud589\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 ",(0,r.jsx)(n.code,{children:"@TransactionalEventListener"}),"\ub97c \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,r.jsxs)(n.admonition,{title:"TransactionPhase \uc124\uc815",type:"note",children:[(0,r.jsx)(n.p,{children:"TransactionPhase\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \uc774\ubca4\ud2b8\ub97c \uc5b4\ub5a4 \ub2e8\uacc4\uc5d0\uc11c \uc218\uc2e0\ud558\uace0 \ucc98\ub9ac\ud560\uc9c0\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),(0,r.jsxs)(n.p,{children:["AFTER_COMMIT(\uae30\ubcf8\uac12): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ucee4\ubc0b \ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","AFTER_ROLLBACK: \ud2b8\ub79c\uc7ad\uc158\uc774 \ub864\ubc31\ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","AFTER_COMPLETION: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub610\ub294 \ub864\ubc31 \ub418\uc5c8\uc744 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","BEFORE_COMMIT: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub418\uae30 \uc804 \uc774\ubca4\ud2b8 \uc2e4\ud589"]})]}),"\n",(0,r.jsx)(n.p,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uae30 \uc704\ud574 @Transactional \uc560\ub108\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="TripUpdateEventHandler"',children:"@Component\npublic class TripUpdateEventHandler {\n\n private final RouteImageGenerator routeImageGenerator;\n private final TripRepository tripRepository;\n\n public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {\n this.routeImageGenerator = routeImageGenerator;\n this.tripRepository = tripRepository;\n }\n\n @Async\n @TransactionalEventListener(phase = AFTER_COMMIT)\n public void handle(TripUpdateEvent tripUpdateEvent) {\n Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());\n\n String imageUrl = routeImageGenerator.generate(\n trip.getLatitudes(),\n trip.getLongitudes(),\n trip.getPointedLatitudes(),\n trip.getPointedLongitudes()\n );\n\n trip.changeRouteImageUrl(imageUrl);\n tripRepository.save(trip);\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c\uc368 \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ubb38\uc81c\uac00 \ub2e4\uc74c\uacfc \uac19\uc774 \ud574\uacb0\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c \uc8fc\uae30\ub2a5\uacfc \ubd80\uae30\ub2a5\uc744 \ubd84\ub9ac\ud568\uc73c\ub85c\uc368 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uc5c8\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n subgraph trip\n TripServcie -- \ubc1c\ud589 --\x3e TripUpdateEvent\n TripRepository\n end\n\n subgraph draw\n TripUpdateEventHandler -- \uad6c\ub3c5 \ud6c4 \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e TripUpdateEvent\n TripUpdateEventHandler -- \uc0dd\uc131\ub41c \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5 --\x3e TripRepository\n end"}),"\n",(0,r.jsx)(n.h3,{id:"\ud14c\uc2a4\ud2b8",children:"\ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsx)(n.p,{children:"\ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \ubc29\ubc95\uc774 \uc788\ub2e4."}),"\n","\n","\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(s.Z,{value:"\ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \uc885\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30 \ud6c4 \uac80\uc99d",label:"\ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \uc885\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30 \ud6c4 \uac80\uc99d",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@SpringBootTest\npublic class TripUpdateEventHandlerIntegrationTest {\n\n ...\n\n @Test\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\n // given\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\n .willReturn(\uc5ec\ud589());\n\n // when\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\n\n // then\n then(routeImageGenerator)\n .should(Mockito.timeout(5000).times(1))\n .generate(any(), any(), any(), any());\n }\n}\n"})})}),(0,r.jsx)(s.Z,{value:"\ud14c\uc2a4\ud2b8 \ud560 \ub54c\ub9cc \ube44\ub3d9\uae30\ub97c \ub3d9\uae30\ub85c \ubcc0\uacbd\ud558\uc5ec \uac80\uc99d",label:"\ud14c\uc2a4\ud2b8 \ud560 \ub54c\ub9cc \ube44\ub3d9\uae30\ub97c \ub3d9\uae30\ub85c \ubcc0\uacbd\ud558\uc5ec \uac80\uc99d",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@ContextConfiguration(classes = TestSyncConfig.class)\n@SpringBootTest\npublic class TripUpdateEventHandlerIntegrationTest {\n\n ...\n\n @Test\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\n // given\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\n .willReturn(\uc5ec\ud589());\n\n // when\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\n\n // then\n then(routeImageGenerator)\n .should(times(1))\n .generate(any(), any(), any(), any());\n }\n}\n"})})})]}),"\n",(0,r.jsxs)(n.p,{children:["\ucc98\uc74c\uc5d0\ub294 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub9cc \ub3d9\uae30\ub85c \uc124\uc815 \ud6c4 \uac80\uc99d\ud558\ub824\uace0 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud1b5\ud569 \ud14c\uc2a4\ud2b8\uc5d0\uc120 ",(0,r.jsx)(n.code,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1 \uc885\ub8cc\ub418\uc5c8\uc744 \ub54c \ube44\ub3d9\uae30\ub85c \uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0"})," \uac80\uc99d\uc774 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc885\uc801\uc73c\ub85c ",(0,r.jsx)(n.code,{children:"Mockito.timeout"})," \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \ud1b5\uacfc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uacb0\uacfc",children:"\uacb0\uacfc"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"./time.png",src:t(89297).Z+"",width:"1682",height:"678"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc704 \uc751\ub2f5 \uc2dc\uac04\uc740 \uc704\uce58 \uc815\ubcf4 1000\uac1c\ub97c \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud55c \uac12\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc751\ub2f5 \uc2dc\uac04\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ud3ec\ud568\ub418\uc9c0 \uc54a\uc544\uc11c \uc131\ub2a5\uc774 \uac1c\uc120\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.task-execution-and-scheduling",children:"7.7. Task Execution and Scheduling, Spring Boot Docs"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.baeldung.com/spring-events",children:"Spring Events, Baeldung"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://techblog.woowahan.com/7835/",children:"\ud68c\uc6d0\uc2dc\uc2a4\ud15c \uc774\ubca4\ud2b8\uae30\ubc18 \uc544\ud0a4\ud14d\ucc98 \uad6c\ucd95\ud558\uae30"})]})]})}function h(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),c=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),p=c(t),h=a,g=p["".concat(l,".").concat(h)]||p[h]||u[h]||i;return t?r.createElement(g,s(s({ref:n},d),{},{components:t})):r.createElement(g,s({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>s});t(67294);var r=t(86010);const a={tabItem:"tabItem_Ymn6"};var i=t(85893);function s(e){let{children:n,hidden:t,className:s}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.Z)(a.tabItem,s),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>T});var r=t(67294),a=t(86010),i=t(12466),s=t(16550),o=t(20469),l=t(91980),c=t(67392),u=t(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:a}}=e;return{value:n,label:t,attributes:r,default:a}}))}(t);return function(e){const n=(0,c.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function g(e){let{queryString:n=!1,groupId:t}=e;const a=(0,s.k6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function m(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=p(e),[s,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[c,d]=g({queryString:t,groupId:a}),[m,b]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,u.Nk)(t);return[a,(0,r.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),v=(()=>{const e=c??m;return h({value:e,tabValues:i})?e:null})();(0,o.Z)((()=>{v&&l(v)}),[v]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!h({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),b(e)}),[d,b,i]),tabValues:i}}var b=t(72389);const v={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=t(85893);function j(e){let{className:n,block:t,selectedValue:r,selectValue:s,tabValues:o}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,i.o5)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),a=o[t].value;a!==r&&(c(n),s(a))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...i,className:(0,a.Z)("tabs__item",v.tabItem,i?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function f(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function y(e){const n=m(e);return(0,x.jsxs)("div",{className:(0,a.Z)("tabs-container",v.tabList),children:[(0,x.jsx)(j,{...e,...n}),(0,x.jsx)(f,{...e,...n})]})}function T(e){const n=(0,b.Z)();return(0,x.jsx)(y,{...e,children:d(e.children)},String(n))}},89297:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/time-8bef9a6cf2dcace85f12ae5624da94f5.png"}}]); \ No newline at end of file diff --git a/assets/js/4d43abad.3e067cc0.js b/assets/js/4d43abad.97a6cc5b.js similarity index 97% rename from assets/js/4d43abad.3e067cc0.js rename to assets/js/4d43abad.97a6cc5b.js index 1f82893a2..965242a73 100644 --- a/assets/js/4d43abad.3e067cc0.js +++ b/assets/js/4d43abad.97a6cc5b.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3365],{79766:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>l,metadata:()=>s,toc:()=>o});var r=n(85893),i=n(3905);const l={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",slug:"route-image-intro",tags:["image","awt"]},a=void 0,s={permalink:"/route-image-intro",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",source:"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",description:"./route.png",date:"2023-07-27T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 27\uc77c",tags:[{label:"image",permalink:"/tags/image"},{label:"awt",permalink:"/tags/awt"}],readingTime:5.865,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",slug:"route-image-intro",tags:["image","awt"]},unlisted:!1,prevItem:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",permalink:"/mock-static-method"},nextItem:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",permalink:"/java-spring-springboot"}},c={authorsImageUrls:[]},o=[{value:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784",id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc758-\ucc45\uc784",level:3},{value:"\uace0\ub824\ud55c \uae30\uc220",id:"\uace0\ub824\ud55c-\uae30\uc220",level:3},{value:"Python & Matplotlib",id:"python--matplotlib",level:2},{value:"Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac",id:"java-awt-\uc774\uc678\uc758-\ub77c\uc774\ube0c\ub7ec\ub9ac",level:3},{value:"Java & AWT(Abstract Window Toolkit)",id:"java--awtabstract-window-toolkit",level:3},{value:"\uae30\uc220 \uc120\ud0dd",id:"\uae30\uc220-\uc120\ud0dd",level:3},{value:"\uc720\uc9c0 \ubcf4\uc218",id:"\uc720\uc9c0-\ubcf4\uc218",level:3},{value:"\ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00",id:"\ub808\ubca8-3\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70-\ub0b4\uc6a9-\ucd94\uac00",level:3}];function d(e){const t={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"./route.png",src:n(29632).Z+"",width:"1014",height:"902"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc758-\ucc45\uc784",children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784"}),"\n",(0,r.jsxs)(t.p,{children:["\uc704 \uc640\uc774\uc5b4 \ud504\ub808\uc784\uc5d0\uc11c ",(0,r.jsx)(t.code,{children:"\uc5ec\ud589 \ud788\uc2a4\ud1a0\ub9ac"}),"\uc640 ",(0,r.jsx)(t.code,{children:"\uc5ec\ud589\uc5d0 \ub300\ud55c \uac10\uc0c1\uc744 \uc704\ud55c \uacbd\ub85c \uc774\ubbf8\uc9c0"}),"\uc758 \uacbd\uc6b0 \ub124\uc774\ubc84 \uc9c0\ub3c4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \uc218 \uc5c6\uc73c\ub2c8 \ub2f9\uc5f0\ud788 \ub9f5 API\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub3c4\ud615 \uadf8\ub9ac\uae30 API(\ub124\uc774\ubc84 \ub9f5 API \uae30\uc900 Polyline)\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub530\ub77c\uc11c \uc774\ubbf8\uc9c0\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uac70\ub098, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c1\uc811 \uc704\uacbd\ub3c4\ub97c \uc774\uc6a9\ud558\uc5ec \uadf8\ub824\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:"\ud574\ub2f9 \uc694\uad6c\uc0ac\ud56d\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uae30\ub2a5\uc744 \uac00\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud544\uc694\ud558\ub2e4."}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131"}),"\n",(0,r.jsx)(t.li,{children:"\uc120\uacfc \uc810 \ud45c\ud604"}),"\n",(0,r.jsx)(t.li,{children:"\ud22c\uba85\ud55c \ubc30\uacbd\uc0c9"}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"\ud604\uc7ac \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ubc14\uc05c \uc77c\uc815\uacfc \uae30\ub2a5 \uad6c\ud604\uc5d0 \uc788\uc5b4 \uc57d\uac04\uc758 \uc5f0\uc0b0\uc774 \ub4e4\uc5b4\uac04\ub2e4\ub294 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uc5ec \ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30\ub85c \uacb0\uc815\uc744 \ub0b4\ub838\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"\uace0\ub824\ud55c-\uae30\uc220",children:"\uace0\ub824\ud55c \uae30\uc220"}),"\n",(0,r.jsx)(t.p,{children:"\ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uae30 \uc704\ud574 \ub2e4\uc74c\uacfc \uac19\uc740 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 \uae30\uc220\ub4e4\uc744 \ud655\uc778\ud574 \ubcf4\uc558\ub2e4."}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"Python\uc758 Matplotlib"}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.strong,{children:"AWT(Abstract Window Toolkit) [\ucd5c\uc885 \uc120\ud0dd]"})}),"\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \ucc98\ub9ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ubc0f Java\uc5d0\uc11c \ub0b4\ubd80\uc801\uc73c\ub85c Matplotlib \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac (\uc6d0\ud558\ub294 \uae30\ub2a5 \uc5c6\uc74c)"}),"\n",(0,r.jsx)(t.li,{children:"Java Swing, Java FX (\ub2e8\uc21c\ud55c \uc120 \uadf8\ub9ac\uae30 + \uc810 \ucc0d\uae30\ub77c \ubd88\ud544\uc694)"}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"python--matplotlib",children:"Python & Matplotlib"}),"\n",(0,r.jsxs)(t.p,{children:["\ub370\uc774\ud130 \uc2dc\uac01\ud654 \ub77c\uc774\ube0c\ub7ec\ub9ac",(0,r.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 0.2\ucd08"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ucf54\ub4dc\uac00 \uac04\ub2e8\ud574\uc11c \uc720\uc9c0 \ubcf4\uc218\uc131\uc774 \uc88b\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"AWS Lambda \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ucef4\ud4e8\ud305 \uc11c\ube44\uc2a4\ub098 FastAPI\uc640 \uac19\uc740 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\ub85c \ucd94\uac00\uc801\uc778 API\ub97c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"Spring Boot\uc5d0\uc11c \ucd94\uac00\uc801\uc778 API \ud638\ucd9c\uc744 \ud574\uc57c\ud558\uace0, \ud655\uc7a5\uc131\uacfc \ube44\ub3d9\uae30 \ucc98\ub9ac \ub4f1 \uace0\ub824 \ud574\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"java-awt-\uc774\uc678\uc758-\ub77c\uc774\ube0c\ub7ec\ub9ac",children:"Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),"\n",(0,r.jsx)(t.p,{children:"Python\uc774 \uc544\ub2cc Java\uc5d0\uc11c\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub3c4 \uace0\ub824\ub97c \ud574\ubd24\uc9c0\ub9cc \uc694\uad6c\uc0ac\ud56d\uc5d0 \uc801\ud569\ud558\uc9c0 \uc54a\uac70\ub098, \uc801\uc740 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac70\uc6b4 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\uc678\ud588\ub2e4."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"\ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.th,{children:"\uc124\uba85"}),(0,r.jsx)(t.th,{children:"\uc81c\uc678 \uc774\uc720"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Swing"}),(0,r.jsx)(t.td,{children:"AWT \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, \ub124\uc774\ud2f0\ube0c UI\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubaa8\ub4e0 \uc6b4\uc601\uccb4\uc81c \uc0c1\uc5d0\uc11c \ub3d9\uc77c\ud55c UI\ub97c \uac00\uc9c0\ub3c4\ub85d \ud568"}),(0,r.jsx)(t.td,{children:"\uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"JavaFX"}),(0,r.jsx)(t.td,{children:"Swing \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, 3\ucc28\uc6d0 \uadf8\ub798\ud53d\uc744 \uc9c0\uc6d0\ud568"}),(0,r.jsx)(t.td,{children:"\uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://github.com/yuriy-g/simple-java-plot",children:"simple-java-plot"})}),(0,r.jsx)(t.td,{children:"AWT\ub85c \uad6c\ud604\ub41c \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.td,{children:"AWT \uae30\ubc18\uc774\uae34 \ud558\uc9c0\ub9cc \uc9c1\uc811 AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc5d0 \ube44\ud574 \uba54\ub9ac\ud2b8\uac00 \uc5c6\uc74c, \ucee4\uc2a4\ud140 \uc124\uc815 \uae30\ub2a5\uc774 \uc5c6\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://github.com/sh0nk/matplotlib4j",children:"matplotlib4j"})}),(0,r.jsx)(t.td,{children:"Matplotlib\ub97c Java\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud558\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.td,{children:"\ub0b4\ubd80\uc801\uc73c\ub85c \ud30c\uc774\uc36c \uc0ac\uc6a9\ud558\uae30\uc5d0 \ubb34\uac70\uc6c0, \ubc30\uacbd \ud22c\uba85\ud654 \uae30\ub2a5 \uc5c6\uc74c"})]})]})]}),"\n",(0,r.jsx)(t.h3,{id:"java--awtabstract-window-toolkit",children:"Java & AWT(Abstract Window Toolkit)"}),"\n",(0,r.jsxs)(t.p,{children:["\uadf8\ub798\ud53d\uacfc \uc774\ubbf8\uc9c0\ub97c \uadf8\ub9ac\uae30 \uc704\ud55c \ub3c4\uad6c",(0,r.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 1.75\ucd08"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ubcf4\ub2e4 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub2e4\uc18c \uc18c\uc694\ub418\uae30 \ub54c\ubb38\uc5d0 \ube60\ub978 \uc751\ub2f5 \ubc18\ud658\uc744 \uc704\ud574 \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"\uae30\uc220-\uc120\ud0dd",children:"\uae30\uc220 \uc120\ud0dd"}),"\n",(0,r.jsxs)(t.p,{children:["AWT\uc758 \uacbd\uc6b0 Matplotlib\uc5d0 \ube44\ud574 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc788\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub354 \ub9ce\uc774 \uac78\ub9ac\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub418\ub294 \ubd80\ubd84, Python\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc778 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uace0\ub824\ud558\uc5ec AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc720\uc9c0-\ubcf4\uc218",children:"\uc720\uc9c0 \ubcf4\uc218"}),"\n",(0,r.jsxs)(t.p,{children:["AWT\ub77c\ub294 \uc0dd\uc18c\ud55c \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc720\uc9c0 \ubcf4\uc218\uc131\uc744 \uc704\ud574 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub530\ub77c\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\ubc95\uc73c\ub85c \uacf5\uc720\ud558\uae30\ub85c \ud588\ub2e4."]}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"\ucf54\ub4dc \ub9ac\ubdf0\uc640 PR\uc744 \ud1b5\ud574 \uc791\uc131\ud55c AWT \ucf54\ub4dc\uc5d0 \ub300\ud55c \uc124\uba85 \ubc0f \ub9ac\ubdf0 \ubc1b\ub294\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"AWT\ub97c \uc0ac\uc6a9\ud55c \ubd80\ubd84\uc744 \ubb38\uc11c\ud654\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"\ub808\ubca8-3\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70-\ub0b4\uc6a9-\ucd94\uac00",children:"\ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00"}),"\n",(0,r.jsxs)(t.p,{children:["\uae30\uc220 \uc120\ud0dd\uc744 \ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815\uc5d0 \uc624\ub958\uac00 \uc788\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589 \uc2dc\uac04\uc744 \uc81c\uc678\ud558\uba74 \ud30c\uc774\uc36c\uacfc \ube44\uc2b7\ud55c \uc2dc\uac04\uc548\uc5d0 \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud560 \uc218 \uc788\uc5c8\ub2e4."]})]})}function h(e={}){const{wrapper:t}={...(0,i.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>o});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var c=r.createContext({}),o=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,l=e.originalType,c=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),j=o(n),p=i,x=j["".concat(c,".").concat(p)]||j[p]||d[p]||l;return n?r.createElement(x,a(a({ref:t},h),{},{components:n})):r.createElement(x,a({ref:t},h))}));h.displayName="MDXCreateElement"},29632:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/route-89cacb9b7815a3191ab1f9d9e23c43a1.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3365],{79766:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>l,metadata:()=>s,toc:()=>o});var r=n(85893),i=n(3905);const l={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",slug:"route-image-intro",tags:["image","awt"]},a=void 0,s={permalink:"/route-image-intro",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",source:"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",description:"./route.png",date:"2023-07-27T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 27\uc77c",tags:[{label:"image",permalink:"/tags/image"},{label:"awt",permalink:"/tags/awt"}],readingTime:5.865,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",slug:"route-image-intro",tags:["image","awt"]},unlisted:!1,prevItem:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",permalink:"/java-spring-springboot"},nextItem:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",permalink:"/mock-static-method"}},c={authorsImageUrls:[]},o=[{value:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784",id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc758-\ucc45\uc784",level:3},{value:"\uace0\ub824\ud55c \uae30\uc220",id:"\uace0\ub824\ud55c-\uae30\uc220",level:3},{value:"Python & Matplotlib",id:"python--matplotlib",level:2},{value:"Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac",id:"java-awt-\uc774\uc678\uc758-\ub77c\uc774\ube0c\ub7ec\ub9ac",level:3},{value:"Java & AWT(Abstract Window Toolkit)",id:"java--awtabstract-window-toolkit",level:3},{value:"\uae30\uc220 \uc120\ud0dd",id:"\uae30\uc220-\uc120\ud0dd",level:3},{value:"\uc720\uc9c0 \ubcf4\uc218",id:"\uc720\uc9c0-\ubcf4\uc218",level:3},{value:"\ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00",id:"\ub808\ubca8-3\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70-\ub0b4\uc6a9-\ucd94\uac00",level:3}];function d(e){const t={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"./route.png",src:n(29632).Z+"",width:"1014",height:"902"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc758-\ucc45\uc784",children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784"}),"\n",(0,r.jsxs)(t.p,{children:["\uc704 \uc640\uc774\uc5b4 \ud504\ub808\uc784\uc5d0\uc11c ",(0,r.jsx)(t.code,{children:"\uc5ec\ud589 \ud788\uc2a4\ud1a0\ub9ac"}),"\uc640 ",(0,r.jsx)(t.code,{children:"\uc5ec\ud589\uc5d0 \ub300\ud55c \uac10\uc0c1\uc744 \uc704\ud55c \uacbd\ub85c \uc774\ubbf8\uc9c0"}),"\uc758 \uacbd\uc6b0 \ub124\uc774\ubc84 \uc9c0\ub3c4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \uc218 \uc5c6\uc73c\ub2c8 \ub2f9\uc5f0\ud788 \ub9f5 API\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub3c4\ud615 \uadf8\ub9ac\uae30 API(\ub124\uc774\ubc84 \ub9f5 API \uae30\uc900 Polyline)\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub530\ub77c\uc11c \uc774\ubbf8\uc9c0\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uac70\ub098, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c1\uc811 \uc704\uacbd\ub3c4\ub97c \uc774\uc6a9\ud558\uc5ec \uadf8\ub824\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:"\ud574\ub2f9 \uc694\uad6c\uc0ac\ud56d\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uae30\ub2a5\uc744 \uac00\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud544\uc694\ud558\ub2e4."}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131"}),"\n",(0,r.jsx)(t.li,{children:"\uc120\uacfc \uc810 \ud45c\ud604"}),"\n",(0,r.jsx)(t.li,{children:"\ud22c\uba85\ud55c \ubc30\uacbd\uc0c9"}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"\ud604\uc7ac \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ubc14\uc05c \uc77c\uc815\uacfc \uae30\ub2a5 \uad6c\ud604\uc5d0 \uc788\uc5b4 \uc57d\uac04\uc758 \uc5f0\uc0b0\uc774 \ub4e4\uc5b4\uac04\ub2e4\ub294 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uc5ec \ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30\ub85c \uacb0\uc815\uc744 \ub0b4\ub838\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"\uace0\ub824\ud55c-\uae30\uc220",children:"\uace0\ub824\ud55c \uae30\uc220"}),"\n",(0,r.jsx)(t.p,{children:"\ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uae30 \uc704\ud574 \ub2e4\uc74c\uacfc \uac19\uc740 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 \uae30\uc220\ub4e4\uc744 \ud655\uc778\ud574 \ubcf4\uc558\ub2e4."}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"Python\uc758 Matplotlib"}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.strong,{children:"AWT(Abstract Window Toolkit) [\ucd5c\uc885 \uc120\ud0dd]"})}),"\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \ucc98\ub9ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ubc0f Java\uc5d0\uc11c \ub0b4\ubd80\uc801\uc73c\ub85c Matplotlib \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac (\uc6d0\ud558\ub294 \uae30\ub2a5 \uc5c6\uc74c)"}),"\n",(0,r.jsx)(t.li,{children:"Java Swing, Java FX (\ub2e8\uc21c\ud55c \uc120 \uadf8\ub9ac\uae30 + \uc810 \ucc0d\uae30\ub77c \ubd88\ud544\uc694)"}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"python--matplotlib",children:"Python & Matplotlib"}),"\n",(0,r.jsxs)(t.p,{children:["\ub370\uc774\ud130 \uc2dc\uac01\ud654 \ub77c\uc774\ube0c\ub7ec\ub9ac",(0,r.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 0.2\ucd08"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ucf54\ub4dc\uac00 \uac04\ub2e8\ud574\uc11c \uc720\uc9c0 \ubcf4\uc218\uc131\uc774 \uc88b\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"AWS Lambda \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ucef4\ud4e8\ud305 \uc11c\ube44\uc2a4\ub098 FastAPI\uc640 \uac19\uc740 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\ub85c \ucd94\uac00\uc801\uc778 API\ub97c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"Spring Boot\uc5d0\uc11c \ucd94\uac00\uc801\uc778 API \ud638\ucd9c\uc744 \ud574\uc57c\ud558\uace0, \ud655\uc7a5\uc131\uacfc \ube44\ub3d9\uae30 \ucc98\ub9ac \ub4f1 \uace0\ub824 \ud574\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"java-awt-\uc774\uc678\uc758-\ub77c\uc774\ube0c\ub7ec\ub9ac",children:"Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),"\n",(0,r.jsx)(t.p,{children:"Python\uc774 \uc544\ub2cc Java\uc5d0\uc11c\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub3c4 \uace0\ub824\ub97c \ud574\ubd24\uc9c0\ub9cc \uc694\uad6c\uc0ac\ud56d\uc5d0 \uc801\ud569\ud558\uc9c0 \uc54a\uac70\ub098, \uc801\uc740 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac70\uc6b4 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\uc678\ud588\ub2e4."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"\ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.th,{children:"\uc124\uba85"}),(0,r.jsx)(t.th,{children:"\uc81c\uc678 \uc774\uc720"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Swing"}),(0,r.jsx)(t.td,{children:"AWT \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, \ub124\uc774\ud2f0\ube0c UI\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubaa8\ub4e0 \uc6b4\uc601\uccb4\uc81c \uc0c1\uc5d0\uc11c \ub3d9\uc77c\ud55c UI\ub97c \uac00\uc9c0\ub3c4\ub85d \ud568"}),(0,r.jsx)(t.td,{children:"\uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"JavaFX"}),(0,r.jsx)(t.td,{children:"Swing \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, 3\ucc28\uc6d0 \uadf8\ub798\ud53d\uc744 \uc9c0\uc6d0\ud568"}),(0,r.jsx)(t.td,{children:"\uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://github.com/yuriy-g/simple-java-plot",children:"simple-java-plot"})}),(0,r.jsx)(t.td,{children:"AWT\ub85c \uad6c\ud604\ub41c \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.td,{children:"AWT \uae30\ubc18\uc774\uae34 \ud558\uc9c0\ub9cc \uc9c1\uc811 AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc5d0 \ube44\ud574 \uba54\ub9ac\ud2b8\uac00 \uc5c6\uc74c, \ucee4\uc2a4\ud140 \uc124\uc815 \uae30\ub2a5\uc774 \uc5c6\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://github.com/sh0nk/matplotlib4j",children:"matplotlib4j"})}),(0,r.jsx)(t.td,{children:"Matplotlib\ub97c Java\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud558\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.td,{children:"\ub0b4\ubd80\uc801\uc73c\ub85c \ud30c\uc774\uc36c \uc0ac\uc6a9\ud558\uae30\uc5d0 \ubb34\uac70\uc6c0, \ubc30\uacbd \ud22c\uba85\ud654 \uae30\ub2a5 \uc5c6\uc74c"})]})]})]}),"\n",(0,r.jsx)(t.h3,{id:"java--awtabstract-window-toolkit",children:"Java & AWT(Abstract Window Toolkit)"}),"\n",(0,r.jsxs)(t.p,{children:["\uadf8\ub798\ud53d\uacfc \uc774\ubbf8\uc9c0\ub97c \uadf8\ub9ac\uae30 \uc704\ud55c \ub3c4\uad6c",(0,r.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 1.75\ucd08"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ubcf4\ub2e4 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub2e4\uc18c \uc18c\uc694\ub418\uae30 \ub54c\ubb38\uc5d0 \ube60\ub978 \uc751\ub2f5 \ubc18\ud658\uc744 \uc704\ud574 \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"\uae30\uc220-\uc120\ud0dd",children:"\uae30\uc220 \uc120\ud0dd"}),"\n",(0,r.jsxs)(t.p,{children:["AWT\uc758 \uacbd\uc6b0 Matplotlib\uc5d0 \ube44\ud574 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc788\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub354 \ub9ce\uc774 \uac78\ub9ac\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub418\ub294 \ubd80\ubd84, Python\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc778 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uace0\ub824\ud558\uc5ec AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc720\uc9c0-\ubcf4\uc218",children:"\uc720\uc9c0 \ubcf4\uc218"}),"\n",(0,r.jsxs)(t.p,{children:["AWT\ub77c\ub294 \uc0dd\uc18c\ud55c \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc720\uc9c0 \ubcf4\uc218\uc131\uc744 \uc704\ud574 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub530\ub77c\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\ubc95\uc73c\ub85c \uacf5\uc720\ud558\uae30\ub85c \ud588\ub2e4."]}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"\ucf54\ub4dc \ub9ac\ubdf0\uc640 PR\uc744 \ud1b5\ud574 \uc791\uc131\ud55c AWT \ucf54\ub4dc\uc5d0 \ub300\ud55c \uc124\uba85 \ubc0f \ub9ac\ubdf0 \ubc1b\ub294\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"AWT\ub97c \uc0ac\uc6a9\ud55c \ubd80\ubd84\uc744 \ubb38\uc11c\ud654\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"\ub808\ubca8-3\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70-\ub0b4\uc6a9-\ucd94\uac00",children:"\ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00"}),"\n",(0,r.jsxs)(t.p,{children:["\uae30\uc220 \uc120\ud0dd\uc744 \ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815\uc5d0 \uc624\ub958\uac00 \uc788\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589 \uc2dc\uac04\uc744 \uc81c\uc678\ud558\uba74 \ud30c\uc774\uc36c\uacfc \ube44\uc2b7\ud55c \uc2dc\uac04\uc548\uc5d0 \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud560 \uc218 \uc788\uc5c8\ub2e4."]})]})}function h(e={}){const{wrapper:t}={...(0,i.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>o});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var c=r.createContext({}),o=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,l=e.originalType,c=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),j=o(n),p=i,x=j["".concat(c,".").concat(p)]||j[p]||d[p]||l;return n?r.createElement(x,a(a({ref:t},h),{},{components:n})):r.createElement(x,a({ref:t},h))}));h.displayName="MDXCreateElement"},29632:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/route-89cacb9b7815a3191ab1f9d9e23c43a1.png"}}]); \ No newline at end of file diff --git a/assets/js/52106a5f.17a5eda6.js b/assets/js/52106a5f.a24ae46f.js similarity index 94% rename from assets/js/52106a5f.17a5eda6.js rename to assets/js/52106a5f.a24ae46f.js index bc9eb1799..c559dd14d 100644 --- a/assets/js/52106a5f.17a5eda6.js +++ b/assets/js/52106a5f.a24ae46f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9396],{68973:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var r=n(85893),i=n(3905);const l={title:"IntelliJ \uc124\uc815",slug:"intellij-settings",tags:["IntelliJ"]},a=void 0,o={permalink:"/intellij-settings",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",source:"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",title:"IntelliJ \uc124\uc815",description:"Import \uc790\ub3d9 \uc801\uc6a9",date:"2023-01-30T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 30\uc77c",tags:[{label:"IntelliJ",permalink:"/tags/intelli-j"}],readingTime:.465,hasTruncateMarker:!1,authors:[],frontMatter:{title:"IntelliJ \uc124\uc815",slug:"intellij-settings",tags:["IntelliJ"]},unlisted:!1,prevItem:{title:"Parameterized Tests",permalink:"/parameterized-tests"},nextItem:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",permalink:"/kotlin-null"}},s={authorsImageUrls:[]},c=[{value:"Import \uc790\ub3d9 \uc801\uc6a9",id:"import-\uc790\ub3d9-\uc801\uc6a9",level:3},{value:"\uc800\uc7a5\uc2dc \ub3d9\uc791",id:"\uc800\uc7a5\uc2dc-\ub3d9\uc791",level:3},{value:"\uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9",id:"\uba54\uc18c\ub4dc-\ucd94\ucd9c-\ubcc0\uc218-\ucd94\ucd9c\uc2dc-final-\uc801\uc6a9",level:3}];function p(e){const t={h3:"h3",img:"img",p:"p",...(0,i.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"import-\uc790\ub3d9-\uc801\uc6a9",children:"Import \uc790\ub3d9 \uc801\uc6a9"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"auto-import",src:n(41394).Z+"",width:"2558",height:"1656"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc800\uc7a5\uc2dc-\ub3d9\uc791",children:"\uc800\uc7a5\uc2dc \ub3d9\uc791"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Tools > Actions on Save"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"actions-on-save",src:n(24927).Z+"",width:"2558",height:"1656"})}),"\n",(0,r.jsx)(t.p,{children:"Reformat Code: Code Reformmating"}),"\n",(0,r.jsx)(t.p,{children:"Optimize imports: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 Import \uc81c\uac70"}),"\n",(0,r.jsx)(t.p,{children:"Rearrange: Code Style > Arrangement \uc124\uc815 \uae30\ubc18 \ucf54\ub4dc \uc7ac\uc815\ub82c"}),"\n",(0,r.jsx)(t.h3,{id:"\uba54\uc18c\ub4dc-\ucd94\ucd9c-\ubcc0\uc218-\ucd94\ucd9c\uc2dc-final-\uc801\uc6a9",children:"\uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"final-modifier",src:n(21796).Z+"",width:"2558",height:"1656"})})]})}function d(e={}){const{wrapper:t}={...(0,i.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,l=e.originalType,s=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),m=c(n),u=i,f=m["".concat(s,".").concat(u)]||m[u]||p[u]||l;return n?r.createElement(f,a(a({ref:t},d),{},{components:n})):r.createElement(f,a({ref:t},d))}));d.displayName="MDXCreateElement"},24927:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/actions-on-save-6c1203027c28ff08919e045812c7d456.png"},41394:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/auto-import-3dbe46f0109af17296039d52d498225e.png"},21796:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/final-modifier-1dd2aea35979423a30869a7b0ebe501a.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9396],{68973:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var r=n(85893),i=n(3905);const l={title:"IntelliJ \uc124\uc815",slug:"intellij-settings",tags:["IntelliJ"]},a=void 0,o={permalink:"/intellij-settings",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",source:"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",title:"IntelliJ \uc124\uc815",description:"Import \uc790\ub3d9 \uc801\uc6a9",date:"2023-01-30T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 30\uc77c",tags:[{label:"IntelliJ",permalink:"/tags/intelli-j"}],readingTime:.465,hasTruncateMarker:!1,authors:[],frontMatter:{title:"IntelliJ \uc124\uc815",slug:"intellij-settings",tags:["IntelliJ"]},unlisted:!1,prevItem:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",permalink:"/kotlin-null"},nextItem:{title:"Parameterized Tests",permalink:"/parameterized-tests"}},s={authorsImageUrls:[]},c=[{value:"Import \uc790\ub3d9 \uc801\uc6a9",id:"import-\uc790\ub3d9-\uc801\uc6a9",level:3},{value:"\uc800\uc7a5\uc2dc \ub3d9\uc791",id:"\uc800\uc7a5\uc2dc-\ub3d9\uc791",level:3},{value:"\uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9",id:"\uba54\uc18c\ub4dc-\ucd94\ucd9c-\ubcc0\uc218-\ucd94\ucd9c\uc2dc-final-\uc801\uc6a9",level:3}];function p(e){const t={h3:"h3",img:"img",p:"p",...(0,i.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"import-\uc790\ub3d9-\uc801\uc6a9",children:"Import \uc790\ub3d9 \uc801\uc6a9"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"auto-import",src:n(41394).Z+"",width:"2558",height:"1656"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc800\uc7a5\uc2dc-\ub3d9\uc791",children:"\uc800\uc7a5\uc2dc \ub3d9\uc791"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Tools > Actions on Save"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"actions-on-save",src:n(24927).Z+"",width:"2558",height:"1656"})}),"\n",(0,r.jsx)(t.p,{children:"Reformat Code: Code Reformmating"}),"\n",(0,r.jsx)(t.p,{children:"Optimize imports: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 Import \uc81c\uac70"}),"\n",(0,r.jsx)(t.p,{children:"Rearrange: Code Style > Arrangement \uc124\uc815 \uae30\ubc18 \ucf54\ub4dc \uc7ac\uc815\ub82c"}),"\n",(0,r.jsx)(t.h3,{id:"\uba54\uc18c\ub4dc-\ucd94\ucd9c-\ubcc0\uc218-\ucd94\ucd9c\uc2dc-final-\uc801\uc6a9",children:"\uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9"}),"\n",(0,r.jsx)(t.p,{children:"Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"final-modifier",src:n(21796).Z+"",width:"2558",height:"1656"})})]})}function d(e={}){const{wrapper:t}={...(0,i.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,l=e.originalType,s=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),m=c(n),u=i,f=m["".concat(s,".").concat(u)]||m[u]||p[u]||l;return n?r.createElement(f,a(a({ref:t},d),{},{components:n})):r.createElement(f,a({ref:t},d))}));d.displayName="MDXCreateElement"},24927:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/actions-on-save-6c1203027c28ff08919e045812c7d456.png"},41394:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/auto-import-3dbe46f0109af17296039d52d498225e.png"},21796:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/final-modifier-1dd2aea35979423a30869a7b0ebe501a.png"}}]); \ No newline at end of file diff --git a/assets/js/530ffa4f.2cf34794.js b/assets/js/530ffa4f.89118ba6.js similarity index 99% rename from assets/js/530ffa4f.2cf34794.js rename to assets/js/530ffa4f.89118ba6.js index 5bdf89a11..9c8268ffe 100644 --- a/assets/js/530ffa4f.2cf34794.js +++ b/assets/js/530ffa4f.89118ba6.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4818],{17804:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>a});var n=t(85893),s=t(3905);const i={title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",slug:"refactoring-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,o={permalink:"/refactoring-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-refactoring/pull/465",date:"2023-10-31T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 31\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:8.095,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",slug:"refactoring-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,nextItem:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/jdbc-retrospective"}},l={authorsImageUrls:[]},a=[{value:"\ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158",id:"\ub9ac\ud329\ud130\ub9c1-\ubbf8\uc158",level:3},{value:"1, 2\ub2e8\uacc4",id:"1-2\ub2e8\uacc4",level:3},{value:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c",id:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758-\ubcf5\uc7a1\uc131\uc744-\ub2e4\ub8e8\ub294-\uc9c0\ud61c",level:3},{value:"3, 4\ub2e8\uacc4",id:"3-4\ub2e8\uacc4",level:3},{value:"\ub9c8\ubb34\ub9ac",id:"\ub9c8\ubb34\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,n.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/465",children:"https://github.com/woowacourse/jwp-refactoring/pull/465"}),(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/547",children:"https://github.com/woowacourse/jwp-refactoring/pull/547"}),(0,n.jsx)(r.br,{}),"\n","3\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/610",children:"https://github.com/woowacourse/jwp-refactoring/pull/610"}),(0,n.jsx)(r.br,{}),"\n","4\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/721",children:"https://github.com/woowacourse/jwp-refactoring/pull/721"})]})}),"\n",(0,n.jsx)(r.h3,{id:"\ub9ac\ud329\ud130\ub9c1-\ubbf8\uc158",children:"\ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["\uc694\uad6c\uc0ac\ud56d \uc791\uc131 \u2192 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud55c \ucf54\ub4dc \ubcf4\ud638 \u2192 \ub9ac\ud329\ud130\ub9c1 \u2192 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1 \u2192 \uba40\ud2f0\ubaa8\ub4c8 \uc21c\uc11c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc5d0 \uc628\uc804\ud788 \uc9d1\uc911\ud558\uace0 \uc2f6\uc5c8\uc9c0\ub9cc, \ud504\ub85c\uc81d\ud2b8\uc640 \ubcd1\ud589\ud558\uba74\uc11c \uc9c4\ud589\ud588\uae30\uc5d0 \uc5b4\ub290\uc815\ub3c4 \ud0c0\ud611\ubcf4\uace0 \uc9c4\ud589\ud55c \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c \uc544\uc26c\uc6e0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"1-2\ub2e8\uacc4",children:"1, 2\ub2e8\uacc4"}),"\n",(0,n.jsx)(r.p,{children:"1\ub2e8\uacc4\ub294 \uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud558\uace0, \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ucd94\ud6c4\uc5d0 \ub9ac\ud329\ud130\ub9c1 \ud560 \ub54c \uc548\uc815\uac10 \uc788\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\ub3c4\ub85d \uc900\ube44\ud558\ub294 \uacfc\uc815\uc774\uc5c8\ub2e4.\n\uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud560 \ub54c \uc81c\uacf5\ub41c \uc6a9\uc5b4 \uc0ac\uc804\uc744 \ucd5c\ub300\ud55c \ud65c\uc6a9\ud558\uba74\uc11c \uae30\uc874\uc758 \ucf54\ub4dc\ub97c \ubcf4\uba74\uc11c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud588\ub2e4.\n\ud14c\uc2a4\ud2b8\ub294 \uc2dc\uac04 \uad00\uacc4\uc0c1 API, \uc11c\ube44\uc2a4 \ub458 \uc911 \ud558\ub098\ub9cc \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4."}),"\n",(0,n.jsxs)(r.p,{children:["\ucd5c\uc885\uc801\uc73c\ub85c \uc11c\ube44\uc2a4 \uae30\uc900\uc73c\ub85c \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud588\ub294\ub370 \uc57d\uac04 \ud6c4\ud68c\ub418\ub294 \uacb0\uc815\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub9ac\ud329\ud130\ub9c1 \uacfc\uc815\uc5d0\uc11c API \uba85\uc138\uac00 \ubc14\ub00c\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4\ub294 \uac83\uc744 \uae30\uc900\uc744 \uc7a1\uace0 \uc774\ubc88 \ubbf8\uc158\uc744 \ud55c\ub2e4\uace0 \uac00\uc815\ud588\uc744 \ub54c API \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\uace0, \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ub354 \uc548\uc815\uac10 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["2\ub2e8\uacc4\ub294 \uc791\uc131\ub41c \ud14c\uc2a4\ud2b8 \uae30\ubc18\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc11c\ube44\uc2a4\uc5d0\uc11c \ub3c4\uba54\uc778\uc744 \uc9c1\uc811 \ubc18\ud658\ud558\ub294 \uad6c\uc870\uc600\ub294\ub370, \ub3c4\uba54\uc778\uc5d0 JPA\ub97c \uc801\uc6a9\ud558\uba74 \uae30\uc874 \uba85\uc138\uc640 \ub2ec\ub77c\uc9c8 \uac83\uc744 \uc6b0\ub824\ud574\uc11c DTO\ub85c \uc218\uc815\ud558\ub294 \uc791\uc5c5\uc744 \uba3c\uc800 \uc9c4\ud589\ud588\ub2e4.\nDTO \uc774\ud6c4\uc5d0 \uc11c\ube44\uc2a4\uc5d0 \uc788\ub294 \ub85c\uc9c1\uc744 \ub3c4\uba54\uc778\uc73c\ub85c \uc774\ub3d9\uc2dc\ud0a4\uace0, \ucd5c\uc885\uc801\uc73c\ub85c JPA\ub97c \uc801\uc6a9\ud558\ub294 \uc21c\uc11c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud588\ub2e4.\n\uc774 \uacfc\uc815\uc5d0\uc11c \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \uc591\ubc29\ud5a5\uc778 \ubd80\ubd84\ub3c4 \uc0dd\uaca8\ub0ac\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758-\ubcf5\uc7a1\uc131\uc744-\ub2e4\ub8e8\ub294-\uc9c0\ud61c",children:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c"}),"\n",(0,n.jsxs)(r.p,{children:["\uc911\uac04\uc5d0 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\uc5d0 \uad00\ud55c \uc81c\uc774\uc2a8\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\ub294 \uc5d0\ub9ad \uc5d0\ubc18\uc2a4\uc758 \uc800\uc11c ",(0,n.jsx)(r.code,{children:"\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4"}),"\uc758 \ubd80\uc81c\uc774\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\ub294 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4, \uc804\uc220\uc801 \uc124\uacc4\uac00 \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4\uac00 \uc804\uccb4\uc758 90%\uc5d0 \ud574\ub2f9\ud560 \uc815\ub3c4\ub85c \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4. \ub610\ud55c \uc804\uc220\uc801 \uc124\uacc4\ub9cc \ud558\ub294 \uacbd\uc6b0\ub97c DDD Lite \ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\uac04\ub2e8\ud788 \ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\uc5d0\uc11c \ub098\uc624\ub294 \ub2e8\uc5b4\ub97c \uc815\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,n.jsxs)(r.table,{children:[(0,n.jsx)(r.thead,{children:(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.th,{children:"\ub2e8\uc5b4"}),(0,n.jsx)(r.th,{children:"\uc124\uba85"})]})}),(0,n.jsxs)(r.tbody,{children:[(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\ub3c4\uba54\uc778"}),(0,n.jsx)(r.td,{children:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\ub85c \ud574\uacb0\ud558\uace0\uc790 \ud558\ub294 \ubb38\uc81c \uc601\uc5ed"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8"}),(0,n.jsx)(r.td,{children:"\ud574\uacb0 \uc601\uc5ed, \uad00\uc2ec\uc0ac\ub97c \ubd84\ub9ac\ud558\uace0 \uaca9\ub9ac\ud558\uc5ec \ubb38\uc81c \ud574\uacb0\uc5d0 \uc9d1\uc911\ud560 \ubc94\uc704"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4"}),(0,n.jsx)(r.td,{children:"\ud504\ub85c\uc81d\ud2b8\uc5d0 \uc774\ud574\uad00\uacc4\uc790\ub4e4\uc758 \uacf5\ud1b5\ub41c \uc5b8\uc5b4\ub85c, \uc11c\ub85c\uc758 \uc758\uc0ac\uc18c\ud1b5 \ube44\uc6a9\uc744 \uc904\uc774\uae30 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 \uc5b8\uc5b4"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc804\ub7b5\uc801 \uc124\uacc4"}),(0,n.jsx)(r.td,{children:"\ub3c4\uba54\uc778 \uc804\ubb38\uac00\uc640 \uac1c\ubc1c\uc790\uac00 \ud568\uaed8 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec \ub3c4\uba54\uc778\uacfc \uad00\ub828\ub41c \uc9c0\uc2dd\uc744 \uc774\ud574\ud558\uace0 \uc774\ub97c \ubc14\ud0d5\uc73c\ub85c \uacbd\uacc4\ub97c \ub098\ub220 \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc815\uc758\ud558\uace0, \ucee8\ud14d\uc2a4\ud2b8 \ub9f5\uc744 \uc0dd\uc131\ud558\ub294 \uac83\uc744 \ud3ec\ud568\ud558\ub294 \uacfc\uc815"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc804\uc220\uc801 \uc124\uacc4"}),(0,n.jsx)(r.td,{children:"\uc804\ub7b5\uc801 \uc124\uacc4\uc5d0\uc11c \uc815\uc758\ud55c \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\uc640 \ub3c4\uba54\uc778\uc744 \uc774\uc6a9\ud558\uc5ec \uc560\uadf8\ub9ac\uac70\ud2b8, Entity\uc640 VO, Repository \ub4f1\uc744 \uad6c\ud604\ud558\ub294 \uacfc\uc815"})]})]})]}),"\n",(0,n.jsx)(r.p,{children:"\uc774 \uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ub0b4\uc6a9\ub4e4\uc774 \ub098\uc654\uc9c0\ub9cc, \uc9c0\uc2dd\uc744 \uc81c\ub300\ub85c \ud761\uc218\ud558\uc9c0\ub294 \ubabb\ud588\ub2e4."}),"\n",(0,n.jsx)(r.h3,{id:"3-4\ub2e8\uacc4",children:"3, 4\ub2e8\uacc4"}),"\n",(0,n.jsx)(r.p,{children:"\uc81c\uc774\uc2a8\uc758 \uac15\uc758\ub97c \ub4e3\uace0, \uc870\uc601\ud638\ub2d8\uc758 \uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5 \uc720\ud29c\ube0c \uc601\uc0c1\uc744 \ubcf8 \ub2e4\uc74c 3, 4\ub2e8\uacc4\ub97c \uc9c4\ud589\ud588\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:"3\ub2e8\uacc4\ub294 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1\uc5d0 \uad00\ud55c \ub0b4\uc6a9\uc774\uc5c8\ub2e4. \ud074\ub798\uc2a4 \uac04 \ubc29\ud5a5, \ud328\ud0a4\uc9c0 \uac04 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc774 \ub418\ub3c4\ub85d \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud574\uc57c \ud588\uc5c8\ub2e4.\n\ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4\ub4e4\uc744 \ubb36\uace0, \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uae30 \uc704\ud574 \uc0dd\uba85\uc8fc\uae30\uac00 \ub2e4\ub974\ub2e4\uba74 id\ub97c \uc774\uc6a9\ud558\uc5ec \ucc38\uc870\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:"\uc758\uc874\uc131\uc744 \ubd84\ub9ac\ud558\uae30 \uc704\ud574 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4. \uc774\ubca4\ud2b8\ub294 \ud604\uc7ac \uae30\uc900\uc73c\ub85c \uacfc\uac70\uc5d0 \ubc8c\uc5b4\uc9c4 \uac83\uc744 \ud45c\ud604\ud558\uae30 \ub54c\ubb38\uc5d0 \uc774\ubca4\ud2b8\uba85\uc740 \uacfc\uac70 \uc2dc\uc81c\uac00 \ub418\uc5b4\uc57c\ud558\ub294 \uac83\uc744 \uc54c\uc558\ub2e4.\n\ucc98\uc74c\uc5d0\ub294 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud588\uc9c0\ub9cc, \uc11c\ube44\uc2a4 \ub85c\uc9c1\uc744 \ucd5c\ub300\ud55c \uac04\ub2e8\ud558\uac8c \ud558\uae30 \uc704\ud574 \ub3c4\uba54\uc778 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4."}),"\n",(0,n.jsxs)(r.p,{children:["4\ub2e8\uacc4\ub294 \uba40\ud2f0\ubaa8\ub4c8\ub85c \ubd84\ub9ac\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub294\ub370 3\ub2e8\uacc4\uc5d0\uc11c \ubd84\ub9ac\ud574\ub454 \ud328\ud0a4\uc9c0 \uadf8\ub300\ub85c \ubd84\ub9ac\ud558\uc9c0\ub294 \uc54a\uc558\ub2e4.",(0,n.jsx)(r.br,{}),"\n","3\ub2e8\uacc4\uc5d0\uc11c\ub294 \ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4 \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ud588\ub2e4. 4\ub2e8\uacc4\uc5d0\uc11c\ub294 \ub0b4\uac00 \uc778\uc2dd\ud558\uae30 \ud3b8\ud55c \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ub97c \ud588\ub2e4.\n\uc544\uc9c1 \ubd84\ub9ac\ud55c \uae30\uc900\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \ubaa8\ud638\ud588\uace0, \uc774\uc5d0 \ub300\ud55c \uacf5\ubd80\ub97c \uc870\uae08 \ub354 \ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.mermaid,{value:"graph LR\n\tsubgraph Table\n\t\tOrderTable --\x3e TableGroup\n\tend\n\tsubgraph Order\n\t\tO\n\tend\n O[Order] --\x3e OrderTable\n\tsubgraph Menu\n\t\tM[Menu] --\x3e MenuGroup\n\t\tM --\x3e Product\n\tend\n\tO --\x3e M"}),"\n",(0,n.jsxs)(r.p,{children:["\ucd94\uac00\ub85c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc704\ud55c \uc9c1\uc811 \uc791\uc131\ud55c ",(0,n.jsx)(r.code,{children:"@ServiceTest"})," \ucee4\uc2a4\ud140 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc788\uc5c8\ub294\ub370, \uc0c1\uc704 \ubaa8\ub4c8\uc758 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \ub9cc\ub4e0 \ud074\ub798\uc2a4\ub97c \ud558\uc704 \ubaa8\ub4c8\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4.\n\ub530\ub77c\uc11c TestFixtures\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\uacb0\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ub9c8\ubb34\ub9ac",children:"\ub9c8\ubb34\ub9ac"}),"\n",(0,n.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc758 \ub9c8\uc9c0\ub9c9 \ubbf8\uc158\uc774\ub2c8 \ub9cc\ud07c, \uac00\uc7a5 \ud765\ubbf8\ub85c\uc6b4 \ubbf8\uc158\uc774\uc5c8\uace0 \ubc30\uc6b8\uc810\ub3c4 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc14\uc05c \uae30\uac04\uc774\ub77c \ub9ce\uc740 \ub9ac\ubdf0\ub97c \ub0a8\uae30\uc9c0 \ubabb\ud588\ub358 \ub9ac\ubdf0\uc774 \ud638\uc774\uc5d0\uac8c \ubbf8\uc548\ud558\uace0, \ucf54\uba58\ud2b8 \uaf3c\uaf3c\ud558\uac8c \ub2ec\uc544\uc8fc\uace0 \ubbf8\uc158\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub3c4 \uc624\ud504\ub77c\uc778\uc73c\ub85c \ub9ce\uc774 \ub098\ub208 \ub9ac\ubdf0\uc5b4 \ud14c\uc624\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,n.jsxs)(r.p,{children:[(0,n.jsx)(r.a,{href:"https://www.youtube.com/watch?v=kmUneexSxk0",children:"\ub3c4\uba54\uc778 \uc6d0\uc815\ub300, \uc6b0\uc544\ucf58 2021"}),(0,n.jsx)(r.br,{}),"\n",(0,n.jsx)(r.a,{href:"https://www.youtube.com/watch?v=dJ5C4qRqAgA",children:"\uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5, \uc6b0\uc544\ud55c\ud14c\ud06c\uc138\ubbf8\ub098"}),(0,n.jsx)(r.br,{}),"\n",(0,n.jsx)(r.a,{href:"https://kwonnam.pe.kr/wiki/gradle/testfixtures",children:"TestFixtures, \uad8c\ub0a8\ub2d8"})]})]})}function h(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>a});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=n.createContext({}),a=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},d={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},h=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,h=o(e,["components","mdxType","originalType","parentName"]),p=a(t),u=s,j=p["".concat(l,".").concat(u)]||p[u]||d[u]||i;return t?n.createElement(j,c(c({ref:r},h),{},{components:t})):n.createElement(j,c({ref:r},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4818],{17804:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>a});var n=t(85893),s=t(3905);const i={title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",slug:"refactoring-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,o={permalink:"/refactoring-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-refactoring/pull/465",date:"2023-10-31T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 31\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:8.095,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",slug:"refactoring-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/jdbc-retrospective"}},l={authorsImageUrls:[]},a=[{value:"\ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158",id:"\ub9ac\ud329\ud130\ub9c1-\ubbf8\uc158",level:3},{value:"1, 2\ub2e8\uacc4",id:"1-2\ub2e8\uacc4",level:3},{value:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c",id:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758-\ubcf5\uc7a1\uc131\uc744-\ub2e4\ub8e8\ub294-\uc9c0\ud61c",level:3},{value:"3, 4\ub2e8\uacc4",id:"3-4\ub2e8\uacc4",level:3},{value:"\ub9c8\ubb34\ub9ac",id:"\ub9c8\ubb34\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,n.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/465",children:"https://github.com/woowacourse/jwp-refactoring/pull/465"}),(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/547",children:"https://github.com/woowacourse/jwp-refactoring/pull/547"}),(0,n.jsx)(r.br,{}),"\n","3\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/610",children:"https://github.com/woowacourse/jwp-refactoring/pull/610"}),(0,n.jsx)(r.br,{}),"\n","4\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-refactoring/pull/721",children:"https://github.com/woowacourse/jwp-refactoring/pull/721"})]})}),"\n",(0,n.jsx)(r.h3,{id:"\ub9ac\ud329\ud130\ub9c1-\ubbf8\uc158",children:"\ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["\uc694\uad6c\uc0ac\ud56d \uc791\uc131 \u2192 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud55c \ucf54\ub4dc \ubcf4\ud638 \u2192 \ub9ac\ud329\ud130\ub9c1 \u2192 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1 \u2192 \uba40\ud2f0\ubaa8\ub4c8 \uc21c\uc11c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc5d0 \uc628\uc804\ud788 \uc9d1\uc911\ud558\uace0 \uc2f6\uc5c8\uc9c0\ub9cc, \ud504\ub85c\uc81d\ud2b8\uc640 \ubcd1\ud589\ud558\uba74\uc11c \uc9c4\ud589\ud588\uae30\uc5d0 \uc5b4\ub290\uc815\ub3c4 \ud0c0\ud611\ubcf4\uace0 \uc9c4\ud589\ud55c \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c \uc544\uc26c\uc6e0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"1-2\ub2e8\uacc4",children:"1, 2\ub2e8\uacc4"}),"\n",(0,n.jsx)(r.p,{children:"1\ub2e8\uacc4\ub294 \uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud558\uace0, \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ucd94\ud6c4\uc5d0 \ub9ac\ud329\ud130\ub9c1 \ud560 \ub54c \uc548\uc815\uac10 \uc788\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\ub3c4\ub85d \uc900\ube44\ud558\ub294 \uacfc\uc815\uc774\uc5c8\ub2e4.\n\uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud560 \ub54c \uc81c\uacf5\ub41c \uc6a9\uc5b4 \uc0ac\uc804\uc744 \ucd5c\ub300\ud55c \ud65c\uc6a9\ud558\uba74\uc11c \uae30\uc874\uc758 \ucf54\ub4dc\ub97c \ubcf4\uba74\uc11c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud588\ub2e4.\n\ud14c\uc2a4\ud2b8\ub294 \uc2dc\uac04 \uad00\uacc4\uc0c1 API, \uc11c\ube44\uc2a4 \ub458 \uc911 \ud558\ub098\ub9cc \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4."}),"\n",(0,n.jsxs)(r.p,{children:["\ucd5c\uc885\uc801\uc73c\ub85c \uc11c\ube44\uc2a4 \uae30\uc900\uc73c\ub85c \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud588\ub294\ub370 \uc57d\uac04 \ud6c4\ud68c\ub418\ub294 \uacb0\uc815\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub9ac\ud329\ud130\ub9c1 \uacfc\uc815\uc5d0\uc11c API \uba85\uc138\uac00 \ubc14\ub00c\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4\ub294 \uac83\uc744 \uae30\uc900\uc744 \uc7a1\uace0 \uc774\ubc88 \ubbf8\uc158\uc744 \ud55c\ub2e4\uace0 \uac00\uc815\ud588\uc744 \ub54c API \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\uace0, \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ub354 \uc548\uc815\uac10 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["2\ub2e8\uacc4\ub294 \uc791\uc131\ub41c \ud14c\uc2a4\ud2b8 \uae30\ubc18\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc11c\ube44\uc2a4\uc5d0\uc11c \ub3c4\uba54\uc778\uc744 \uc9c1\uc811 \ubc18\ud658\ud558\ub294 \uad6c\uc870\uc600\ub294\ub370, \ub3c4\uba54\uc778\uc5d0 JPA\ub97c \uc801\uc6a9\ud558\uba74 \uae30\uc874 \uba85\uc138\uc640 \ub2ec\ub77c\uc9c8 \uac83\uc744 \uc6b0\ub824\ud574\uc11c DTO\ub85c \uc218\uc815\ud558\ub294 \uc791\uc5c5\uc744 \uba3c\uc800 \uc9c4\ud589\ud588\ub2e4.\nDTO \uc774\ud6c4\uc5d0 \uc11c\ube44\uc2a4\uc5d0 \uc788\ub294 \ub85c\uc9c1\uc744 \ub3c4\uba54\uc778\uc73c\ub85c \uc774\ub3d9\uc2dc\ud0a4\uace0, \ucd5c\uc885\uc801\uc73c\ub85c JPA\ub97c \uc801\uc6a9\ud558\ub294 \uc21c\uc11c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud588\ub2e4.\n\uc774 \uacfc\uc815\uc5d0\uc11c \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \uc591\ubc29\ud5a5\uc778 \ubd80\ubd84\ub3c4 \uc0dd\uaca8\ub0ac\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758-\ubcf5\uc7a1\uc131\uc744-\ub2e4\ub8e8\ub294-\uc9c0\ud61c",children:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c"}),"\n",(0,n.jsxs)(r.p,{children:["\uc911\uac04\uc5d0 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\uc5d0 \uad00\ud55c \uc81c\uc774\uc2a8\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\ub294 \uc5d0\ub9ad \uc5d0\ubc18\uc2a4\uc758 \uc800\uc11c ",(0,n.jsx)(r.code,{children:"\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4"}),"\uc758 \ubd80\uc81c\uc774\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\ub294 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4, \uc804\uc220\uc801 \uc124\uacc4\uac00 \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4\uac00 \uc804\uccb4\uc758 90%\uc5d0 \ud574\ub2f9\ud560 \uc815\ub3c4\ub85c \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4. \ub610\ud55c \uc804\uc220\uc801 \uc124\uacc4\ub9cc \ud558\ub294 \uacbd\uc6b0\ub97c DDD Lite \ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\uac04\ub2e8\ud788 \ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\uc5d0\uc11c \ub098\uc624\ub294 \ub2e8\uc5b4\ub97c \uc815\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,n.jsxs)(r.table,{children:[(0,n.jsx)(r.thead,{children:(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.th,{children:"\ub2e8\uc5b4"}),(0,n.jsx)(r.th,{children:"\uc124\uba85"})]})}),(0,n.jsxs)(r.tbody,{children:[(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\ub3c4\uba54\uc778"}),(0,n.jsx)(r.td,{children:"\uc18c\ud504\ud2b8\uc6e8\uc5b4\ub85c \ud574\uacb0\ud558\uace0\uc790 \ud558\ub294 \ubb38\uc81c \uc601\uc5ed"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8"}),(0,n.jsx)(r.td,{children:"\ud574\uacb0 \uc601\uc5ed, \uad00\uc2ec\uc0ac\ub97c \ubd84\ub9ac\ud558\uace0 \uaca9\ub9ac\ud558\uc5ec \ubb38\uc81c \ud574\uacb0\uc5d0 \uc9d1\uc911\ud560 \ubc94\uc704"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4"}),(0,n.jsx)(r.td,{children:"\ud504\ub85c\uc81d\ud2b8\uc5d0 \uc774\ud574\uad00\uacc4\uc790\ub4e4\uc758 \uacf5\ud1b5\ub41c \uc5b8\uc5b4\ub85c, \uc11c\ub85c\uc758 \uc758\uc0ac\uc18c\ud1b5 \ube44\uc6a9\uc744 \uc904\uc774\uae30 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 \uc5b8\uc5b4"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc804\ub7b5\uc801 \uc124\uacc4"}),(0,n.jsx)(r.td,{children:"\ub3c4\uba54\uc778 \uc804\ubb38\uac00\uc640 \uac1c\ubc1c\uc790\uac00 \ud568\uaed8 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec \ub3c4\uba54\uc778\uacfc \uad00\ub828\ub41c \uc9c0\uc2dd\uc744 \uc774\ud574\ud558\uace0 \uc774\ub97c \ubc14\ud0d5\uc73c\ub85c \uacbd\uacc4\ub97c \ub098\ub220 \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc815\uc758\ud558\uace0, \ucee8\ud14d\uc2a4\ud2b8 \ub9f5\uc744 \uc0dd\uc131\ud558\ub294 \uac83\uc744 \ud3ec\ud568\ud558\ub294 \uacfc\uc815"})]}),(0,n.jsxs)(r.tr,{children:[(0,n.jsx)(r.td,{children:"\uc804\uc220\uc801 \uc124\uacc4"}),(0,n.jsx)(r.td,{children:"\uc804\ub7b5\uc801 \uc124\uacc4\uc5d0\uc11c \uc815\uc758\ud55c \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\uc640 \ub3c4\uba54\uc778\uc744 \uc774\uc6a9\ud558\uc5ec \uc560\uadf8\ub9ac\uac70\ud2b8, Entity\uc640 VO, Repository \ub4f1\uc744 \uad6c\ud604\ud558\ub294 \uacfc\uc815"})]})]})]}),"\n",(0,n.jsx)(r.p,{children:"\uc774 \uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ub0b4\uc6a9\ub4e4\uc774 \ub098\uc654\uc9c0\ub9cc, \uc9c0\uc2dd\uc744 \uc81c\ub300\ub85c \ud761\uc218\ud558\uc9c0\ub294 \ubabb\ud588\ub2e4."}),"\n",(0,n.jsx)(r.h3,{id:"3-4\ub2e8\uacc4",children:"3, 4\ub2e8\uacc4"}),"\n",(0,n.jsx)(r.p,{children:"\uc81c\uc774\uc2a8\uc758 \uac15\uc758\ub97c \ub4e3\uace0, \uc870\uc601\ud638\ub2d8\uc758 \uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5 \uc720\ud29c\ube0c \uc601\uc0c1\uc744 \ubcf8 \ub2e4\uc74c 3, 4\ub2e8\uacc4\ub97c \uc9c4\ud589\ud588\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:"3\ub2e8\uacc4\ub294 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1\uc5d0 \uad00\ud55c \ub0b4\uc6a9\uc774\uc5c8\ub2e4. \ud074\ub798\uc2a4 \uac04 \ubc29\ud5a5, \ud328\ud0a4\uc9c0 \uac04 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc774 \ub418\ub3c4\ub85d \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud574\uc57c \ud588\uc5c8\ub2e4.\n\ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4\ub4e4\uc744 \ubb36\uace0, \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uae30 \uc704\ud574 \uc0dd\uba85\uc8fc\uae30\uac00 \ub2e4\ub974\ub2e4\uba74 id\ub97c \uc774\uc6a9\ud558\uc5ec \ucc38\uc870\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:"\uc758\uc874\uc131\uc744 \ubd84\ub9ac\ud558\uae30 \uc704\ud574 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4. \uc774\ubca4\ud2b8\ub294 \ud604\uc7ac \uae30\uc900\uc73c\ub85c \uacfc\uac70\uc5d0 \ubc8c\uc5b4\uc9c4 \uac83\uc744 \ud45c\ud604\ud558\uae30 \ub54c\ubb38\uc5d0 \uc774\ubca4\ud2b8\uba85\uc740 \uacfc\uac70 \uc2dc\uc81c\uac00 \ub418\uc5b4\uc57c\ud558\ub294 \uac83\uc744 \uc54c\uc558\ub2e4.\n\ucc98\uc74c\uc5d0\ub294 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud588\uc9c0\ub9cc, \uc11c\ube44\uc2a4 \ub85c\uc9c1\uc744 \ucd5c\ub300\ud55c \uac04\ub2e8\ud558\uac8c \ud558\uae30 \uc704\ud574 \ub3c4\uba54\uc778 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4."}),"\n",(0,n.jsxs)(r.p,{children:["4\ub2e8\uacc4\ub294 \uba40\ud2f0\ubaa8\ub4c8\ub85c \ubd84\ub9ac\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub294\ub370 3\ub2e8\uacc4\uc5d0\uc11c \ubd84\ub9ac\ud574\ub454 \ud328\ud0a4\uc9c0 \uadf8\ub300\ub85c \ubd84\ub9ac\ud558\uc9c0\ub294 \uc54a\uc558\ub2e4.",(0,n.jsx)(r.br,{}),"\n","3\ub2e8\uacc4\uc5d0\uc11c\ub294 \ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4 \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ud588\ub2e4. 4\ub2e8\uacc4\uc5d0\uc11c\ub294 \ub0b4\uac00 \uc778\uc2dd\ud558\uae30 \ud3b8\ud55c \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ub97c \ud588\ub2e4.\n\uc544\uc9c1 \ubd84\ub9ac\ud55c \uae30\uc900\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \ubaa8\ud638\ud588\uace0, \uc774\uc5d0 \ub300\ud55c \uacf5\ubd80\ub97c \uc870\uae08 \ub354 \ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.mermaid,{value:"graph LR\n\tsubgraph Table\n\t\tOrderTable --\x3e TableGroup\n\tend\n\tsubgraph Order\n\t\tO\n\tend\n O[Order] --\x3e OrderTable\n\tsubgraph Menu\n\t\tM[Menu] --\x3e MenuGroup\n\t\tM --\x3e Product\n\tend\n\tO --\x3e M"}),"\n",(0,n.jsxs)(r.p,{children:["\ucd94\uac00\ub85c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc704\ud55c \uc9c1\uc811 \uc791\uc131\ud55c ",(0,n.jsx)(r.code,{children:"@ServiceTest"})," \ucee4\uc2a4\ud140 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc788\uc5c8\ub294\ub370, \uc0c1\uc704 \ubaa8\ub4c8\uc758 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \ub9cc\ub4e0 \ud074\ub798\uc2a4\ub97c \ud558\uc704 \ubaa8\ub4c8\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4.\n\ub530\ub77c\uc11c TestFixtures\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\uacb0\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ub9c8\ubb34\ub9ac",children:"\ub9c8\ubb34\ub9ac"}),"\n",(0,n.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc758 \ub9c8\uc9c0\ub9c9 \ubbf8\uc158\uc774\ub2c8 \ub9cc\ud07c, \uac00\uc7a5 \ud765\ubbf8\ub85c\uc6b4 \ubbf8\uc158\uc774\uc5c8\uace0 \ubc30\uc6b8\uc810\ub3c4 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc14\uc05c \uae30\uac04\uc774\ub77c \ub9ce\uc740 \ub9ac\ubdf0\ub97c \ub0a8\uae30\uc9c0 \ubabb\ud588\ub358 \ub9ac\ubdf0\uc774 \ud638\uc774\uc5d0\uac8c \ubbf8\uc548\ud558\uace0, \ucf54\uba58\ud2b8 \uaf3c\uaf3c\ud558\uac8c \ub2ec\uc544\uc8fc\uace0 \ubbf8\uc158\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub3c4 \uc624\ud504\ub77c\uc778\uc73c\ub85c \ub9ce\uc774 \ub098\ub208 \ub9ac\ubdf0\uc5b4 \ud14c\uc624\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,n.jsxs)(r.p,{children:[(0,n.jsx)(r.a,{href:"https://www.youtube.com/watch?v=kmUneexSxk0",children:"\ub3c4\uba54\uc778 \uc6d0\uc815\ub300, \uc6b0\uc544\ucf58 2021"}),(0,n.jsx)(r.br,{}),"\n",(0,n.jsx)(r.a,{href:"https://www.youtube.com/watch?v=dJ5C4qRqAgA",children:"\uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5, \uc6b0\uc544\ud55c\ud14c\ud06c\uc138\ubbf8\ub098"}),(0,n.jsx)(r.br,{}),"\n",(0,n.jsx)(r.a,{href:"https://kwonnam.pe.kr/wiki/gradle/testfixtures",children:"TestFixtures, \uad8c\ub0a8\ub2d8"})]})]})}function h(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>a});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=n.createContext({}),a=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},d={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},h=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,h=o(e,["components","mdxType","originalType","parentName"]),p=a(t),u=s,j=p["".concat(l,".").concat(u)]||p[u]||d[u]||i;return t?n.createElement(j,c(c({ref:r},h),{},{components:t})):n.createElement(j,c({ref:r},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/537817cb.65f6a412.js b/assets/js/537817cb.910a967a.js similarity index 95% rename from assets/js/537817cb.65f6a412.js rename to assets/js/537817cb.910a967a.js index 6baef2c16..1f8d87628 100644 --- a/assets/js/537817cb.65f6a412.js +++ b/assets/js/537817cb.910a967a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3457],{75088:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var r=n(85893),a=n(3905);const l={title:"JSR-310",slug:"jsr-310",tags:["Java","Time"]},i=void 0,o={permalink:"/jsr-310",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-08-JSR-310.mdx",source:"@site/blog/2023-1/2023-01-08-JSR-310.mdx",title:"JSR-310",description:"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API",date:"2023-01-08T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 8\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Time",permalink:"/tags/time"}],readingTime:1.685,hasTruncateMarker:!1,authors:[],frontMatter:{title:"JSR-310",slug:"jsr-310",tags:["Java","Time"]},unlisted:!1,prevItem:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",permalink:"/kotlin-null"},nextItem:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",permalink:"/the-essence-of-object-orientation"}},s={authorsImageUrls:[]},c=[{value:"LocalDate, LocalTime, LocalDateTime",id:"localdate-localtime-localdatetime",level:3},{value:"Instant",id:"instant",level:3},{value:"Duration, Period",id:"duration-period",level:3},{value:"TemporalAdjusters",id:"temporaladjusters",level:3},{value:"DateTimeFormatter",id:"datetimeformatter",level:3},{value:"ZoneId, ZoneOffset",id:"zoneid-zoneoffset",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API",(0,r.jsx)(t.br,{}),"\n","ISO-8601\uc744 \uae30\ubc18\uc73c\ub85c \uc791\uc131",(0,r.jsx)(t.br,{}),"\n","\uc124\uacc4 \ubaa9\ud45c \u2192 \ubd88\ubcc0, Fluent API, \uba85\ud655\ud558\uace0 \uba85\uc2dc\uc801, \ud655\uc7a5 \uac00\ub2a5\uc131"]}),"\n",(0,r.jsx)(t.admonition,{title:"ISO-8601",type:"note",children:(0,r.jsx)(t.p,{children:"\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc5d0 \uad00\ub828\ub41c \ub370\uc774\ud130\ub97c \ub2e4\ub8e8\ub294 \uad6d\uc81c \ud45c\uc900"})}),"\n",(0,r.jsx)(t.h3,{id:"localdate-localtime-localdatetime",children:"LocalDate, LocalTime, LocalDateTime"}),"\n",(0,r.jsx)(t.p,{children:"\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4"}),"\n",(0,r.jsx)(t.h3,{id:"instant",children:"Instant"}),"\n",(0,r.jsxs)(t.p,{children:["\uc720\ub2c9\uc2a4 \uc2dc\uac04(1970-01-01, 00:00:00 UTC) \uae30\uc900\uc73c\ub85c \ud2b9\uc815 \uc9c0\uc810\uae4c\uc9c0\uc758 \uc2dc\uac04\uc744 \ucd08\ub85c \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4",(0,r.jsx)(t.br,{}),"\n","\uae30\uacc4\uc758 \uad00\uc810\uc5d0\uc11c \uc2dc\uac04 \ud45c\ud604"]}),"\n",(0,r.jsx)(t.h3,{id:"duration-period",children:"Duration, Period"}),"\n",(0,r.jsx)(t.p,{children:"\uac04\uaca9\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4"}),"\n",(0,r.jsx)(t.h3,{id:"temporaladjusters",children:"TemporalAdjusters"}),"\n",(0,r.jsxs)(t.p,{children:["\ubcf5\uc7a1\ud55c \ub0a0\uc9dc \uc870\uc815\uc774 \ud544\uc694\ud560 \ub54c \uc0ac\uc6a9",(0,r.jsx)(t.br,{}),"\n","\ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uc5ec \ucee4\uc2a4\ud140 TemporalAdjuster\ub97c \uad6c\ud604 \uac00\ub2a5"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"@FunctionalInterface\npublic interface TemporalAdjuster {\n Temporal adjustInto(Temporal temporal);\n}\n"})}),"\n",(0,r.jsx)(t.h3,{id:"datetimeformatter",children:"DateTimeFormatter"}),"\n",(0,r.jsxs)(t.p,{children:["\ub0a0\uc9dc\uc640 \uc2dc\uac04 \ud3ec\ub9f7 \ud074\ub798\uc2a4",(0,r.jsx)(t.br,{}),"\n","\ud2b9\uc815 \ub0a0\uc9dc \ud328\ud134\uc774\ub098, DateTimeFormatterBuilder\ub97c \uc774\uc6a9\ud574\uc11c \ucee4\uc2a4\ud140\ud55c \ud3ec\ub9f7\uc744 \uc0dd\uc131 \uac00\ub2a5"]}),"\n",(0,r.jsx)(t.h3,{id:"zoneid-zoneoffset",children:"ZoneId, ZoneOffset"}),"\n",(0,r.jsxs)(t.p,{children:["ZoneId\ub294 \uc9c0\uc5ed ID\ub294 ",(0,r.jsx)(t.code,{children:"\u2018\uc9c0\uc5ed/\ub3c4\uc2dc\u2019"})," \ud615\uc2dd, ZoneOffset\uc740 \uc2dc\ucc28 UTC \uae30\uc900 \uace0\uc815\ub41c \uc2dc\uac04 \ucc28\uc774 \uc774\uc6a9",(0,r.jsx)(t.br,{}),"\n","ZoneId\uc758 \uacbd\uc6b0 IANA Time Zone Database\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc9c0\uc5ed \uc9d1\ud569 \uc815\ubcf4 \uc0ac\uc6a9"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"Instant instant = Instant.now();\nLocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);\n"})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://product.kyobobook.co.kr/detail/S000001810171",children:"\ubaa8\ub358 \uc790\ubc14 \uc778 \uc561\uc158"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://d2.naver.com/helloworld/645609",children:"Java\uc758 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://www.w3.org/TR/NOTE-datetime",children:"ISO-8601"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://download.oracle.com/otn-pub/jcp/date_time-0.2-edr-oth-JSpec/date_time-0_2-edr-spec.pdf?AuthParam=1673171124_74a718be92efe4911c6977c02965aff4",children:"JSR-310 Spec"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://www.baeldung.com/java-temporal-adjuster",children:"Temporal Adjuster"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html",children:"DateTimeFormatter"})}),"\n"]})]})}function m(e={}){const{wrapper:t}={...(0,a.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),p=c(n),u=a,h=p["".concat(s,".").concat(u)]||p[u]||d[u]||l;return n?r.createElement(h,i(i({ref:t},m),{},{components:n})):r.createElement(h,i({ref:t},m))}));m.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3457],{75088:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var r=n(85893),a=n(3905);const l={title:"JSR-310",slug:"jsr-310",tags:["Java","Time"]},i=void 0,o={permalink:"/jsr-310",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-08-JSR-310.mdx",source:"@site/blog/2023-1/2023-01-08-JSR-310.mdx",title:"JSR-310",description:"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API",date:"2023-01-08T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 8\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Time",permalink:"/tags/time"}],readingTime:1.685,hasTruncateMarker:!1,authors:[],frontMatter:{title:"JSR-310",slug:"jsr-310",tags:["Java","Time"]},unlisted:!1,prevItem:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",permalink:"/the-essence-of-object-orientation"},nextItem:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",permalink:"/kotlin-null"}},s={authorsImageUrls:[]},c=[{value:"LocalDate, LocalTime, LocalDateTime",id:"localdate-localtime-localdatetime",level:3},{value:"Instant",id:"instant",level:3},{value:"Duration, Period",id:"duration-period",level:3},{value:"TemporalAdjusters",id:"temporaladjusters",level:3},{value:"DateTimeFormatter",id:"datetimeformatter",level:3},{value:"ZoneId, ZoneOffset",id:"zoneid-zoneoffset",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API",(0,r.jsx)(t.br,{}),"\n","ISO-8601\uc744 \uae30\ubc18\uc73c\ub85c \uc791\uc131",(0,r.jsx)(t.br,{}),"\n","\uc124\uacc4 \ubaa9\ud45c \u2192 \ubd88\ubcc0, Fluent API, \uba85\ud655\ud558\uace0 \uba85\uc2dc\uc801, \ud655\uc7a5 \uac00\ub2a5\uc131"]}),"\n",(0,r.jsx)(t.admonition,{title:"ISO-8601",type:"note",children:(0,r.jsx)(t.p,{children:"\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc5d0 \uad00\ub828\ub41c \ub370\uc774\ud130\ub97c \ub2e4\ub8e8\ub294 \uad6d\uc81c \ud45c\uc900"})}),"\n",(0,r.jsx)(t.h3,{id:"localdate-localtime-localdatetime",children:"LocalDate, LocalTime, LocalDateTime"}),"\n",(0,r.jsx)(t.p,{children:"\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4"}),"\n",(0,r.jsx)(t.h3,{id:"instant",children:"Instant"}),"\n",(0,r.jsxs)(t.p,{children:["\uc720\ub2c9\uc2a4 \uc2dc\uac04(1970-01-01, 00:00:00 UTC) \uae30\uc900\uc73c\ub85c \ud2b9\uc815 \uc9c0\uc810\uae4c\uc9c0\uc758 \uc2dc\uac04\uc744 \ucd08\ub85c \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4",(0,r.jsx)(t.br,{}),"\n","\uae30\uacc4\uc758 \uad00\uc810\uc5d0\uc11c \uc2dc\uac04 \ud45c\ud604"]}),"\n",(0,r.jsx)(t.h3,{id:"duration-period",children:"Duration, Period"}),"\n",(0,r.jsx)(t.p,{children:"\uac04\uaca9\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4"}),"\n",(0,r.jsx)(t.h3,{id:"temporaladjusters",children:"TemporalAdjusters"}),"\n",(0,r.jsxs)(t.p,{children:["\ubcf5\uc7a1\ud55c \ub0a0\uc9dc \uc870\uc815\uc774 \ud544\uc694\ud560 \ub54c \uc0ac\uc6a9",(0,r.jsx)(t.br,{}),"\n","\ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uc5ec \ucee4\uc2a4\ud140 TemporalAdjuster\ub97c \uad6c\ud604 \uac00\ub2a5"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"@FunctionalInterface\npublic interface TemporalAdjuster {\n Temporal adjustInto(Temporal temporal);\n}\n"})}),"\n",(0,r.jsx)(t.h3,{id:"datetimeformatter",children:"DateTimeFormatter"}),"\n",(0,r.jsxs)(t.p,{children:["\ub0a0\uc9dc\uc640 \uc2dc\uac04 \ud3ec\ub9f7 \ud074\ub798\uc2a4",(0,r.jsx)(t.br,{}),"\n","\ud2b9\uc815 \ub0a0\uc9dc \ud328\ud134\uc774\ub098, DateTimeFormatterBuilder\ub97c \uc774\uc6a9\ud574\uc11c \ucee4\uc2a4\ud140\ud55c \ud3ec\ub9f7\uc744 \uc0dd\uc131 \uac00\ub2a5"]}),"\n",(0,r.jsx)(t.h3,{id:"zoneid-zoneoffset",children:"ZoneId, ZoneOffset"}),"\n",(0,r.jsxs)(t.p,{children:["ZoneId\ub294 \uc9c0\uc5ed ID\ub294 ",(0,r.jsx)(t.code,{children:"\u2018\uc9c0\uc5ed/\ub3c4\uc2dc\u2019"})," \ud615\uc2dd, ZoneOffset\uc740 \uc2dc\ucc28 UTC \uae30\uc900 \uace0\uc815\ub41c \uc2dc\uac04 \ucc28\uc774 \uc774\uc6a9",(0,r.jsx)(t.br,{}),"\n","ZoneId\uc758 \uacbd\uc6b0 IANA Time Zone Database\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc9c0\uc5ed \uc9d1\ud569 \uc815\ubcf4 \uc0ac\uc6a9"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"Instant instant = Instant.now();\nLocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);\n"})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://product.kyobobook.co.kr/detail/S000001810171",children:"\ubaa8\ub358 \uc790\ubc14 \uc778 \uc561\uc158"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://d2.naver.com/helloworld/645609",children:"Java\uc758 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://www.w3.org/TR/NOTE-datetime",children:"ISO-8601"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://download.oracle.com/otn-pub/jcp/date_time-0.2-edr-oth-JSpec/date_time-0_2-edr-spec.pdf?AuthParam=1673171124_74a718be92efe4911c6977c02965aff4",children:"JSR-310 Spec"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://www.baeldung.com/java-temporal-adjuster",children:"Temporal Adjuster"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html",children:"DateTimeFormatter"})}),"\n"]})]})}function m(e={}){const{wrapper:t}={...(0,a.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),p=c(n),u=a,h=p["".concat(s,".").concat(u)]||p[u]||d[u]||l;return n?r.createElement(h,i(i({ref:t},m),{},{components:n})):r.createElement(h,i({ref:t},m))}));m.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/5a473bed.c534c8ad.js b/assets/js/5a473bed.0629687d.js similarity index 98% rename from assets/js/5a473bed.c534c8ad.js rename to assets/js/5a473bed.0629687d.js index 46e5e912a..477cea354 100644 --- a/assets/js/5a473bed.c534c8ad.js +++ b/assets/js/5a473bed.0629687d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9686],{52857:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var t=r(85893),a=r(3905);const l={title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"mvc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,o={permalink:"/mvc-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-mvc/pull/404",date:"2023-10-07T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 7\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.175,hasTruncateMarker:!1,authors:[],frontMatter:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"mvc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/jdbc-retrospective"},nextItem:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",permalink:"/spring-test-isolation"}},s={authorsImageUrls:[]},c=[{value:"MVC \uad6c\ud604",id:"mvc-\uad6c\ud604",level:3},{value:"\uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30",id:"\uc560\ub108\ud14c\uc774\uc158-\uae30\ubc18-\ud504\ub808\uc784\uc6cc\ud06c-\ub9cc\ub4e4\uae30",level:3},{value:"Legacy MVC\uc640 @MVC \ud1b5\ud569",id:"legacy-mvc\uc640-mvc-\ud1b5\ud569",level:3},{value:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",level:3},{value:"\ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95",id:"\ucd94\uc0c1\uc801\uc778-\uac1c\ub150-\ud559\uc2b5-\ubc29\ubc95",level:3},{value:"\uc815\ub9ac",id:"\uc815\ub9ac",level:3}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/404",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/404"}),(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/465",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/465"}),(0,t.jsx)(n.br,{}),"\n","3\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/580",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/580"})]})}),"\n",(0,t.jsx)(n.h3,{id:"mvc-\uad6c\ud604",children:"MVC \uad6c\ud604"}),"\n",(0,t.jsxs)(n.p,{children:["Reflection\uc744 \uc774\uc6a9\ud558\uc5ec Spring MVC\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubbf8\uc158\uc758 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\uc558\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"MVC \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uad6c\ud604\ud558\uba74\uc11c \ub0b4\ubd80 \ub3d9\uc791 \uc6d0\ub9ac\ub97c \ud559\uc2b5\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc810\uc9c4\uc801\uc778 \ub9ac\ud329\ud1a0\ub9c1\uc744 \uacbd\ud5d8\ud55c\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ubbf8\uc158\uc758 \ubaa9\ud45c\uc640 \ub354\ubd88\uc5b4 \uac01 \ud074\ub798\uc2a4\ub4e4\uc774 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \uc801\uc808\ud788 \uac00\uc9c0\ub3c4\ub85d \ud558\uace0, \ud328\ud0a4\uc9c0\uc758 \uc758\uc874 \ubc29\ud5a5\uc744 \uace0\ubbfc\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc5d0 \uc911\uc810\uc744 \ub450\uc5c8\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"\uc560\ub108\ud14c\uc774\uc158-\uae30\ubc18-\ud504\ub808\uc784\uc6cc\ud06c-\ub9cc\ub4e4\uae30",children:"\uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uae30\uc874 \ucf54\ub4dc\uc5d0 ManualHandlerMapping\uc774\ub77c\ub294 \uc11c\ube14\ub9bf\uc744 \uc9c1\uc811 \ub4f1\ub85d\ud574\uc11c \uc0ac\uc6a9\ud558\ub294 HandlerMapping \ud074\ub798\uc2a4\uac00 \uc788\uc5c8\uace0, 1\ub2e8\uacc4\uc5d0\uc11c\ub294 \uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18\uc758 AnnotationHandlerMapping\uc744 \uad6c\ud604\ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 @Controller, @RequestMapping\uc744 Reflection\uc744 \uc774\uc6a9\ud558\uc5ec \uc2a4\uce94\ud558\uace0, \ud578\ub4e4\ub7ec \ub9e4\ud551\uc744 \ub4f1\ub85d\ud558\ub294 \ubd80\ubd84\uae4c\uc9c0 \uc9c4\ud589\ud574\uc57c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud14c\uc624\uac00 @GetMapping\uc774\ub098 @PostMapping \ubd80\ubd84\ub3c4 \uc9c4\ud589\ud558\uba74 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4\uace0 \ud574\uc11c \uac19\uc774 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ubbf8\uc158 \uc694\uad6c\uc0ac\ud56d\uc740 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ud074\ub798\uc2a4 \ub808\ubca8\uc5d0 \uc801\uc6a9\ub41c @RequestMapping\ub3c4 \ub3d9\uc791\ud558\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\uc558\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n AHM[AnnotationHandlerMapping] --\x3e AS[AnnotationScanner]\n\tAHM --\x3e HKG[HandlerKeyGenerator] --\x3e HMAP[HttpMappingAnnotationParser]"}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc740 Flow\ub85c Handler(\uc2e4\uc81c \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uba54\uc11c\ub4dc) \ub4f1\ub85d\uc744 \uc9c4\ud589\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"@Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 \uc815\ubcf4\ub97c \uc2a4\uce94\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"@Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 @RequestMapping\uc774 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\ub4e4\uc758 \uc815\ubcf4\ub97c \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:["\uac01 \uba54\uc11c\ub4dc\ub4e4\uc744 \uc21c\ud68c\ud558\uba70 HandlerKey(uri + httpMethod \uc815\ubcf4)\uc640 HandlerExecution(\uc778\uc2a4\ud134\uc2a4 + \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc)\uc744 \uc0dd\uc131\ud558\uc5ec ",(0,t.jsx)(n.code,{children:"Map"}),"\uc5d0 \ucd94\uac00\ud55c\ub2e4."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"AnnotationHandlerMapping\uc758 initialize \uba54\uc11c\ub4dc\uc5d0\uc11c Handler\ub97c \ub4f1\ub85d\ud55c\ub2e4. \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AnnotationHandlerMapping",children:'public void initialize() {\n if (!initialized.compareAndSet(false, true)) {\n return;\n }\n\n final Map, ControllerInstance> controllers = annotationScanner.scanControllers();\n final Set methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());\n for (final Method method : methods) {\n final ControllerInstance controller = controllers.get(method.getDeclaringClass());\n final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);\n final List handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);\n handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));\n }\n\n log.info("Initialized AnnotationHandlerMapping!");\n handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"legacy-mvc\uc640-mvc-\ud1b5\ud569",children:"Legacy MVC\uc640 @MVC \ud1b5\ud569"}),"\n",(0,t.jsxs)(n.p,{children:["2\ub2e8\uacc4\ub294 Legacy MVC\uc640 AnnotationHandlerMapping\uc744 \ud1b5\ud569\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 MVC\uc640 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc801\uc6a9\ub41c MVC \ub450 \uac1c\ub97c \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5b4\uc57c \ud5c0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub300\ub7b5\uc801\uc778 \ud750\ub984\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"DispatcherServlet.service(request, response) \ud638\ucd9c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerMappings\ub97c \ud1b5\ud574 \uc785\ub825\ubc1b\uc740 request\uc5d0 \ud574\ub2f9\ud558\ub294 Handler \uc870\ud68c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerAdapters\ub97c \ud1b5\ud574 Handler\ub97c \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub294 HandlerAdapter \uc870\ud68c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerAdapter\uc758.handle \uba54\uc11c\ub4dc \uc2e4\ud589"}),"\n",(0,t.jsx)(n.li,{children:"View\uc758 render \ud638\ucd9c"}),"\n"]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n D[DispatcherServlet]\n D --\x3e HMS[HandlerMappings]\n D --\x3e HAS[HandlerAdapters]\n\n\tHMS --\x3e HandlerMapping\n\tsubgraph HandlerMapping\n\t\tdirection BT\n\t\tAHM[AnnotationHandlerMapping] --\x3e HM[HandlerMapping]\n\t\tMHM[ManualHandlerMapping] --\x3e HM\n\tend\n\n\tHAS --\x3e HandlerAdapter\n\tsubgraph HandlerAdapter\n\t\tdirection BT\n\t\tHEHA[HandlerExecutionHandlerAdapter] --\x3e HA[HandlerAdapter]\n\t\tCHA[ControllerHandlerAdapter] --\x3e HA\n\tend"}),"\n",(0,t.jsx)(n.h3,{id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",children:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking"}),"\n",(0,t.jsxs)(n.p,{children:["\ub0b4\uc6a9\uc774 \uae38\uc5b4\uc838\uc11c ",(0,t.jsx)(n.a,{href:"./web-application-evolution",children:"\ub2e4\uc74c \ubb38\uc11c"}),"\uc5d0 \uc815\ub9ac\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucd94\uc0c1\uc801\uc778-\uac1c\ub150-\ud559\uc2b5-\ubc29\ubc95",children:"\ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.p,{children:"\uc9c1\uad00\uc801\uc774\uc9c0 \uc54a\uc740 \ucd94\uc0c1\uc801\uc778 \uac1c\ub150\uc744 \ud559\uc2b5\ud560 \ub54c\ub294 \uac1c\ub150\uc758 \uad6c\ud604\uc744 \ucc38\uace0\ud558\uba74 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"\uac1c\ub150"}),(0,t.jsx)(n.th,{children:"\uad6c\ud604"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"OOP"}),(0,t.jsx)(n.td,{children:"Java"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"WAS"}),(0,t.jsx)(n.td,{children:"Tomcat, Jetty"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"IoC"}),(0,t.jsx)(n.td,{children:"Spring BeanFactory, Servlet Container, Framework"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"DI"}),(0,t.jsx)(n.td,{children:"Spring BeanFactory"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"\uc815\ub9ac",children:"\uc815\ub9ac"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c0\uae08\uae4c\uc9c0 \uc2a4\ud504\ub9c1\uc758 DispatcherServlet\uc758 \ub3d9\uc791\uc744 \uc774\ub860\uc801\uc73c\ub85c\ub9cc \uc54c\uace0 \uc788\uc5c8\ub294\ub370, \uc2e4\uc81c\ub85c \uad6c\ud604\ud574 \ubcf4\ub2c8 \uc870\uae08 \ub354 \uc774\ud574\uac00 \uc798 \uac00\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c \ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub8e8\uce74, \ub9ac\ubdf0\uc774\ub294 \ud5e4\ub098\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9e4 \ub2e8\uacc4\ub9c8\ub2e4 \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0\ud574 \uc900 \ub8e8\uce74\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\uace0, \ud5e4\ub098\uc5d0\uac8c \uc774\uc0c1\ud55c \ub9ac\ubdf0\ub97c \ub9ce\uc774 \ub0a8\uae34 \uac83 \uac19\uc740\ub370 \uaf3c\uaf3c\ud788 \ubc18\uc601\ud574\uc918\uc11c \uac10\uc0ac\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub7ab\ub3d9\uc548 \uae30\ub2e4\ub824\uc654\ub358 \ub808\ubca8 4 \ubbf8\uc158\uc774 \ud558\ub098\uc529 \ub9c8\ubb34\ub9ac \ub420 \ub54c \ub9c8\ub2e4 \uc544\uc26c\uc6c0\uc774 \ub0a8\ub294\ub2e4."]})]})}function p(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>c});var t=r(67294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=t.createContext({}),c=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),h=c(r),u=a,x=h["".concat(s,".").concat(u)]||h[u]||d[u]||l;return r?t.createElement(x,i(i({ref:n},p),{},{components:r})):t.createElement(x,i({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9686],{52857:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var t=r(85893),a=r(3905);const l={title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"mvc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,o={permalink:"/mvc-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-mvc/pull/404",date:"2023-10-07T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 7\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.175,hasTruncateMarker:!1,authors:[],frontMatter:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"mvc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",permalink:"/spring-test-isolation"},nextItem:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/jdbc-retrospective"}},s={authorsImageUrls:[]},c=[{value:"MVC \uad6c\ud604",id:"mvc-\uad6c\ud604",level:3},{value:"\uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30",id:"\uc560\ub108\ud14c\uc774\uc158-\uae30\ubc18-\ud504\ub808\uc784\uc6cc\ud06c-\ub9cc\ub4e4\uae30",level:3},{value:"Legacy MVC\uc640 @MVC \ud1b5\ud569",id:"legacy-mvc\uc640-mvc-\ud1b5\ud569",level:3},{value:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",level:3},{value:"\ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95",id:"\ucd94\uc0c1\uc801\uc778-\uac1c\ub150-\ud559\uc2b5-\ubc29\ubc95",level:3},{value:"\uc815\ub9ac",id:"\uc815\ub9ac",level:3}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/404",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/404"}),(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/465",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/465"}),(0,t.jsx)(n.br,{}),"\n","3\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/580",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/580"})]})}),"\n",(0,t.jsx)(n.h3,{id:"mvc-\uad6c\ud604",children:"MVC \uad6c\ud604"}),"\n",(0,t.jsxs)(n.p,{children:["Reflection\uc744 \uc774\uc6a9\ud558\uc5ec Spring MVC\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubbf8\uc158\uc758 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\uc558\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"MVC \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uad6c\ud604\ud558\uba74\uc11c \ub0b4\ubd80 \ub3d9\uc791 \uc6d0\ub9ac\ub97c \ud559\uc2b5\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc810\uc9c4\uc801\uc778 \ub9ac\ud329\ud1a0\ub9c1\uc744 \uacbd\ud5d8\ud55c\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ubbf8\uc158\uc758 \ubaa9\ud45c\uc640 \ub354\ubd88\uc5b4 \uac01 \ud074\ub798\uc2a4\ub4e4\uc774 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \uc801\uc808\ud788 \uac00\uc9c0\ub3c4\ub85d \ud558\uace0, \ud328\ud0a4\uc9c0\uc758 \uc758\uc874 \ubc29\ud5a5\uc744 \uace0\ubbfc\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc5d0 \uc911\uc810\uc744 \ub450\uc5c8\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"\uc560\ub108\ud14c\uc774\uc158-\uae30\ubc18-\ud504\ub808\uc784\uc6cc\ud06c-\ub9cc\ub4e4\uae30",children:"\uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uae30\uc874 \ucf54\ub4dc\uc5d0 ManualHandlerMapping\uc774\ub77c\ub294 \uc11c\ube14\ub9bf\uc744 \uc9c1\uc811 \ub4f1\ub85d\ud574\uc11c \uc0ac\uc6a9\ud558\ub294 HandlerMapping \ud074\ub798\uc2a4\uac00 \uc788\uc5c8\uace0, 1\ub2e8\uacc4\uc5d0\uc11c\ub294 \uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18\uc758 AnnotationHandlerMapping\uc744 \uad6c\ud604\ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 @Controller, @RequestMapping\uc744 Reflection\uc744 \uc774\uc6a9\ud558\uc5ec \uc2a4\uce94\ud558\uace0, \ud578\ub4e4\ub7ec \ub9e4\ud551\uc744 \ub4f1\ub85d\ud558\ub294 \ubd80\ubd84\uae4c\uc9c0 \uc9c4\ud589\ud574\uc57c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud14c\uc624\uac00 @GetMapping\uc774\ub098 @PostMapping \ubd80\ubd84\ub3c4 \uc9c4\ud589\ud558\uba74 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4\uace0 \ud574\uc11c \uac19\uc774 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ubbf8\uc158 \uc694\uad6c\uc0ac\ud56d\uc740 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ud074\ub798\uc2a4 \ub808\ubca8\uc5d0 \uc801\uc6a9\ub41c @RequestMapping\ub3c4 \ub3d9\uc791\ud558\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\uc558\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n AHM[AnnotationHandlerMapping] --\x3e AS[AnnotationScanner]\n\tAHM --\x3e HKG[HandlerKeyGenerator] --\x3e HMAP[HttpMappingAnnotationParser]"}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc740 Flow\ub85c Handler(\uc2e4\uc81c \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uba54\uc11c\ub4dc) \ub4f1\ub85d\uc744 \uc9c4\ud589\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"@Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 \uc815\ubcf4\ub97c \uc2a4\uce94\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"@Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 @RequestMapping\uc774 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\ub4e4\uc758 \uc815\ubcf4\ub97c \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:["\uac01 \uba54\uc11c\ub4dc\ub4e4\uc744 \uc21c\ud68c\ud558\uba70 HandlerKey(uri + httpMethod \uc815\ubcf4)\uc640 HandlerExecution(\uc778\uc2a4\ud134\uc2a4 + \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc)\uc744 \uc0dd\uc131\ud558\uc5ec ",(0,t.jsx)(n.code,{children:"Map"}),"\uc5d0 \ucd94\uac00\ud55c\ub2e4."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"AnnotationHandlerMapping\uc758 initialize \uba54\uc11c\ub4dc\uc5d0\uc11c Handler\ub97c \ub4f1\ub85d\ud55c\ub2e4. \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AnnotationHandlerMapping",children:'public void initialize() {\n if (!initialized.compareAndSet(false, true)) {\n return;\n }\n\n final Map, ControllerInstance> controllers = annotationScanner.scanControllers();\n final Set methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());\n for (final Method method : methods) {\n final ControllerInstance controller = controllers.get(method.getDeclaringClass());\n final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);\n final List handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);\n handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));\n }\n\n log.info("Initialized AnnotationHandlerMapping!");\n handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"legacy-mvc\uc640-mvc-\ud1b5\ud569",children:"Legacy MVC\uc640 @MVC \ud1b5\ud569"}),"\n",(0,t.jsxs)(n.p,{children:["2\ub2e8\uacc4\ub294 Legacy MVC\uc640 AnnotationHandlerMapping\uc744 \ud1b5\ud569\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 MVC\uc640 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc801\uc6a9\ub41c MVC \ub450 \uac1c\ub97c \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5b4\uc57c \ud5c0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub300\ub7b5\uc801\uc778 \ud750\ub984\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"DispatcherServlet.service(request, response) \ud638\ucd9c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerMappings\ub97c \ud1b5\ud574 \uc785\ub825\ubc1b\uc740 request\uc5d0 \ud574\ub2f9\ud558\ub294 Handler \uc870\ud68c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerAdapters\ub97c \ud1b5\ud574 Handler\ub97c \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub294 HandlerAdapter \uc870\ud68c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerAdapter\uc758.handle \uba54\uc11c\ub4dc \uc2e4\ud589"}),"\n",(0,t.jsx)(n.li,{children:"View\uc758 render \ud638\ucd9c"}),"\n"]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n D[DispatcherServlet]\n D --\x3e HMS[HandlerMappings]\n D --\x3e HAS[HandlerAdapters]\n\n\tHMS --\x3e HandlerMapping\n\tsubgraph HandlerMapping\n\t\tdirection BT\n\t\tAHM[AnnotationHandlerMapping] --\x3e HM[HandlerMapping]\n\t\tMHM[ManualHandlerMapping] --\x3e HM\n\tend\n\n\tHAS --\x3e HandlerAdapter\n\tsubgraph HandlerAdapter\n\t\tdirection BT\n\t\tHEHA[HandlerExecutionHandlerAdapter] --\x3e HA[HandlerAdapter]\n\t\tCHA[ControllerHandlerAdapter] --\x3e HA\n\tend"}),"\n",(0,t.jsx)(n.h3,{id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",children:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking"}),"\n",(0,t.jsxs)(n.p,{children:["\ub0b4\uc6a9\uc774 \uae38\uc5b4\uc838\uc11c ",(0,t.jsx)(n.a,{href:"./web-application-evolution",children:"\ub2e4\uc74c \ubb38\uc11c"}),"\uc5d0 \uc815\ub9ac\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucd94\uc0c1\uc801\uc778-\uac1c\ub150-\ud559\uc2b5-\ubc29\ubc95",children:"\ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.p,{children:"\uc9c1\uad00\uc801\uc774\uc9c0 \uc54a\uc740 \ucd94\uc0c1\uc801\uc778 \uac1c\ub150\uc744 \ud559\uc2b5\ud560 \ub54c\ub294 \uac1c\ub150\uc758 \uad6c\ud604\uc744 \ucc38\uace0\ud558\uba74 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"\uac1c\ub150"}),(0,t.jsx)(n.th,{children:"\uad6c\ud604"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"OOP"}),(0,t.jsx)(n.td,{children:"Java"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"WAS"}),(0,t.jsx)(n.td,{children:"Tomcat, Jetty"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"IoC"}),(0,t.jsx)(n.td,{children:"Spring BeanFactory, Servlet Container, Framework"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"DI"}),(0,t.jsx)(n.td,{children:"Spring BeanFactory"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"\uc815\ub9ac",children:"\uc815\ub9ac"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c0\uae08\uae4c\uc9c0 \uc2a4\ud504\ub9c1\uc758 DispatcherServlet\uc758 \ub3d9\uc791\uc744 \uc774\ub860\uc801\uc73c\ub85c\ub9cc \uc54c\uace0 \uc788\uc5c8\ub294\ub370, \uc2e4\uc81c\ub85c \uad6c\ud604\ud574 \ubcf4\ub2c8 \uc870\uae08 \ub354 \uc774\ud574\uac00 \uc798 \uac00\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c \ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub8e8\uce74, \ub9ac\ubdf0\uc774\ub294 \ud5e4\ub098\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9e4 \ub2e8\uacc4\ub9c8\ub2e4 \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0\ud574 \uc900 \ub8e8\uce74\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\uace0, \ud5e4\ub098\uc5d0\uac8c \uc774\uc0c1\ud55c \ub9ac\ubdf0\ub97c \ub9ce\uc774 \ub0a8\uae34 \uac83 \uac19\uc740\ub370 \uaf3c\uaf3c\ud788 \ubc18\uc601\ud574\uc918\uc11c \uac10\uc0ac\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub7ab\ub3d9\uc548 \uae30\ub2e4\ub824\uc654\ub358 \ub808\ubca8 4 \ubbf8\uc158\uc774 \ud558\ub098\uc529 \ub9c8\ubb34\ub9ac \ub420 \ub54c \ub9c8\ub2e4 \uc544\uc26c\uc6c0\uc774 \ub0a8\ub294\ub2e4."]})]})}function p(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>c});var t=r(67294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=t.createContext({}),c=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),h=c(r),u=a,x=h["".concat(s,".").concat(u)]||h[u]||d[u]||l;return r?t.createElement(x,i(i({ref:n},p),{},{components:r})):t.createElement(x,i({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/5c07bdab.54ff7247.js b/assets/js/5c07bdab.bae264e4.js similarity index 97% rename from assets/js/5c07bdab.54ff7247.js rename to assets/js/5c07bdab.bae264e4.js index 7377a1d52..80390d77b 100644 --- a/assets/js/5c07bdab.54ff7247.js +++ b/assets/js/5c07bdab.bae264e4.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6300],{50701:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(85893),a=n(3905);const o={title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"jdbc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/jdbc-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-jdbc/pull/267",date:"2023-10-10T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 10\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.83,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"jdbc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",permalink:"/refactoring-retrospective"},nextItem:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/mvc-retrospective"}},s={authorsImageUrls:[]},l=[{value:"Jdbc \uad6c\ud604",id:"jdbc-\uad6c\ud604",level:3},{value:"JdbcTemplate",id:"jdbctemplate",level:3},{value:"\ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9",id:"\ud2b8\ub79c\uc7ad\uc158-\uc801\uc6a9",level:3},{value:"\ub9c8\ubb34\ub9ac",id:"\ub9c8\ubb34\ub9ac",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,r.jsxs)(t.p,{children:["1\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267"}),(0,r.jsx)(t.br,{}),"\n","2\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358"}),(0,r.jsx)(t.br,{}),"\n","3\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448"}),(0,r.jsx)(t.br,{}),"\n","4\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515"})]})}),"\n",(0,r.jsx)(t.h3,{id:"jdbc-\uad6c\ud604",children:"Jdbc \uad6c\ud604"}),"\n",(0,r.jsxs)(t.p,{children:["\uc774\ubc88 \ubbf8\uc158\uc740 Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uace0, Transaction \uacbd\uacc4 \uc124\uc815\uacfc \ub3d9\uae30\ud654\ud558\ub294 \ubd80\ubd84\uc744 \uad6c\ud604\ud574 \ubcf4\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ubbf8\uc158 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"JDBC \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uba74\uc11c \uc911\ubcf5\uc744 \uc81c\uac70\ud558\ub294 \uc5f0\uc2b5\uc744 \ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\ub97c \ub192\uc778\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"\ucd5c\ub300\ud55c Java\uac00 \uc81c\uacf5\ud558\ub294 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud588\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"jdbctemplate",children:"JdbcTemplate"}),"\n",(0,r.jsxs)(t.p,{children:["JdbcTemplate\uc740 Connection\uc744 \uc774\uc6a9\ud558\uc5ec PreparedStatement\ub97c \uc0dd\uc131\ud558\ub294 \ubd80\ubd84, \uadf8\ub9ac\uace0 PreparedStatement\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ubd84\ub9ac\ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc801\uc808\ud558\uac8c \uc801\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \ube44\uad50\uc801 \uac04\ub2e8\ud558\uac8c \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608\uc804\uc5d0\ub3c4 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c ",(0,r.jsx)(t.a,{href:"./custom-jdbc-template",children:"JdbcTemplate\uc744 \uad6c\ud604"}),"\ud55c \uc801\uc774 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \uc790\uc6d0 \ud560\ub2f9\uacfc \ud574\uc81c \ubd80\ubd84\uc5d0 \ub300\ud55c \uc911\ubcf5\ub3c4 \uc81c\uac70\ud588\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:'public class JdbcTemplate {\n\n private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);\n\n private final DataSource dataSource;\n private final StatementCreator statementCreator;\n private final StatementExecutor statementExecutor;\n\n public JdbcTemplate(final DataSource dataSource) {\n this(dataSource, new StatementCreator(), new StatementExecutor());\n }\n\n JdbcTemplate(\n final DataSource dataSource,\n final StatementCreator statementCreator,\n final StatementExecutor statementExecutor\n ) {\n this.dataSource = dataSource;\n this.statementCreator = statementCreator;\n this.statementExecutor = statementExecutor;\n }\n\n private T query(\n final String sql,\n final PreparedStatementCallback preparedStatementCallback,\n final Object... parameters\n ) {\n final Connection connection = DataSourceUtils.getConnection(dataSource);\n try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {\n return preparedStatementCallback.execute(preparedStatement);\n } catch (final SQLException e) {\n log.error(e.getMessage(), e);\n throw new DataAccessException(e);\n } finally {\n DataSourceUtils.releaseConnection(connection, dataSource);\n }\n }\n\n public void update(final String sql, final Object... parameters) {\n query(sql, PreparedStatement::executeUpdate, parameters);\n }\n\n public Optional queryForObject(final String sql, final RowMapper rowMapper, final Object... parameters) {\n final List results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\n if (results.size() > 1) {\n throw new DataAccessException("2\uac1c \uc774\uc0c1\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.");\n }\n return results.stream().findAny();\n }\n\n public List queryForList(final String sql, final RowMapper rowMapper, final Object... parameters) {\n return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\n }\n}\n'})}),"\n",(0,r.jsx)(t.h3,{id:"\ud2b8\ub79c\uc7ad\uc158-\uc801\uc6a9",children:"\ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9"}),"\n",(0,r.jsxs)(t.p,{children:["3, 4\ub2e8\uacc4\ub294 \uae30\uc874\uc758 \ucf54\ub4dc\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uace0 \ub05d\ub098\ub294 \ubd80\ubd84\uc778 \ud2b8\ub79c\uc7ad\uc158 \uacbd\uacc4\ub97c \uc124\uc815\ud558\uace0 ThreadLocal\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654(Transaction synchronization)\ub97c \uc801\uc6a9\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654\ub780 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uae30 \uc704\ud55c Connection \uac1d\uccb4\ub97c ThreadLocal\uacfc \uac19\uc740 \uacf5\uac04\uc5d0 \ub530\ub85c \uc800\uc7a5 \ud6c4, \ud544\uc694\ud560 \ub54c \uc800\uc7a5\ub41c Connection\uc744 \uac00\uc838\ub2e4 \uc0ac\uc6a9\ud558\ub294 \ubc29\uc2dd\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub294\ub370, ThreadLocal\uc5d0 Connection \uac1d\uccb4\uac00 \uc544\ub2cc, Connection \uac1d\uccb4\uc640 Transaction\uc774 \uc9c4\ud589 \uc911\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 flag\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \uc800\uc7a5\ud574\uc11c \uc0ac\uc6a9\ud558\ub3c4\ub85d \ud588\ub2e4."]}),"\n",(0,r.jsx)(t.mermaid,{value:"graph LR\n\tTransactionTemplate --\x3e TransactionManager\n\tTransactionManager --\x3e TransactionSynchronizationManager\n\tDataSourceUtils --\x3e TransactionSynchronizationManager\n\tJdbcTemplate --\x3e DataSourceUtils"}),"\n",(0,r.jsx)(t.h3,{id:"\ub9c8\ubb34\ub9ac",children:"\ub9c8\ubb34\ub9ac"}),"\n",(0,r.jsxs)(t.p,{children:["Jdbc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c AOP\ub098 Transactional\uc5d0 \ub300\ud55c \ud559\uc2b5 \ud14c\uc2a4\ud2b8\ub3c4 \uc9c4\ud589\ud558\uace0, \uc57d\uac04 \uc54c\ucc2c \ubbf8\uc158\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uaf3c\uaf3c\ud788 \ucf54\ub4dc\ub97c \ubd10\uc900 \ub9ac\ubdf0\uc5b4 \ud638\uc774 \uadf8\ub9ac\uace0 \uc5f0\ud734 \ub3d9\uc548 \uacc4\uc18d \ud2f0\ud0a4\ud0c0\uce74 \ud558\uba74\uc11c \uc7ac\ubc0c\uac8c \ub9ac\ubdf0\ud55c \ubbfc\ud2b8\uc5d0\uac8c \uac10\uc0ac\ud558\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud68c\uace0 \uc774\ub9cc \ub05d\ub0b4\uace0 \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud558\ub7ec\uac00\uc57c\uaca0\ub2e4. \ud83d\ude0a"]})]})}function d(e={}){const{wrapper:t}={...(0,a.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>l});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),u=l(n),b=a,m=u["".concat(s,".").concat(b)]||u[b]||p[b]||o;return n?r.createElement(m,c(c({ref:t},d),{},{components:n})):r.createElement(m,c({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6300],{50701:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(85893),a=n(3905);const o={title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"jdbc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/jdbc-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-jdbc/pull/267",date:"2023-10-10T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 10\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.83,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"jdbc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/mvc-retrospective"},nextItem:{title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",permalink:"/refactoring-retrospective"}},s={authorsImageUrls:[]},l=[{value:"Jdbc \uad6c\ud604",id:"jdbc-\uad6c\ud604",level:3},{value:"JdbcTemplate",id:"jdbctemplate",level:3},{value:"\ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9",id:"\ud2b8\ub79c\uc7ad\uc158-\uc801\uc6a9",level:3},{value:"\ub9c8\ubb34\ub9ac",id:"\ub9c8\ubb34\ub9ac",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,r.jsxs)(t.p,{children:["1\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267"}),(0,r.jsx)(t.br,{}),"\n","2\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358"}),(0,r.jsx)(t.br,{}),"\n","3\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448"}),(0,r.jsx)(t.br,{}),"\n","4\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515"})]})}),"\n",(0,r.jsx)(t.h3,{id:"jdbc-\uad6c\ud604",children:"Jdbc \uad6c\ud604"}),"\n",(0,r.jsxs)(t.p,{children:["\uc774\ubc88 \ubbf8\uc158\uc740 Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uace0, Transaction \uacbd\uacc4 \uc124\uc815\uacfc \ub3d9\uae30\ud654\ud558\ub294 \ubd80\ubd84\uc744 \uad6c\ud604\ud574 \ubcf4\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ubbf8\uc158 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"JDBC \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uba74\uc11c \uc911\ubcf5\uc744 \uc81c\uac70\ud558\ub294 \uc5f0\uc2b5\uc744 \ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\ub97c \ub192\uc778\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"\ucd5c\ub300\ud55c Java\uac00 \uc81c\uacf5\ud558\ub294 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud588\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"jdbctemplate",children:"JdbcTemplate"}),"\n",(0,r.jsxs)(t.p,{children:["JdbcTemplate\uc740 Connection\uc744 \uc774\uc6a9\ud558\uc5ec PreparedStatement\ub97c \uc0dd\uc131\ud558\ub294 \ubd80\ubd84, \uadf8\ub9ac\uace0 PreparedStatement\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ubd84\ub9ac\ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc801\uc808\ud558\uac8c \uc801\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \ube44\uad50\uc801 \uac04\ub2e8\ud558\uac8c \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608\uc804\uc5d0\ub3c4 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c ",(0,r.jsx)(t.a,{href:"./custom-jdbc-template",children:"JdbcTemplate\uc744 \uad6c\ud604"}),"\ud55c \uc801\uc774 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \uc790\uc6d0 \ud560\ub2f9\uacfc \ud574\uc81c \ubd80\ubd84\uc5d0 \ub300\ud55c \uc911\ubcf5\ub3c4 \uc81c\uac70\ud588\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:'public class JdbcTemplate {\n\n private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);\n\n private final DataSource dataSource;\n private final StatementCreator statementCreator;\n private final StatementExecutor statementExecutor;\n\n public JdbcTemplate(final DataSource dataSource) {\n this(dataSource, new StatementCreator(), new StatementExecutor());\n }\n\n JdbcTemplate(\n final DataSource dataSource,\n final StatementCreator statementCreator,\n final StatementExecutor statementExecutor\n ) {\n this.dataSource = dataSource;\n this.statementCreator = statementCreator;\n this.statementExecutor = statementExecutor;\n }\n\n private T query(\n final String sql,\n final PreparedStatementCallback preparedStatementCallback,\n final Object... parameters\n ) {\n final Connection connection = DataSourceUtils.getConnection(dataSource);\n try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {\n return preparedStatementCallback.execute(preparedStatement);\n } catch (final SQLException e) {\n log.error(e.getMessage(), e);\n throw new DataAccessException(e);\n } finally {\n DataSourceUtils.releaseConnection(connection, dataSource);\n }\n }\n\n public void update(final String sql, final Object... parameters) {\n query(sql, PreparedStatement::executeUpdate, parameters);\n }\n\n public Optional queryForObject(final String sql, final RowMapper rowMapper, final Object... parameters) {\n final List results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\n if (results.size() > 1) {\n throw new DataAccessException("2\uac1c \uc774\uc0c1\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.");\n }\n return results.stream().findAny();\n }\n\n public List queryForList(final String sql, final RowMapper rowMapper, final Object... parameters) {\n return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\n }\n}\n'})}),"\n",(0,r.jsx)(t.h3,{id:"\ud2b8\ub79c\uc7ad\uc158-\uc801\uc6a9",children:"\ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9"}),"\n",(0,r.jsxs)(t.p,{children:["3, 4\ub2e8\uacc4\ub294 \uae30\uc874\uc758 \ucf54\ub4dc\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uace0 \ub05d\ub098\ub294 \ubd80\ubd84\uc778 \ud2b8\ub79c\uc7ad\uc158 \uacbd\uacc4\ub97c \uc124\uc815\ud558\uace0 ThreadLocal\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654(Transaction synchronization)\ub97c \uc801\uc6a9\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654\ub780 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uae30 \uc704\ud55c Connection \uac1d\uccb4\ub97c ThreadLocal\uacfc \uac19\uc740 \uacf5\uac04\uc5d0 \ub530\ub85c \uc800\uc7a5 \ud6c4, \ud544\uc694\ud560 \ub54c \uc800\uc7a5\ub41c Connection\uc744 \uac00\uc838\ub2e4 \uc0ac\uc6a9\ud558\ub294 \ubc29\uc2dd\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub294\ub370, ThreadLocal\uc5d0 Connection \uac1d\uccb4\uac00 \uc544\ub2cc, Connection \uac1d\uccb4\uc640 Transaction\uc774 \uc9c4\ud589 \uc911\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 flag\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \uc800\uc7a5\ud574\uc11c \uc0ac\uc6a9\ud558\ub3c4\ub85d \ud588\ub2e4."]}),"\n",(0,r.jsx)(t.mermaid,{value:"graph LR\n\tTransactionTemplate --\x3e TransactionManager\n\tTransactionManager --\x3e TransactionSynchronizationManager\n\tDataSourceUtils --\x3e TransactionSynchronizationManager\n\tJdbcTemplate --\x3e DataSourceUtils"}),"\n",(0,r.jsx)(t.h3,{id:"\ub9c8\ubb34\ub9ac",children:"\ub9c8\ubb34\ub9ac"}),"\n",(0,r.jsxs)(t.p,{children:["Jdbc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c AOP\ub098 Transactional\uc5d0 \ub300\ud55c \ud559\uc2b5 \ud14c\uc2a4\ud2b8\ub3c4 \uc9c4\ud589\ud558\uace0, \uc57d\uac04 \uc54c\ucc2c \ubbf8\uc158\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uaf3c\uaf3c\ud788 \ucf54\ub4dc\ub97c \ubd10\uc900 \ub9ac\ubdf0\uc5b4 \ud638\uc774 \uadf8\ub9ac\uace0 \uc5f0\ud734 \ub3d9\uc548 \uacc4\uc18d \ud2f0\ud0a4\ud0c0\uce74 \ud558\uba74\uc11c \uc7ac\ubc0c\uac8c \ub9ac\ubdf0\ud55c \ubbfc\ud2b8\uc5d0\uac8c \uac10\uc0ac\ud558\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud68c\uace0 \uc774\ub9cc \ub05d\ub0b4\uace0 \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud558\ub7ec\uac00\uc57c\uaca0\ub2e4. \ud83d\ude0a"]})]})}function d(e={}){const{wrapper:t}={...(0,a.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>l});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),u=l(n),b=a,m=u["".concat(s,".").concat(b)]||u[b]||p[b]||o;return n?r.createElement(m,c(c({ref:t},d),{},{components:n})):r.createElement(m,c({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/5d4cff52.e443e998.js b/assets/js/5d4cff52.fade9e47.js similarity index 98% rename from assets/js/5d4cff52.e443e998.js rename to assets/js/5d4cff52.fade9e47.js index 2dbaa2a07..29acf47e3 100644 --- a/assets/js/5d4cff52.e443e998.js +++ b/assets/js/5d4cff52.fade9e47.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1252],{88653:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var t=r(85893),a=r(3905);const l={title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"mvc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,o={permalink:"/mvc-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-mvc/pull/404",date:"2023-10-07T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 7\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.175,hasTruncateMarker:!1,authors:[],frontMatter:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"mvc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/jdbc-retrospective"},nextItem:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",permalink:"/spring-test-isolation"}},s={authorsImageUrls:[]},c=[{value:"MVC \uad6c\ud604",id:"mvc-\uad6c\ud604",level:3},{value:"\uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30",id:"\uc560\ub108\ud14c\uc774\uc158-\uae30\ubc18-\ud504\ub808\uc784\uc6cc\ud06c-\ub9cc\ub4e4\uae30",level:3},{value:"Legacy MVC\uc640 @MVC \ud1b5\ud569",id:"legacy-mvc\uc640-mvc-\ud1b5\ud569",level:3},{value:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",level:3},{value:"\ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95",id:"\ucd94\uc0c1\uc801\uc778-\uac1c\ub150-\ud559\uc2b5-\ubc29\ubc95",level:3},{value:"\uc815\ub9ac",id:"\uc815\ub9ac",level:3}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/404",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/404"}),(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/465",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/465"}),(0,t.jsx)(n.br,{}),"\n","3\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/580",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/580"})]})}),"\n",(0,t.jsx)(n.h3,{id:"mvc-\uad6c\ud604",children:"MVC \uad6c\ud604"}),"\n",(0,t.jsxs)(n.p,{children:["Reflection\uc744 \uc774\uc6a9\ud558\uc5ec Spring MVC\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubbf8\uc158\uc758 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\uc558\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"MVC \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uad6c\ud604\ud558\uba74\uc11c \ub0b4\ubd80 \ub3d9\uc791 \uc6d0\ub9ac\ub97c \ud559\uc2b5\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc810\uc9c4\uc801\uc778 \ub9ac\ud329\ud1a0\ub9c1\uc744 \uacbd\ud5d8\ud55c\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ubbf8\uc158\uc758 \ubaa9\ud45c\uc640 \ub354\ubd88\uc5b4 \uac01 \ud074\ub798\uc2a4\ub4e4\uc774 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \uc801\uc808\ud788 \uac00\uc9c0\ub3c4\ub85d \ud558\uace0, \ud328\ud0a4\uc9c0\uc758 \uc758\uc874 \ubc29\ud5a5\uc744 \uace0\ubbfc\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc5d0 \uc911\uc810\uc744 \ub450\uc5c8\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"\uc560\ub108\ud14c\uc774\uc158-\uae30\ubc18-\ud504\ub808\uc784\uc6cc\ud06c-\ub9cc\ub4e4\uae30",children:"\uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uae30\uc874 \ucf54\ub4dc\uc5d0 ManualHandlerMapping\uc774\ub77c\ub294 \uc11c\ube14\ub9bf\uc744 \uc9c1\uc811 \ub4f1\ub85d\ud574\uc11c \uc0ac\uc6a9\ud558\ub294 HandlerMapping \ud074\ub798\uc2a4\uac00 \uc788\uc5c8\uace0, 1\ub2e8\uacc4\uc5d0\uc11c\ub294 \uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18\uc758 AnnotationHandlerMapping\uc744 \uad6c\ud604\ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 @Controller, @RequestMapping\uc744 Reflection\uc744 \uc774\uc6a9\ud558\uc5ec \uc2a4\uce94\ud558\uace0, \ud578\ub4e4\ub7ec \ub9e4\ud551\uc744 \ub4f1\ub85d\ud558\ub294 \ubd80\ubd84\uae4c\uc9c0 \uc9c4\ud589\ud574\uc57c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud14c\uc624\uac00 @GetMapping\uc774\ub098 @PostMapping \ubd80\ubd84\ub3c4 \uc9c4\ud589\ud558\uba74 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4\uace0 \ud574\uc11c \uac19\uc774 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ubbf8\uc158 \uc694\uad6c\uc0ac\ud56d\uc740 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ud074\ub798\uc2a4 \ub808\ubca8\uc5d0 \uc801\uc6a9\ub41c @RequestMapping\ub3c4 \ub3d9\uc791\ud558\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\uc558\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n AHM[AnnotationHandlerMapping] --\x3e AS[AnnotationScanner]\n\tAHM --\x3e HKG[HandlerKeyGenerator] --\x3e HMAP[HttpMappingAnnotationParser]"}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc740 Flow\ub85c Handler(\uc2e4\uc81c \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uba54\uc11c\ub4dc) \ub4f1\ub85d\uc744 \uc9c4\ud589\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"@Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 \uc815\ubcf4\ub97c \uc2a4\uce94\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"@Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 @RequestMapping\uc774 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\ub4e4\uc758 \uc815\ubcf4\ub97c \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:["\uac01 \uba54\uc11c\ub4dc\ub4e4\uc744 \uc21c\ud68c\ud558\uba70 HandlerKey(uri + httpMethod \uc815\ubcf4)\uc640 HandlerExecution(\uc778\uc2a4\ud134\uc2a4 + \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc)\uc744 \uc0dd\uc131\ud558\uc5ec ",(0,t.jsx)(n.code,{children:"Map"}),"\uc5d0 \ucd94\uac00\ud55c\ub2e4."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"AnnotationHandlerMapping\uc758 initialize \uba54\uc11c\ub4dc\uc5d0\uc11c Handler\ub97c \ub4f1\ub85d\ud55c\ub2e4. \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AnnotationHandlerMapping",children:'public void initialize() {\n if (!initialized.compareAndSet(false, true)) {\n return;\n }\n\n final Map, ControllerInstance> controllers = annotationScanner.scanControllers();\n final Set methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());\n for (final Method method : methods) {\n final ControllerInstance controller = controllers.get(method.getDeclaringClass());\n final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);\n final List handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);\n handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));\n }\n\n log.info("Initialized AnnotationHandlerMapping!");\n handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"legacy-mvc\uc640-mvc-\ud1b5\ud569",children:"Legacy MVC\uc640 @MVC \ud1b5\ud569"}),"\n",(0,t.jsxs)(n.p,{children:["2\ub2e8\uacc4\ub294 Legacy MVC\uc640 AnnotationHandlerMapping\uc744 \ud1b5\ud569\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 MVC\uc640 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc801\uc6a9\ub41c MVC \ub450 \uac1c\ub97c \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5b4\uc57c \ud5c0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub300\ub7b5\uc801\uc778 \ud750\ub984\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"DispatcherServlet.service(request, response) \ud638\ucd9c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerMappings\ub97c \ud1b5\ud574 \uc785\ub825\ubc1b\uc740 request\uc5d0 \ud574\ub2f9\ud558\ub294 Handler \uc870\ud68c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerAdapters\ub97c \ud1b5\ud574 Handler\ub97c \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub294 HandlerAdapter \uc870\ud68c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerAdapter\uc758.handle \uba54\uc11c\ub4dc \uc2e4\ud589"}),"\n",(0,t.jsx)(n.li,{children:"View\uc758 render \ud638\ucd9c"}),"\n"]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n D[DispatcherServlet]\n D --\x3e HMS[HandlerMappings]\n D --\x3e HAS[HandlerAdapters]\n\n\tHMS --\x3e HandlerMapping\n\tsubgraph HandlerMapping\n\t\tdirection BT\n\t\tAHM[AnnotationHandlerMapping] --\x3e HM[HandlerMapping]\n\t\tMHM[ManualHandlerMapping] --\x3e HM\n\tend\n\n\tHAS --\x3e HandlerAdapter\n\tsubgraph HandlerAdapter\n\t\tdirection BT\n\t\tHEHA[HandlerExecutionHandlerAdapter] --\x3e HA[HandlerAdapter]\n\t\tCHA[ControllerHandlerAdapter] --\x3e HA\n\tend"}),"\n",(0,t.jsx)(n.h3,{id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",children:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking"}),"\n",(0,t.jsxs)(n.p,{children:["\ub0b4\uc6a9\uc774 \uae38\uc5b4\uc838\uc11c ",(0,t.jsx)(n.a,{href:"./web-application-evolution",children:"\ub2e4\uc74c \ubb38\uc11c"}),"\uc5d0 \uc815\ub9ac\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucd94\uc0c1\uc801\uc778-\uac1c\ub150-\ud559\uc2b5-\ubc29\ubc95",children:"\ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.p,{children:"\uc9c1\uad00\uc801\uc774\uc9c0 \uc54a\uc740 \ucd94\uc0c1\uc801\uc778 \uac1c\ub150\uc744 \ud559\uc2b5\ud560 \ub54c\ub294 \uac1c\ub150\uc758 \uad6c\ud604\uc744 \ucc38\uace0\ud558\uba74 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"\uac1c\ub150"}),(0,t.jsx)(n.th,{children:"\uad6c\ud604"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"OOP"}),(0,t.jsx)(n.td,{children:"Java"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"WAS"}),(0,t.jsx)(n.td,{children:"Tomcat, Jetty"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"IoC"}),(0,t.jsx)(n.td,{children:"Spring BeanFactory, Servlet Container, Framework"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"DI"}),(0,t.jsx)(n.td,{children:"Spring BeanFactory"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"\uc815\ub9ac",children:"\uc815\ub9ac"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c0\uae08\uae4c\uc9c0 \uc2a4\ud504\ub9c1\uc758 DispatcherServlet\uc758 \ub3d9\uc791\uc744 \uc774\ub860\uc801\uc73c\ub85c\ub9cc \uc54c\uace0 \uc788\uc5c8\ub294\ub370, \uc2e4\uc81c\ub85c \uad6c\ud604\ud574 \ubcf4\ub2c8 \uc870\uae08 \ub354 \uc774\ud574\uac00 \uc798 \uac00\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c \ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub8e8\uce74, \ub9ac\ubdf0\uc774\ub294 \ud5e4\ub098\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9e4 \ub2e8\uacc4\ub9c8\ub2e4 \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0\ud574 \uc900 \ub8e8\uce74\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\uace0, \ud5e4\ub098\uc5d0\uac8c \uc774\uc0c1\ud55c \ub9ac\ubdf0\ub97c \ub9ce\uc774 \ub0a8\uae34 \uac83 \uac19\uc740\ub370 \uaf3c\uaf3c\ud788 \ubc18\uc601\ud574\uc918\uc11c \uac10\uc0ac\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub7ab\ub3d9\uc548 \uae30\ub2e4\ub824\uc654\ub358 \ub808\ubca8 4 \ubbf8\uc158\uc774 \ud558\ub098\uc529 \ub9c8\ubb34\ub9ac \ub420 \ub54c \ub9c8\ub2e4 \uc544\uc26c\uc6c0\uc774 \ub0a8\ub294\ub2e4."]})]})}function p(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>c});var t=r(67294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=t.createContext({}),c=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),h=c(r),u=a,x=h["".concat(s,".").concat(u)]||h[u]||d[u]||l;return r?t.createElement(x,i(i({ref:n},p),{},{components:r})):t.createElement(x,i({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1252],{88653:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var t=r(85893),a=r(3905);const l={title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"mvc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,o={permalink:"/mvc-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-mvc/pull/404",date:"2023-10-07T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 7\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.175,hasTruncateMarker:!1,authors:[],frontMatter:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"mvc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",permalink:"/spring-test-isolation"},nextItem:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/jdbc-retrospective"}},s={authorsImageUrls:[]},c=[{value:"MVC \uad6c\ud604",id:"mvc-\uad6c\ud604",level:3},{value:"\uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30",id:"\uc560\ub108\ud14c\uc774\uc158-\uae30\ubc18-\ud504\ub808\uc784\uc6cc\ud06c-\ub9cc\ub4e4\uae30",level:3},{value:"Legacy MVC\uc640 @MVC \ud1b5\ud569",id:"legacy-mvc\uc640-mvc-\ud1b5\ud569",level:3},{value:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",level:3},{value:"\ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95",id:"\ucd94\uc0c1\uc801\uc778-\uac1c\ub150-\ud559\uc2b5-\ubc29\ubc95",level:3},{value:"\uc815\ub9ac",id:"\uc815\ub9ac",level:3}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/404",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/404"}),(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/465",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/465"}),(0,t.jsx)(n.br,{}),"\n","3\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/580",children:"https://github.com/woowacourse/jwp-dashboard-mvc/pull/580"})]})}),"\n",(0,t.jsx)(n.h3,{id:"mvc-\uad6c\ud604",children:"MVC \uad6c\ud604"}),"\n",(0,t.jsxs)(n.p,{children:["Reflection\uc744 \uc774\uc6a9\ud558\uc5ec Spring MVC\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubbf8\uc158\uc758 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\uc558\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"MVC \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uad6c\ud604\ud558\uba74\uc11c \ub0b4\ubd80 \ub3d9\uc791 \uc6d0\ub9ac\ub97c \ud559\uc2b5\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc810\uc9c4\uc801\uc778 \ub9ac\ud329\ud1a0\ub9c1\uc744 \uacbd\ud5d8\ud55c\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ubbf8\uc158\uc758 \ubaa9\ud45c\uc640 \ub354\ubd88\uc5b4 \uac01 \ud074\ub798\uc2a4\ub4e4\uc774 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \uc801\uc808\ud788 \uac00\uc9c0\ub3c4\ub85d \ud558\uace0, \ud328\ud0a4\uc9c0\uc758 \uc758\uc874 \ubc29\ud5a5\uc744 \uace0\ubbfc\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc5d0 \uc911\uc810\uc744 \ub450\uc5c8\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"\uc560\ub108\ud14c\uc774\uc158-\uae30\ubc18-\ud504\ub808\uc784\uc6cc\ud06c-\ub9cc\ub4e4\uae30",children:"\uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uae30\uc874 \ucf54\ub4dc\uc5d0 ManualHandlerMapping\uc774\ub77c\ub294 \uc11c\ube14\ub9bf\uc744 \uc9c1\uc811 \ub4f1\ub85d\ud574\uc11c \uc0ac\uc6a9\ud558\ub294 HandlerMapping \ud074\ub798\uc2a4\uac00 \uc788\uc5c8\uace0, 1\ub2e8\uacc4\uc5d0\uc11c\ub294 \uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18\uc758 AnnotationHandlerMapping\uc744 \uad6c\ud604\ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 @Controller, @RequestMapping\uc744 Reflection\uc744 \uc774\uc6a9\ud558\uc5ec \uc2a4\uce94\ud558\uace0, \ud578\ub4e4\ub7ec \ub9e4\ud551\uc744 \ub4f1\ub85d\ud558\ub294 \ubd80\ubd84\uae4c\uc9c0 \uc9c4\ud589\ud574\uc57c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud14c\uc624\uac00 @GetMapping\uc774\ub098 @PostMapping \ubd80\ubd84\ub3c4 \uc9c4\ud589\ud558\uba74 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4\uace0 \ud574\uc11c \uac19\uc774 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ubbf8\uc158 \uc694\uad6c\uc0ac\ud56d\uc740 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ud074\ub798\uc2a4 \ub808\ubca8\uc5d0 \uc801\uc6a9\ub41c @RequestMapping\ub3c4 \ub3d9\uc791\ud558\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\uc558\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n AHM[AnnotationHandlerMapping] --\x3e AS[AnnotationScanner]\n\tAHM --\x3e HKG[HandlerKeyGenerator] --\x3e HMAP[HttpMappingAnnotationParser]"}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc740 Flow\ub85c Handler(\uc2e4\uc81c \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uba54\uc11c\ub4dc) \ub4f1\ub85d\uc744 \uc9c4\ud589\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"@Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 \uc815\ubcf4\ub97c \uc2a4\uce94\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"@Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 @RequestMapping\uc774 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\ub4e4\uc758 \uc815\ubcf4\ub97c \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:["\uac01 \uba54\uc11c\ub4dc\ub4e4\uc744 \uc21c\ud68c\ud558\uba70 HandlerKey(uri + httpMethod \uc815\ubcf4)\uc640 HandlerExecution(\uc778\uc2a4\ud134\uc2a4 + \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc)\uc744 \uc0dd\uc131\ud558\uc5ec ",(0,t.jsx)(n.code,{children:"Map"}),"\uc5d0 \ucd94\uac00\ud55c\ub2e4."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"AnnotationHandlerMapping\uc758 initialize \uba54\uc11c\ub4dc\uc5d0\uc11c Handler\ub97c \ub4f1\ub85d\ud55c\ub2e4. \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AnnotationHandlerMapping",children:'public void initialize() {\n if (!initialized.compareAndSet(false, true)) {\n return;\n }\n\n final Map, ControllerInstance> controllers = annotationScanner.scanControllers();\n final Set methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());\n for (final Method method : methods) {\n final ControllerInstance controller = controllers.get(method.getDeclaringClass());\n final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);\n final List handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);\n handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));\n }\n\n log.info("Initialized AnnotationHandlerMapping!");\n handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"legacy-mvc\uc640-mvc-\ud1b5\ud569",children:"Legacy MVC\uc640 @MVC \ud1b5\ud569"}),"\n",(0,t.jsxs)(n.p,{children:["2\ub2e8\uacc4\ub294 Legacy MVC\uc640 AnnotationHandlerMapping\uc744 \ud1b5\ud569\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 MVC\uc640 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc801\uc6a9\ub41c MVC \ub450 \uac1c\ub97c \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5b4\uc57c \ud5c0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub300\ub7b5\uc801\uc778 \ud750\ub984\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"DispatcherServlet.service(request, response) \ud638\ucd9c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerMappings\ub97c \ud1b5\ud574 \uc785\ub825\ubc1b\uc740 request\uc5d0 \ud574\ub2f9\ud558\ub294 Handler \uc870\ud68c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerAdapters\ub97c \ud1b5\ud574 Handler\ub97c \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub294 HandlerAdapter \uc870\ud68c"}),"\n",(0,t.jsx)(n.li,{children:"HandlerAdapter\uc758.handle \uba54\uc11c\ub4dc \uc2e4\ud589"}),"\n",(0,t.jsx)(n.li,{children:"View\uc758 render \ud638\ucd9c"}),"\n"]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n D[DispatcherServlet]\n D --\x3e HMS[HandlerMappings]\n D --\x3e HAS[HandlerAdapters]\n\n\tHMS --\x3e HandlerMapping\n\tsubgraph HandlerMapping\n\t\tdirection BT\n\t\tAHM[AnnotationHandlerMapping] --\x3e HM[HandlerMapping]\n\t\tMHM[ManualHandlerMapping] --\x3e HM\n\tend\n\n\tHAS --\x3e HandlerAdapter\n\tsubgraph HandlerAdapter\n\t\tdirection BT\n\t\tHEHA[HandlerExecutionHandlerAdapter] --\x3e HA[HandlerAdapter]\n\t\tCHA[ControllerHandlerAdapter] --\x3e HA\n\tend"}),"\n",(0,t.jsx)(n.h3,{id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",children:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph LR\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking"}),"\n",(0,t.jsxs)(n.p,{children:["\ub0b4\uc6a9\uc774 \uae38\uc5b4\uc838\uc11c ",(0,t.jsx)(n.a,{href:"./web-application-evolution",children:"\ub2e4\uc74c \ubb38\uc11c"}),"\uc5d0 \uc815\ub9ac\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucd94\uc0c1\uc801\uc778-\uac1c\ub150-\ud559\uc2b5-\ubc29\ubc95",children:"\ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.p,{children:"\uc9c1\uad00\uc801\uc774\uc9c0 \uc54a\uc740 \ucd94\uc0c1\uc801\uc778 \uac1c\ub150\uc744 \ud559\uc2b5\ud560 \ub54c\ub294 \uac1c\ub150\uc758 \uad6c\ud604\uc744 \ucc38\uace0\ud558\uba74 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"\uac1c\ub150"}),(0,t.jsx)(n.th,{children:"\uad6c\ud604"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"OOP"}),(0,t.jsx)(n.td,{children:"Java"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"WAS"}),(0,t.jsx)(n.td,{children:"Tomcat, Jetty"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"IoC"}),(0,t.jsx)(n.td,{children:"Spring BeanFactory, Servlet Container, Framework"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"DI"}),(0,t.jsx)(n.td,{children:"Spring BeanFactory"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"\uc815\ub9ac",children:"\uc815\ub9ac"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c0\uae08\uae4c\uc9c0 \uc2a4\ud504\ub9c1\uc758 DispatcherServlet\uc758 \ub3d9\uc791\uc744 \uc774\ub860\uc801\uc73c\ub85c\ub9cc \uc54c\uace0 \uc788\uc5c8\ub294\ub370, \uc2e4\uc81c\ub85c \uad6c\ud604\ud574 \ubcf4\ub2c8 \uc870\uae08 \ub354 \uc774\ud574\uac00 \uc798 \uac00\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c \ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub8e8\uce74, \ub9ac\ubdf0\uc774\ub294 \ud5e4\ub098\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9e4 \ub2e8\uacc4\ub9c8\ub2e4 \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0\ud574 \uc900 \ub8e8\uce74\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\uace0, \ud5e4\ub098\uc5d0\uac8c \uc774\uc0c1\ud55c \ub9ac\ubdf0\ub97c \ub9ce\uc774 \ub0a8\uae34 \uac83 \uac19\uc740\ub370 \uaf3c\uaf3c\ud788 \ubc18\uc601\ud574\uc918\uc11c \uac10\uc0ac\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub7ab\ub3d9\uc548 \uae30\ub2e4\ub824\uc654\ub358 \ub808\ubca8 4 \ubbf8\uc158\uc774 \ud558\ub098\uc529 \ub9c8\ubb34\ub9ac \ub420 \ub54c \ub9c8\ub2e4 \uc544\uc26c\uc6c0\uc774 \ub0a8\ub294\ub2e4."]})]})}function p(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>c});var t=r(67294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=t.createContext({}),c=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),h=c(r),u=a,x=h["".concat(s,".").concat(u)]||h[u]||d[u]||l;return r?t.createElement(x,i(i({ref:n},p),{},{components:r})):t.createElement(x,i({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/6552f31f.46a2fccb.js b/assets/js/6552f31f.7b26502f.js similarity index 97% rename from assets/js/6552f31f.46a2fccb.js rename to assets/js/6552f31f.7b26502f.js index 0ef20ef66..3f0192373 100644 --- a/assets/js/6552f31f.46a2fccb.js +++ b/assets/js/6552f31f.7b26502f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[917],{84112:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var n=t(85893),o=t(3905);const i={title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",slug:"level2-interview-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,s={permalink:"/level2-interview-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",description:"\ub808\ubca8 \uc778\ud130\ubdf0",date:"2023-06-08T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 8\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.435,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",slug:"level2-interview-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",permalink:"/woowacourse-level2-retrospective"},nextItem:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",permalink:"/order-retrospective"}},a={authorsImageUrls:[]},l=[{value:"\ub808\ubca8 \uc778\ud130\ubdf0",id:"\ub808\ubca8-\uc778\ud130\ubdf0",level:3},{value:"API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd",id:"api-\ubb38\uc11c-\ub3c4\uad6c-\uc120\ud0dd",level:3},{value:"PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158",id:"put\uacfc-patch--\ud1a0\ud070\uacfc-\uc138\uc158",level:3},{value:"\uadf8 \uc678 \uac1c\uc120\ud560 \uc810",id:"\uadf8-\uc678-\uac1c\uc120\ud560-\uc810",level:3}];function p(e){const r={blockquote:"blockquote",br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.h3,{id:"\ub808\ubca8-\uc778\ud130\ubdf0",children:"\ub808\ubca8 \uc778\ud130\ubdf0"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 1 \ub54c\ub294 \uc900\ube44\ud574\ub454 \ub0b4\uc6a9\uc73c\ub85c \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud574\uc11c \uadf8\ub807\uac8c \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc774 \uc5c6\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \ub808\ubca8 1 \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0\ub294 \ub808\ubca8 1 \ud68c\uace0\ub97c \uc791\uc131\ud560 \ub54c \ub07c\uc6cc\ub123\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \ubc94\uc704\ub3c4 \uc81c\ud55c\ub418\uc5b4 \uc788\uc5b4 \uc5b4\ub5bb\uac8c \uc900\ube44\ud574\uc57c \ud560\uc9c0 \ub2f9\ud669\ud588\uace0, \ub2f5\ubcc0\uc5d0\ub3c4 \ubd80\uc871\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uae30\uc5b5\uc774 \uc0ac\ub77c\uc9c0\uae30 \uc804\uc5d0 \ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\ud55c \ub0b4\uc6a9\uc744 \uc81c\uc678\ud558\uace0, \uae30\uc5b5 \ub0a8\ub294 \uac83 \uc704\uc8fc\ub85c \uc791\uc131\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"api-\ubb38\uc11c-\ub3c4\uad6c-\uc120\ud0dd",children:"API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd"}),"\n",(0,n.jsxs)(r.p,{children:["\ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\uc744 \ud588\ub294\ub370 \uc55e\uc73c\ub85c\ub3c4 \ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \ud558\uba74\uc11c \ub3c4\uc6c0 \ub420 \uac83 \uac19\uc740 \ub0b4\uc6a9\uc774 \uc788\uc5b4\uc11c \ub0a8\uaca8\ub450\ub824\uace0 \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc31\uc5d4\ub4dc \ud300\uc6d0\uc774 \ud568\uaed8 \uc758\uc0ac\uacb0\uc815\uc744 \ud588\uace0, \ubbf8\uc158 \uae30\uac04\uc774 \uc9e7\uc740 \ub9cc\ud07c \ud300 \ucc28\uc6d0\uc5d0\uc11c \ube44\uad50\uc801 \ud559\uc2b5\ud558\uae30 \uc26c\uc6b4 Swagger\ub97c \uc120\ud0dd\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ucd94\uac00\ub85c \ub4e4\uc5b4\uac00\ub294 \uc2dc\uac04 \ub300\ube44 \ud558\uc774 \ub9ac\ud134\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4\uace0 \ub2f5\ubcc0\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ud300 \ucc28\uc6d0\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uc5b8\uae09\ud574\uc11c, \ub2e4\uc74c\uacfc \uac19\uc740 \uc88b\uc740 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4."}),"\n",(0,n.jsxs)(r.blockquote,{children:["\n",(0,n.jsxs)(r.p,{children:["\ud2b9\ud788 \ud300\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\ud558\ub294 \uacfc\uc815\uc744 \uacf5\uc720\ud574 \uc900 \uc810\uc774 \uc88b\uc558\uace0 \uae30\uc220\uc801 \uc758\uc0ac\uacb0\uc815 \uacfc\uc815\uc5d0\uc11c \ud300\uc758 \ud559\uc2b5\ube44\uc6a9\uc744 \uace0\ub824\ud55c \uc810\uc774 \uc88b\uc558\uc74c.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c\ub3c4 \ud559\uc2b5 \ube44\uc6a9\uc740 \uc8fc\uc694\ud558\uac8c \uace0\ub824\ud574\uc57c \ud560 \uc0ac\ud56d"]}),"\n"]}),"\n",(0,n.jsx)(r.h3,{id:"put\uacfc-patch--\ud1a0\ud070\uacfc-\uc138\uc158",children:"PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["PUT\uacfc PATCH \ucc28\uc774\ub97c \uc124\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c\ub294 PATCH\ub97c \uc0ac\uc6a9\ud560 \ub54c \ud398\uc774\ub85c\ub4dc\uac00 \uc801\uc5b4\uc9c4\ub2e4\ub294 \ub0b4\uc6a9\uc744 \ube7c\uba39\uace0 \ub2f5\ubcc0\uc744 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud1a0\ud070\uacfc \uc138\uc158\uc758 \uacbd\uc6b0 \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud574\ub2ec\ub77c\ub294 \uc81c\uc57d\uc870\uac74\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ud574\ub2f9 \ub0b4\uc6a9\uc744 \ub2f5\ubcc0\ud558\uba74\uc11c \uae30\uc220\uc801\uc778 \uae4a\uc774\uac00 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc2e4\uc81c\ub85c \ub808\ubca8 2 \ub54c \uc774\ub860\uc801\uc778 \ud559\uc2b5 \uc2dc\uac04\uc774 \ub9e4\uc6b0 \uc801\uc5c8\uace0, \uc9d1\uc911\ub825\ub3c4 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc5b4\ub5bb\uac8c \uae4a\uc774\ub97c \ucc44\uc6b8\uc9c0 \uace0\ubbfc\uc744 \ud560 \uc218 \uc788\ub294 \uc9c8\ubb38\ub4e4\uc774\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ucd94\uac00\ub85c \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud558\ub294 \uac00\uc815\uc744 \ub450\uace0 \ud559\uc2b5\uc744 \ud55c\ub2e4\uba74 \ud070 \ub3c4\uc6c0\uc774 \ub420 \uac70\ub77c\ub294 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4."}),"\n",(0,n.jsx)(r.h3,{id:"\uadf8-\uc678-\uac1c\uc120\ud560-\uc810",children:"\uadf8 \uc678 \uac1c\uc120\ud560 \uc810"}),"\n",(0,n.jsxs)(r.p,{children:["\uc778\ud130\ubdf0\ud560 \ub54c \ud2b9\uc720\uc758 \ub9d0\ubc84\ub987\uc744 \uac1c\uc120\ud558\uae30",(0,n.jsx)(r.br,{}),"\n",'\uc0dd\uac01\ud560 \uc2dc\uac04\uc744 \uac00\uc84c\uc744 \ub54c "\ub2e4\uc2dc \ub9d0\uc500\ub4dc\ub824\ub3c4 \ub420\uae4c\uc694?"\ub77c\uace0 \ub9d0\ud558\uace0 \ub2f5\ubcc0\uc744 \uc774\uc5b4\ub098\uac00\uae30',(0,n.jsx)(r.br,{}),"\n","\uae30\uc220\uc801\uc73c\ub85c \uae4a\uc774\uac00 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5b4\uc11c \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\uae30",(0,n.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0 \uacf5\ubd80\ud588\ub358\uac70 \ub418\ub3cc\uc544 \ubcf4\ub294 \uc2dc\uac04 \uac00\uc9c0\uae30"]})]})}function u(e={}){const{wrapper:r}={...(0,o.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,a=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),b=l(t),h=o,d=b["".concat(a,".").concat(h)]||b[h]||p[h]||i;return t?n.createElement(d,c(c({ref:r},u),{},{components:t})):n.createElement(d,c({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[917],{84112:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var n=t(85893),o=t(3905);const i={title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",slug:"level2-interview-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,s={permalink:"/level2-interview-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",description:"\ub808\ubca8 \uc778\ud130\ubdf0",date:"2023-06-08T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 8\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.435,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",slug:"level2-interview-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",permalink:"/order-retrospective"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",permalink:"/woowacourse-level2-retrospective"}},a={authorsImageUrls:[]},l=[{value:"\ub808\ubca8 \uc778\ud130\ubdf0",id:"\ub808\ubca8-\uc778\ud130\ubdf0",level:3},{value:"API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd",id:"api-\ubb38\uc11c-\ub3c4\uad6c-\uc120\ud0dd",level:3},{value:"PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158",id:"put\uacfc-patch--\ud1a0\ud070\uacfc-\uc138\uc158",level:3},{value:"\uadf8 \uc678 \uac1c\uc120\ud560 \uc810",id:"\uadf8-\uc678-\uac1c\uc120\ud560-\uc810",level:3}];function p(e){const r={blockquote:"blockquote",br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.h3,{id:"\ub808\ubca8-\uc778\ud130\ubdf0",children:"\ub808\ubca8 \uc778\ud130\ubdf0"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 1 \ub54c\ub294 \uc900\ube44\ud574\ub454 \ub0b4\uc6a9\uc73c\ub85c \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud574\uc11c \uadf8\ub807\uac8c \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc774 \uc5c6\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \ub808\ubca8 1 \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0\ub294 \ub808\ubca8 1 \ud68c\uace0\ub97c \uc791\uc131\ud560 \ub54c \ub07c\uc6cc\ub123\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \ubc94\uc704\ub3c4 \uc81c\ud55c\ub418\uc5b4 \uc788\uc5b4 \uc5b4\ub5bb\uac8c \uc900\ube44\ud574\uc57c \ud560\uc9c0 \ub2f9\ud669\ud588\uace0, \ub2f5\ubcc0\uc5d0\ub3c4 \ubd80\uc871\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uae30\uc5b5\uc774 \uc0ac\ub77c\uc9c0\uae30 \uc804\uc5d0 \ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\ud55c \ub0b4\uc6a9\uc744 \uc81c\uc678\ud558\uace0, \uae30\uc5b5 \ub0a8\ub294 \uac83 \uc704\uc8fc\ub85c \uc791\uc131\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"api-\ubb38\uc11c-\ub3c4\uad6c-\uc120\ud0dd",children:"API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd"}),"\n",(0,n.jsxs)(r.p,{children:["\ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\uc744 \ud588\ub294\ub370 \uc55e\uc73c\ub85c\ub3c4 \ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \ud558\uba74\uc11c \ub3c4\uc6c0 \ub420 \uac83 \uac19\uc740 \ub0b4\uc6a9\uc774 \uc788\uc5b4\uc11c \ub0a8\uaca8\ub450\ub824\uace0 \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc31\uc5d4\ub4dc \ud300\uc6d0\uc774 \ud568\uaed8 \uc758\uc0ac\uacb0\uc815\uc744 \ud588\uace0, \ubbf8\uc158 \uae30\uac04\uc774 \uc9e7\uc740 \ub9cc\ud07c \ud300 \ucc28\uc6d0\uc5d0\uc11c \ube44\uad50\uc801 \ud559\uc2b5\ud558\uae30 \uc26c\uc6b4 Swagger\ub97c \uc120\ud0dd\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ucd94\uac00\ub85c \ub4e4\uc5b4\uac00\ub294 \uc2dc\uac04 \ub300\ube44 \ud558\uc774 \ub9ac\ud134\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4\uace0 \ub2f5\ubcc0\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ud300 \ucc28\uc6d0\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uc5b8\uae09\ud574\uc11c, \ub2e4\uc74c\uacfc \uac19\uc740 \uc88b\uc740 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4."}),"\n",(0,n.jsxs)(r.blockquote,{children:["\n",(0,n.jsxs)(r.p,{children:["\ud2b9\ud788 \ud300\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\ud558\ub294 \uacfc\uc815\uc744 \uacf5\uc720\ud574 \uc900 \uc810\uc774 \uc88b\uc558\uace0 \uae30\uc220\uc801 \uc758\uc0ac\uacb0\uc815 \uacfc\uc815\uc5d0\uc11c \ud300\uc758 \ud559\uc2b5\ube44\uc6a9\uc744 \uace0\ub824\ud55c \uc810\uc774 \uc88b\uc558\uc74c.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c\ub3c4 \ud559\uc2b5 \ube44\uc6a9\uc740 \uc8fc\uc694\ud558\uac8c \uace0\ub824\ud574\uc57c \ud560 \uc0ac\ud56d"]}),"\n"]}),"\n",(0,n.jsx)(r.h3,{id:"put\uacfc-patch--\ud1a0\ud070\uacfc-\uc138\uc158",children:"PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["PUT\uacfc PATCH \ucc28\uc774\ub97c \uc124\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c\ub294 PATCH\ub97c \uc0ac\uc6a9\ud560 \ub54c \ud398\uc774\ub85c\ub4dc\uac00 \uc801\uc5b4\uc9c4\ub2e4\ub294 \ub0b4\uc6a9\uc744 \ube7c\uba39\uace0 \ub2f5\ubcc0\uc744 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud1a0\ud070\uacfc \uc138\uc158\uc758 \uacbd\uc6b0 \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud574\ub2ec\ub77c\ub294 \uc81c\uc57d\uc870\uac74\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ud574\ub2f9 \ub0b4\uc6a9\uc744 \ub2f5\ubcc0\ud558\uba74\uc11c \uae30\uc220\uc801\uc778 \uae4a\uc774\uac00 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc2e4\uc81c\ub85c \ub808\ubca8 2 \ub54c \uc774\ub860\uc801\uc778 \ud559\uc2b5 \uc2dc\uac04\uc774 \ub9e4\uc6b0 \uc801\uc5c8\uace0, \uc9d1\uc911\ub825\ub3c4 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc5b4\ub5bb\uac8c \uae4a\uc774\ub97c \ucc44\uc6b8\uc9c0 \uace0\ubbfc\uc744 \ud560 \uc218 \uc788\ub294 \uc9c8\ubb38\ub4e4\uc774\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ucd94\uac00\ub85c \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud558\ub294 \uac00\uc815\uc744 \ub450\uace0 \ud559\uc2b5\uc744 \ud55c\ub2e4\uba74 \ud070 \ub3c4\uc6c0\uc774 \ub420 \uac70\ub77c\ub294 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4."}),"\n",(0,n.jsx)(r.h3,{id:"\uadf8-\uc678-\uac1c\uc120\ud560-\uc810",children:"\uadf8 \uc678 \uac1c\uc120\ud560 \uc810"}),"\n",(0,n.jsxs)(r.p,{children:["\uc778\ud130\ubdf0\ud560 \ub54c \ud2b9\uc720\uc758 \ub9d0\ubc84\ub987\uc744 \uac1c\uc120\ud558\uae30",(0,n.jsx)(r.br,{}),"\n",'\uc0dd\uac01\ud560 \uc2dc\uac04\uc744 \uac00\uc84c\uc744 \ub54c "\ub2e4\uc2dc \ub9d0\uc500\ub4dc\ub824\ub3c4 \ub420\uae4c\uc694?"\ub77c\uace0 \ub9d0\ud558\uace0 \ub2f5\ubcc0\uc744 \uc774\uc5b4\ub098\uac00\uae30',(0,n.jsx)(r.br,{}),"\n","\uae30\uc220\uc801\uc73c\ub85c \uae4a\uc774\uac00 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5b4\uc11c \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\uae30",(0,n.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0 \uacf5\ubd80\ud588\ub358\uac70 \ub418\ub3cc\uc544 \ubcf4\ub294 \uc2dc\uac04 \uac00\uc9c0\uae30"]})]})}function u(e={}){const{wrapper:r}={...(0,o.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,a=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),b=l(t),h=o,d=b["".concat(a,".").concat(h)]||b[h]||p[h]||i;return t?n.createElement(d,c(c({ref:r},u),{},{components:t})):n.createElement(d,c({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/6675e9ab.aea6d3a6.js b/assets/js/6675e9ab.2eb5bc04.js similarity index 97% rename from assets/js/6675e9ab.aea6d3a6.js rename to assets/js/6675e9ab.2eb5bc04.js index 7b18b5591..de9f82be1 100644 --- a/assets/js/6675e9ab.aea6d3a6.js +++ b/assets/js/6675e9ab.2eb5bc04.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1255],{29218:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var n=t(85893),s=t(3905);const o={title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",slug:"shopping-cart-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/shopping-cart-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-shopping-cart/pull/244",date:"2023-05-12T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 12\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.845,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",slug:"shopping-cart-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",permalink:"/accidental-duplication"},nextItem:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",permalink:"/web-racing-car-retrospective"}},a={authorsImageUrls:[]},l=[{value:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158",id:"\uc6f9-\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",h3:"h3",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,n.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-shopping-cart/pull/244",children:"https://github.com/woowacourse/jwp-shopping-cart/pull/244"}),(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-shopping-cart/pull/300",children:"https://github.com/woowacourse/jwp-shopping-cart/pull/300"})]})}),"\n",(0,n.jsx)(r.h3,{id:"\uc6f9-\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158",children:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc740 \ube14\ub799\ucea3\uc774\ub791 \uc9c4\ud589\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc694\uad6c\uc0ac\ud56d\uc774 \uc5c4\uccad \ubcf5\uc7a1\ud55c \ubbf8\uc158\uc740 \uc544\ub2c8\uc5c8\uace0, \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\ubcf8\uc801\uc778 CRUD\ub97c \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4\uc5d0\uc11c\ub294 Basic \uc778\uc99d\uc744 \ud1b5\ud574 \uc790\uc2e0\uc758 \uc7a5\ubc14\uad6c\ub2c8\uc5d0\ub9cc \uc0c1\ud488\uc744 \ub2f4\uace0, \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \uad6c\ud604\ud558\ub294 \uc694\uad6c\uc0ac\ud56d\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","Interceptor\ub098 Argument Resolver\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\uac00 \ub192\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc870\uae08 \ub354 \uc54c\uc544\uac04 \ub290\ub08c\uc774\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0 \uc2a4\ud504\ub9c1 \uc0ac\uc6a9\ud560 \ub54c\ub294 \uc544\ubb34 \uc0dd\uac01 \uc5c6\uc774 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub294\ub370, \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \ub54c \uadfc\uac70\uac00 \uc0dd\uae30\uace0 \uc788\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"DTO \uc6b0\ubc1c\uc801 \uc911\ubcf5"})}),"\n",(0,n.jsx)(r.p,{children:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.img,{alt:"dto1",src:t(33946).Z+"",width:"2028",height:"704"})}),"\n",(0,n.jsxs)(r.p,{children:["\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d \ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0 \uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\uc744 \ud588\uace0, \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec \uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4."]}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsx)(r.li,{children:"\uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,n.jsx)(r.li,{children:"\uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4."}),"\n"]}),"\n",(0,n.jsxs)(r.p,{children:["\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131 \uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \ub9ac\ubdf0\uc5b4 \uc6e8\uc9c0\uac00 \uc544\ub798\uc640 \uac19\uc774 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\uace0 \uc54c\ub824\uc8fc\uc168\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.img,{alt:"dto2",src:t(15907).Z+"",width:"1508",height:"896"})}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"Interceptor\uc5d0\uc11c \uc778\uc99d\ud55c \uac12 \uc7ac\uc0ac\uc6a9"})}),"\n",(0,n.jsxs)(r.p,{children:["\uc0ac\uc2e4 \uc870\ud68c\ub97c \ub450 \ubc88 \ud558\uae30 \uc2eb\uc5b4\uc11c \ub2e4\uc591\ud55c \ubc29\ubc95\uc744 \uc0dd\uac01\ud588\uc5c8\ub294\ub370 \uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 ThreadLocal\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc77c\ub2e8 Tomcat\uc740 \uc694\uccad\ub9c8\ub2e4 \ub2e4\ub978 \uc2a4\ub808\ub4dc\ub97c \uc0ac\uc6a9\ud558\uace0, Interceptor\uc5d0\uc11c \uc870\ud68c\ud574\uc11c \ub9cc\ub4e0 Credential\uc744 ThreadLocal\uc5d0 \ub123\uc5b4\ub450\uc5c8\ub2e4\uac00 ArgumentResolver\uc5d0\uc11c \uaebc\ub0b8 \ub2e4\uc74c ThreadLocal\uc744 clear \ud558\uba74 \ubb38\uc81c\uac00 \uc5c6\uc744 \uac70\ub77c \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub9ac\ubdf0\uc5b4\uc778 \uc6e8\uc9c0\uc5d0\uac8c\ub3c4 \uc5b4\ub5a4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560\uc9c0 \uad81\uae08\uc99d\uc744 \uc791\uc131\ud588\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc6e8\uc9c0\ub294 email\uc5d0 index\ub97c \uac78\uc5b4\ub450\uace0 dao \uc7ac\uc870\ud68c\ub97c \uc0ac\uc6a9\ud560 \uac83\uc774\ub77c\uace0 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc7ac\uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 db\uc5d0 \uc778\ub371\uc2a4\ub97c \uac78 \uc0dd\uac01\uc740 \ud558\uc9c0 \ubabb\ud588\ub294\ub370, \uc81c\uc77c \uc9c1\uad00\uc801\uc774\uace0 \uc88b\uc740 \ubc29\ubc95\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"\uae30\ub85d"})}),"\n",(0,n.jsxs)(r.p,{children:["\ube14\ub799\ucea3\uc740 \uae30\ub85d\uc744 \uad49\uc7a5\ud788 \uc798 \ud558\ub294 \ud06c\ub8e8\uc600\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub178\uc158\uc5d0 \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ud588\ub358 \ub0b4\uc6a9 + \uace0\ubbfc\ud588\ub358 \ubd80\ubd84 + \ud68c\uace0\ub97c \uaf3c\uaf3c\ud558\uac8c \uae30\ub85d\ud574\uc11c \uacf5\uc720\ud574 \uc8fc\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ucd94\uac00\uc801\uc73c\ub85c \uc774\ubaa8\uc9c0\ub97c \uc801\uadf9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uc5ec \ub354\uc6b1 \uc88b\uc558\ub2e4!"]}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"\uc758\uacac \uc77c\uce58\uc2dc\ud0a4\uae30"})}),"\n",(0,n.jsxs)(r.p,{children:["\ud398\uc5b4 \uc2dc\uac04\uc740 \ud55c\uc815\ub418\uc5b4 \uc788\uace0, \uae30\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574\uc57c \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \uc801\ub2f9\ud788 \ud0c0\ud611\uc744 \ubd10\uc11c \uc758\uacac\uc744 \ube60\ub974\uac8c \uc218\uc6a9\ud574 \ub370\ub4dc\ub77c\uc778\uc744 \ub9de\ucd94\ub294 \uac83\ub3c4 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ube14\ub799\ucea3\uc740 \ub0b4 \uc758\uacac\uc744 \uc798 \ub4e4\uc5b4\uc92c\uace0, \ub355\ubd84\uc5d0 \ub9c9\ud788\ub294 \ubd80\ubd84 \uc5c6\uc774 \ube60\ub974\uac8c \ubbf8\uc158\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ube68\ub9ac \uce5c\ud574\uc84c\uace0, \uc758\uc0ac\uc18c\ud1b5\uc774 \uc798 \ub3fc\uc11c \uc7ac\ubc0c\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uc5c8\ub2e4!"})]})}function h(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},h=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,o=e.originalType,a=e.parentName,h=i(e,["components","mdxType","originalType","parentName"]),d=l(t),u=s,j=d["".concat(a,".").concat(u)]||d[u]||p[u]||o;return t?n.createElement(j,c(c({ref:r},h),{},{components:t})):n.createElement(j,c({ref:r},h))}));h.displayName="MDXCreateElement"},33946:(e,r,t)=>{t.d(r,{Z:()=>n});const n=t.p+"assets/images/dto1-ccd4f91674b224578f2b295b3fccaf2c.png"},15907:(e,r,t)=>{t.d(r,{Z:()=>n});const n=t.p+"assets/images/dto2-15b381e0a024487f54608d438e5385f9.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1255],{29218:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var n=t(85893),s=t(3905);const o={title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",slug:"shopping-cart-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/shopping-cart-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-shopping-cart/pull/244",date:"2023-05-12T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 12\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.845,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",slug:"shopping-cart-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",permalink:"/web-racing-car-retrospective"},nextItem:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",permalink:"/accidental-duplication"}},a={authorsImageUrls:[]},l=[{value:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158",id:"\uc6f9-\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",h3:"h3",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,n.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-shopping-cart/pull/244",children:"https://github.com/woowacourse/jwp-shopping-cart/pull/244"}),(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-shopping-cart/pull/300",children:"https://github.com/woowacourse/jwp-shopping-cart/pull/300"})]})}),"\n",(0,n.jsx)(r.h3,{id:"\uc6f9-\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158",children:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc740 \ube14\ub799\ucea3\uc774\ub791 \uc9c4\ud589\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc694\uad6c\uc0ac\ud56d\uc774 \uc5c4\uccad \ubcf5\uc7a1\ud55c \ubbf8\uc158\uc740 \uc544\ub2c8\uc5c8\uace0, \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\ubcf8\uc801\uc778 CRUD\ub97c \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4\uc5d0\uc11c\ub294 Basic \uc778\uc99d\uc744 \ud1b5\ud574 \uc790\uc2e0\uc758 \uc7a5\ubc14\uad6c\ub2c8\uc5d0\ub9cc \uc0c1\ud488\uc744 \ub2f4\uace0, \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \uad6c\ud604\ud558\ub294 \uc694\uad6c\uc0ac\ud56d\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","Interceptor\ub098 Argument Resolver\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\uac00 \ub192\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc870\uae08 \ub354 \uc54c\uc544\uac04 \ub290\ub08c\uc774\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0 \uc2a4\ud504\ub9c1 \uc0ac\uc6a9\ud560 \ub54c\ub294 \uc544\ubb34 \uc0dd\uac01 \uc5c6\uc774 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub294\ub370, \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \ub54c \uadfc\uac70\uac00 \uc0dd\uae30\uace0 \uc788\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"DTO \uc6b0\ubc1c\uc801 \uc911\ubcf5"})}),"\n",(0,n.jsx)(r.p,{children:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.img,{alt:"dto1",src:t(33946).Z+"",width:"2028",height:"704"})}),"\n",(0,n.jsxs)(r.p,{children:["\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d \ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0 \uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\uc744 \ud588\uace0, \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec \uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4."]}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsx)(r.li,{children:"\uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,n.jsx)(r.li,{children:"\uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4."}),"\n"]}),"\n",(0,n.jsxs)(r.p,{children:["\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131 \uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \ub9ac\ubdf0\uc5b4 \uc6e8\uc9c0\uac00 \uc544\ub798\uc640 \uac19\uc774 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\uace0 \uc54c\ub824\uc8fc\uc168\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.img,{alt:"dto2",src:t(15907).Z+"",width:"1508",height:"896"})}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"Interceptor\uc5d0\uc11c \uc778\uc99d\ud55c \uac12 \uc7ac\uc0ac\uc6a9"})}),"\n",(0,n.jsxs)(r.p,{children:["\uc0ac\uc2e4 \uc870\ud68c\ub97c \ub450 \ubc88 \ud558\uae30 \uc2eb\uc5b4\uc11c \ub2e4\uc591\ud55c \ubc29\ubc95\uc744 \uc0dd\uac01\ud588\uc5c8\ub294\ub370 \uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 ThreadLocal\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc77c\ub2e8 Tomcat\uc740 \uc694\uccad\ub9c8\ub2e4 \ub2e4\ub978 \uc2a4\ub808\ub4dc\ub97c \uc0ac\uc6a9\ud558\uace0, Interceptor\uc5d0\uc11c \uc870\ud68c\ud574\uc11c \ub9cc\ub4e0 Credential\uc744 ThreadLocal\uc5d0 \ub123\uc5b4\ub450\uc5c8\ub2e4\uac00 ArgumentResolver\uc5d0\uc11c \uaebc\ub0b8 \ub2e4\uc74c ThreadLocal\uc744 clear \ud558\uba74 \ubb38\uc81c\uac00 \uc5c6\uc744 \uac70\ub77c \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub9ac\ubdf0\uc5b4\uc778 \uc6e8\uc9c0\uc5d0\uac8c\ub3c4 \uc5b4\ub5a4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560\uc9c0 \uad81\uae08\uc99d\uc744 \uc791\uc131\ud588\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc6e8\uc9c0\ub294 email\uc5d0 index\ub97c \uac78\uc5b4\ub450\uace0 dao \uc7ac\uc870\ud68c\ub97c \uc0ac\uc6a9\ud560 \uac83\uc774\ub77c\uace0 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc7ac\uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 db\uc5d0 \uc778\ub371\uc2a4\ub97c \uac78 \uc0dd\uac01\uc740 \ud558\uc9c0 \ubabb\ud588\ub294\ub370, \uc81c\uc77c \uc9c1\uad00\uc801\uc774\uace0 \uc88b\uc740 \ubc29\ubc95\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"\uae30\ub85d"})}),"\n",(0,n.jsxs)(r.p,{children:["\ube14\ub799\ucea3\uc740 \uae30\ub85d\uc744 \uad49\uc7a5\ud788 \uc798 \ud558\ub294 \ud06c\ub8e8\uc600\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub178\uc158\uc5d0 \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ud588\ub358 \ub0b4\uc6a9 + \uace0\ubbfc\ud588\ub358 \ubd80\ubd84 + \ud68c\uace0\ub97c \uaf3c\uaf3c\ud558\uac8c \uae30\ub85d\ud574\uc11c \uacf5\uc720\ud574 \uc8fc\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ucd94\uac00\uc801\uc73c\ub85c \uc774\ubaa8\uc9c0\ub97c \uc801\uadf9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uc5ec \ub354\uc6b1 \uc88b\uc558\ub2e4!"]}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"\uc758\uacac \uc77c\uce58\uc2dc\ud0a4\uae30"})}),"\n",(0,n.jsxs)(r.p,{children:["\ud398\uc5b4 \uc2dc\uac04\uc740 \ud55c\uc815\ub418\uc5b4 \uc788\uace0, \uae30\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574\uc57c \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \uc801\ub2f9\ud788 \ud0c0\ud611\uc744 \ubd10\uc11c \uc758\uacac\uc744 \ube60\ub974\uac8c \uc218\uc6a9\ud574 \ub370\ub4dc\ub77c\uc778\uc744 \ub9de\ucd94\ub294 \uac83\ub3c4 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ube14\ub799\ucea3\uc740 \ub0b4 \uc758\uacac\uc744 \uc798 \ub4e4\uc5b4\uc92c\uace0, \ub355\ubd84\uc5d0 \ub9c9\ud788\ub294 \ubd80\ubd84 \uc5c6\uc774 \ube60\ub974\uac8c \ubbf8\uc158\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ube68\ub9ac \uce5c\ud574\uc84c\uace0, \uc758\uc0ac\uc18c\ud1b5\uc774 \uc798 \ub3fc\uc11c \uc7ac\ubc0c\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uc5c8\ub2e4!"})]})}function h(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},h=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,o=e.originalType,a=e.parentName,h=i(e,["components","mdxType","originalType","parentName"]),d=l(t),u=s,j=d["".concat(a,".").concat(u)]||d[u]||p[u]||o;return t?n.createElement(j,c(c({ref:r},h),{},{components:t})):n.createElement(j,c({ref:r},h))}));h.displayName="MDXCreateElement"},33946:(e,r,t)=>{t.d(r,{Z:()=>n});const n=t.p+"assets/images/dto1-ccd4f91674b224578f2b295b3fccaf2c.png"},15907:(e,r,t)=>{t.d(r,{Z:()=>n});const n=t.p+"assets/images/dto2-15b381e0a024487f54608d438e5385f9.png"}}]); \ No newline at end of file diff --git a/assets/js/6b54f6a4.2c404bfc.js b/assets/js/6b54f6a4.b0d83dc8.js similarity index 98% rename from assets/js/6b54f6a4.2c404bfc.js rename to assets/js/6b54f6a4.b0d83dc8.js index 1b24f4739..560f32ddb 100644 --- a/assets/js/6b54f6a4.2c404bfc.js +++ b/assets/js/6b54f6a4.b0d83dc8.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4558],{57211:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>c,default:()=>m,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var r=t(85893),a=t(3905),i=t(74866),l=t(85162);const o={title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",slug:"custom-jdbc-template",tags:["JDBC","Java"]},c=void 0,s={permalink:"/custom-jdbc-template",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",source:"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",description:"\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.",date:"2023-04-02T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 2\uc77c",tags:[{label:"JDBC",permalink:"/tags/jdbc"},{label:"Java",permalink:"/tags/java"}],readingTime:9.025,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",slug:"custom-jdbc-template",tags:["JDBC","Java"]},unlisted:!1,prevItem:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",permalink:"/java-class-file"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",permalink:"/woowacourse-level1-retrospective"}},u={authorsImageUrls:[]},p=[{value:"\uae30\uc874 \ucf54\ub4dc",id:"\uae30\uc874-\ucf54\ub4dc",level:3},{value:"SELECT, DELETE \uc911\ubcf5 \uc81c\uac70",id:"select-delete-\uc911\ubcf5-\uc81c\uac70",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---1-\ucf5c\ubc31\uc744-\uc704\ud55c-\uc778\ud130\ud398\uc774\uc2a4-\uc815\uc758",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---2-\ub2e8\uac74-\uc870\ud68c",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---3-\ub2e4\uac74-\uc870\ud68c",level:3},{value:"\uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30",id:"\uc81c\ub124\ub9ad-\uc0ac\uc6a9\ud558\uae30",level:3},{value:"\uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30",id:"\uba54\uc11c\ub4dc-\ubd84\ub9ac\ud55c-\ubd80\ubd84-\ud074\ub798\uc2a4\ub85c-\ubd84\ub9ac\ud558\uae30--optional-\uc0ac\uc6a9\ud558\uae30",level:3}];function d(e){const n={admonition:"admonition",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774 \ub54c JDBC\ub97c \uc0ac\uc6a9\ud560 \ub54c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ucee4\ub125\uc158\uc744 \uc5bb\uace0, try-with-resource\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc774 \ubc18\ubcf5\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc774\uc6a9\ud558\uc5ec \ub098\ub9cc\uc758 JdbcTemplate\uc744 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uae30\uc874-\ucf54\ub4dc",children:"\uae30\uc874 \ucf54\ub4dc"}),"\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(l.Z,{value:"User",label:"User",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public class User {\n private final int id;\n private final String name;\n\n public User(final int id, final String name) {\n this.id = id;\n this.name = name;\n }\n\n public int getId() {\n return id;\n }\n\n public String getName() {\n return name;\n }\n}\n"})})}),(0,r.jsx)(l.Z,{value:"UserDao",label:"UserDao",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class UserDao {\n private final ConnectionPool connectionPool;\n\n public UserDao(final ConnectionPool connectionPool) {\n this.connectionPool = connectionPool;\n }\n\n public void insert(final String name) {\n final Connection connection = connectionPool.getConnection();\n final String query = "INSERT INTO User (name) VALUES (?)";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setString(1, name);\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public void delete(final int userId) {\n final Connection connection = connectionPool.getConnection();\n final String query = "DELETE FROM user WHERE id = ?";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setInt(1, userId);\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public User findById(final int userId) {\n final Connection connection = connectionPool.getConnection();\n final String query = "SELECT * FROM user WHERE id = ?";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setInt(1, userId);\n final ResultSet resultSet = preparedStatement.executeQuery();\n if (resultSet.next()) {\n return new User(\n resultSet.getInt("id"),\n resultSet.getString("name")\n );\n }\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n return null;\n }\n\n public List findAll() {\n final Connection connection = connectionPool.getConnection();\n final String query = "SELECT * FROM user";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n final ResultSet resultSet = preparedStatement.executeQuery();\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(new User(\n resultSet.getInt("id"),\n resultSet.getString("name")\n ));\n }\n return result;\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n}\n'})})}),(0,r.jsx)(l.Z,{value:"ConnectionPool",label:"ConnectionPool",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class ConnectionPool {\n private static final String SERVER = "localhost:13306";\n private static final String DATABASE = "chess";\n private static final String OPTION = "?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";\n private static final String URL = "jdbc:mysql://" + SERVER + "/" + DATABASE + OPTION;\n private static final String USERNAME = "root";\n private static final String PASSWORD = "root";\n\n private final AtomicInteger index = new AtomicInteger();\n private final List connections;\n\n public ConnectionPool(final int connectionCount) {\n connections = generateConnections(connectionCount);\n }\n\n private List generateConnections(final int connectionCount) {\n return Stream.generate(this::generateConnection)\n .limit(connectionCount)\n .collect(toList());\n }\n\n private Connection generateConnection() {\n try {\n return DriverManager.getConnection(URL, USERNAME, PASSWORD);\n } catch (SQLException e) {\n throw new IllegalStateException("\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.");\n }\n }\n\n public Connection getConnection() {\n int currentIndex = index.getAndIncrement();\n return connections.get(currentIndex % connections.size());\n }\n}\n'})})})]}),"\n",(0,r.jsx)(n.h3,{id:"select-delete-\uc911\ubcf5-\uc81c\uac70",children:"SELECT, DELETE \uc911\ubcf5 \uc81c\uac70"}),"\n",(0,r.jsxs)(n.p,{children:["\ubcc0\ud558\uc9c0 \uc54a\ub294 \ubd80\ubd84: try-with-resource, preparedStatement\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84, executeUpdate\ub85c \uc2e4\ud589 \ub4f1\ub4f1",(0,r.jsx)(n.br,{}),"\n","\ubcc0\ud558\ub294 \ubd80\ubd84: SQL Query, \ub9e4\uac1c\ubcc0\uc218"]}),"\n",(0,r.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\ub294 \ubd80\ubd84\uc744 \ubd84\ub9ac\ud558\uace0 \uac00\ubcc0\uc778\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 SELECT\uc640 DELETE\uc758 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public void insert(final String name) {\n final String query = "INSERT INTO User (name) VALUES (?)";\n executeUpdate(query, name);\n}\n\npublic void delete(final int userId) {\n final String query = "DELETE FROM user WHERE user_id = ?";\n executeUpdate(query, userId);\n}\n\nprivate void executeUpdate(final String query, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---1-\ucf5c\ubc31\uc744-\uc704\ud55c-\uc778\ud130\ud398\uc774\uc2a4-\uc815\uc758",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758"}),"\n",(0,r.jsxs)(n.p,{children:["\uc870\ud68c\ub294 INSERT, DELETE\uc640 \ub2ec\ub9ac \uac12\uc744 \ubc18\ud658\ubc1b\uc544\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0 \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774 \ub54c \ucf5c\ubc31\uc774\ub77c\ub294 \uac83\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsxs)(n.admonition,{title:"\ucf5c\ubc31(Callback)",type:"note",children:[(0,r.jsxs)(n.p,{children:["\ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \ucf5c\ubc31\uc740 \ub2e4\ub978 \ucf54\ub4dc\uc758 \uc778\uc218\ub85c \ub118\uaca8\uc8fc\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ucf54\ub4dc\ub97c \ub73b\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\ubc14\uc5d0\uc11c\ub294 \ub78c\ub2e4\ub098 \uc775\uba85 \ud074\ub798\uc2a4\ub97c \ub118\uaca8\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),(0,r.jsx)(n.mermaid,{value:"flowchart LR\n \ud074\ub77c\uc774\uc5b8\ud2b8 -- \ucf5c\ubc31\uc804\ub2ec --\x3e \uba54\uc11c\ub4dc\n \uba54\uc11c\ub4dc -- \ub0b4\ubd80\ud638\ucd9c --\x3e \uc804\ub2ec\ubc1b\uc740\ucf5c\ubc31"})]}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uc870\ud68c\ud558\uace0, \ud574\ub2f9 \uac12\uc744 \uac1d\uccb4\ub85c \ub9e4\ud551\ud558\uc5ec \uac12\uc744 \ubc18\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","executeQuery\ub85c \uc870\ud68c\ud55c \uac12\uc740 ResultSet \uc548\uc5d0 \ub4e4\uc5b4\uac00\uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ub97c \uc6d0\ud558\ub294 \ud0c0\uc785\uc758 \uac12\uc73c\ub85c \ubcc0\ud658\ud574\uc57c\ud558\ub2c8 \uc77c\ub2e8 \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface RowMapper {\n User mapRow(final ResultSet resultSet) throws SQLException;\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---2-\ub2e8\uac74-\uc870\ud68c",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c"}),"\n",(0,r.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c \uc815\uc758\ud55c RowMapper\ub97c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c?",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc774 SQL \ucffc\ub9ac, RowMapper, \ud30c\ub77c\ubbf8\ud130\ub97c \ubd84\ub9ac\ud55c \uba54\uc11c\ub4dc\uc5d0 \ub118\uaca8\uc8fc\uace0 \ucffc\ub9ac \uc2e4\ud589 \ud6c4 \ub9e4\ud551\ud55c \uac12\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public User findById(final int userId) {\n final String query = "SELECT * FROM user WHERE id = ?";\n return queryForSingleResult(query, resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n }, userId);\n}\n\nprivate User queryForSingleResult(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n if (resultSet.next()) {\n return rowMapper.mapRow(resultSet);\n }\n return null;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n\nprivate ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---3-\ub2e4\uac74-\uc870\ud68c",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c"}),"\n",(0,r.jsx)(n.p,{children:"\ub2e8\uac74 \uc870\ud68c\uc640 \uc720\uc0ac\ud558\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public List findAll() {\n final String query = "SELECT * FROM user";\n return query(query, resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n });\n}\n\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(rowMapper.mapRow(resultSet));\n }\n return result;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n\nprivate ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc81c\ub124\ub9ad-\uc0ac\uc6a9\ud558\uae30",children:"\uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30"}),"\n",(0,r.jsxs)(n.p,{children:["\uc704\uc758 \ucf54\ub4dc\ub294 User\ub97c \uc870\ud68c\ud560 \ub54c\ub9cc \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc774 \uc81c\ub124\ub9ad\uc744 \uc801\uc6a9\ud558\uc5ec \ub2e4\ub978 Dao\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface RowMapper {\n T mapRow(final ResultSet resultSet) throws SQLException;\n}\n\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {...}\nprivate T queryForSingleResult(final String query, final RowMapper rowMapper, final Object... parameters) {...}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\uba54\uc11c\ub4dc-\ubd84\ub9ac\ud55c-\ubd80\ubd84-\ud074\ub798\uc2a4\ub85c-\ubd84\ub9ac\ud558\uae30--optional-\uc0ac\uc6a9\ud558\uae30",children:"\uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30"}),"\n",(0,r.jsxs)(n.p,{children:["\uba54\uc11c\ub4dc\ub85c \ubd84\ub9ac\ud55c \ubd80\ubd84\uc744 JdbcTemplate\uc774\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc62e\uae34\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c null\uc744 \ubc18\ud658\ud558\uae30 \ubcf4\ub2e8 Optional\ub85c \uac10\uc2f8\uc11c \ubc18\ud658\ud558\ub3c4\ub85d \ubcc0\uacbd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd5c\uc885\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uac00 \uc644\uc131\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(l.Z,{value:"UserDao",label:"UserDao",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class UserDao {\n private final RowMapper rowMapper = resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n };\n private final JdbcTemplate jdbcTemplate;\n\n public UserDao(final JdbcTemplate jdbcTemplate) {\n this.jdbcTemplate = jdbcTemplate;\n }\n\n public void insert(final String name) {\n final String query = "INSERT INTO User (name) VALUES (?)";\n jdbcTemplate.executeUpdate(query, name);\n }\n\n public void delete(final int userId) {\n final String query = "DELETE FROM user WHERE user_id = ?";\n jdbcTemplate.executeUpdate(query, userId);\n }\n\n public Optional findById(final int userId) {\n final String query = "SELECT * FROM user WHERE id = ?";\n return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);\n }\n\n public List findAll() {\n final String query = "SELECT * FROM user";\n return jdbcTemplate.query(query, rowMapper);\n }\n}\n'})})}),(0,r.jsx)(l.Z,{value:"JdbcTemplate",label:"JdbcTemplate",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public class JdbcTemplate {\n private final ConnectionPool connectionPool;\n\n public JdbcTemplate(final ConnectionPool connectionPool) {\n this.connectionPool = connectionPool;\n }\n\n public void executeUpdate(final String query, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public Optional queryForSingleResult(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n ) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n if (resultSet.next()) {\n return Optional.of(rowMapper.mapRow(resultSet));\n }\n return Optional.empty();\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n private ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters\n ) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n }\n\n public List query(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n ) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(rowMapper.mapRow(resultSet));\n }\n return result;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n}\n"})})})]})]})}function m(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>s});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=r.createContext({}),s=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),d=s(t),m=a,f=d["".concat(c,".").concat(m)]||d[m]||u[m]||i;return t?r.createElement(f,l(l({ref:n},p),{},{components:t})):r.createElement(f,l({ref:n},p))}));p.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>l});t(67294);var r=t(86010);const a={tabItem:"tabItem_Ymn6"};var i=t(85893);function l(e){let{children:n,hidden:t,className:l}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.Z)(a.tabItem,l),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>j});var r=t(67294),a=t(86010),i=t(12466),l=t(16550),o=t(20469),c=t(91980),s=t(67392),u=t(50012);function p(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function d(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return p(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:a}}=e;return{value:n,label:t,attributes:r,default:a}}))}(t);return function(e){const n=(0,s.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function m(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function f(e){let{queryString:n=!1,groupId:t}=e;const a=(0,l.k6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,c._X)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function S(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=d(e),[l,c]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!m({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[s,p]=f({queryString:t,groupId:a}),[S,g]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,u.Nk)(t);return[a,(0,r.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),b=(()=>{const e=s??S;return m({value:e,tabValues:i})?e:null})();(0,o.Z)((()=>{b&&c(b)}),[b]);return{selectedValue:l,selectValue:(0,r.useCallback)((e=>{if(!m({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),p(e),g(e)}),[p,g,i]),tabValues:i}}var g=t(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var h=t(85893);function x(e){let{className:n,block:t,selectedValue:r,selectValue:l,tabValues:o}=e;const c=[],{blockElementScrollPositionUntilNextRender:s}=(0,i.o5)(),u=e=>{const n=e.currentTarget,t=c.indexOf(n),a=o[t].value;a!==r&&(s(n),l(a))},p=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=c.indexOf(e.currentTarget)+1;n=c[t]??c[0];break}case"ArrowLeft":{const t=c.indexOf(e.currentTarget)-1;n=c[t]??c[c.length-1];break}}n?.focus()};return(0,h.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,h.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>c.push(e),onKeyDown:p,onClick:u,...i,className:(0,a.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function y(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,h.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function v(e){const n=S(e);return(0,h.jsxs)("div",{className:(0,a.Z)("tabs-container",b.tabList),children:[(0,h.jsx)(x,{...e,...n}),(0,h.jsx)(y,{...e,...n})]})}function j(e){const n=(0,g.Z)();return(0,h.jsx)(v,{...e,children:p(e.children)},String(n))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4558],{57211:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>c,default:()=>m,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var r=t(85893),a=t(3905),i=t(74866),l=t(85162);const o={title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",slug:"custom-jdbc-template",tags:["JDBC","Java"]},c=void 0,s={permalink:"/custom-jdbc-template",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",source:"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",description:"\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.",date:"2023-04-02T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 2\uc77c",tags:[{label:"JDBC",permalink:"/tags/jdbc"},{label:"Java",permalink:"/tags/java"}],readingTime:9.025,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",slug:"custom-jdbc-template",tags:["JDBC","Java"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",permalink:"/woowacourse-level1-retrospective"},nextItem:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",permalink:"/java-class-file"}},u={authorsImageUrls:[]},p=[{value:"\uae30\uc874 \ucf54\ub4dc",id:"\uae30\uc874-\ucf54\ub4dc",level:3},{value:"SELECT, DELETE \uc911\ubcf5 \uc81c\uac70",id:"select-delete-\uc911\ubcf5-\uc81c\uac70",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---1-\ucf5c\ubc31\uc744-\uc704\ud55c-\uc778\ud130\ud398\uc774\uc2a4-\uc815\uc758",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---2-\ub2e8\uac74-\uc870\ud68c",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---3-\ub2e4\uac74-\uc870\ud68c",level:3},{value:"\uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30",id:"\uc81c\ub124\ub9ad-\uc0ac\uc6a9\ud558\uae30",level:3},{value:"\uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30",id:"\uba54\uc11c\ub4dc-\ubd84\ub9ac\ud55c-\ubd80\ubd84-\ud074\ub798\uc2a4\ub85c-\ubd84\ub9ac\ud558\uae30--optional-\uc0ac\uc6a9\ud558\uae30",level:3}];function d(e){const n={admonition:"admonition",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774 \ub54c JDBC\ub97c \uc0ac\uc6a9\ud560 \ub54c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ucee4\ub125\uc158\uc744 \uc5bb\uace0, try-with-resource\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc774 \ubc18\ubcf5\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc774\uc6a9\ud558\uc5ec \ub098\ub9cc\uc758 JdbcTemplate\uc744 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uae30\uc874-\ucf54\ub4dc",children:"\uae30\uc874 \ucf54\ub4dc"}),"\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(l.Z,{value:"User",label:"User",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public class User {\n private final int id;\n private final String name;\n\n public User(final int id, final String name) {\n this.id = id;\n this.name = name;\n }\n\n public int getId() {\n return id;\n }\n\n public String getName() {\n return name;\n }\n}\n"})})}),(0,r.jsx)(l.Z,{value:"UserDao",label:"UserDao",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class UserDao {\n private final ConnectionPool connectionPool;\n\n public UserDao(final ConnectionPool connectionPool) {\n this.connectionPool = connectionPool;\n }\n\n public void insert(final String name) {\n final Connection connection = connectionPool.getConnection();\n final String query = "INSERT INTO User (name) VALUES (?)";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setString(1, name);\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public void delete(final int userId) {\n final Connection connection = connectionPool.getConnection();\n final String query = "DELETE FROM user WHERE id = ?";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setInt(1, userId);\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public User findById(final int userId) {\n final Connection connection = connectionPool.getConnection();\n final String query = "SELECT * FROM user WHERE id = ?";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setInt(1, userId);\n final ResultSet resultSet = preparedStatement.executeQuery();\n if (resultSet.next()) {\n return new User(\n resultSet.getInt("id"),\n resultSet.getString("name")\n );\n }\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n return null;\n }\n\n public List findAll() {\n final Connection connection = connectionPool.getConnection();\n final String query = "SELECT * FROM user";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n final ResultSet resultSet = preparedStatement.executeQuery();\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(new User(\n resultSet.getInt("id"),\n resultSet.getString("name")\n ));\n }\n return result;\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n}\n'})})}),(0,r.jsx)(l.Z,{value:"ConnectionPool",label:"ConnectionPool",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class ConnectionPool {\n private static final String SERVER = "localhost:13306";\n private static final String DATABASE = "chess";\n private static final String OPTION = "?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";\n private static final String URL = "jdbc:mysql://" + SERVER + "/" + DATABASE + OPTION;\n private static final String USERNAME = "root";\n private static final String PASSWORD = "root";\n\n private final AtomicInteger index = new AtomicInteger();\n private final List connections;\n\n public ConnectionPool(final int connectionCount) {\n connections = generateConnections(connectionCount);\n }\n\n private List generateConnections(final int connectionCount) {\n return Stream.generate(this::generateConnection)\n .limit(connectionCount)\n .collect(toList());\n }\n\n private Connection generateConnection() {\n try {\n return DriverManager.getConnection(URL, USERNAME, PASSWORD);\n } catch (SQLException e) {\n throw new IllegalStateException("\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.");\n }\n }\n\n public Connection getConnection() {\n int currentIndex = index.getAndIncrement();\n return connections.get(currentIndex % connections.size());\n }\n}\n'})})})]}),"\n",(0,r.jsx)(n.h3,{id:"select-delete-\uc911\ubcf5-\uc81c\uac70",children:"SELECT, DELETE \uc911\ubcf5 \uc81c\uac70"}),"\n",(0,r.jsxs)(n.p,{children:["\ubcc0\ud558\uc9c0 \uc54a\ub294 \ubd80\ubd84: try-with-resource, preparedStatement\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84, executeUpdate\ub85c \uc2e4\ud589 \ub4f1\ub4f1",(0,r.jsx)(n.br,{}),"\n","\ubcc0\ud558\ub294 \ubd80\ubd84: SQL Query, \ub9e4\uac1c\ubcc0\uc218"]}),"\n",(0,r.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\ub294 \ubd80\ubd84\uc744 \ubd84\ub9ac\ud558\uace0 \uac00\ubcc0\uc778\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 SELECT\uc640 DELETE\uc758 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public void insert(final String name) {\n final String query = "INSERT INTO User (name) VALUES (?)";\n executeUpdate(query, name);\n}\n\npublic void delete(final int userId) {\n final String query = "DELETE FROM user WHERE user_id = ?";\n executeUpdate(query, userId);\n}\n\nprivate void executeUpdate(final String query, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---1-\ucf5c\ubc31\uc744-\uc704\ud55c-\uc778\ud130\ud398\uc774\uc2a4-\uc815\uc758",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758"}),"\n",(0,r.jsxs)(n.p,{children:["\uc870\ud68c\ub294 INSERT, DELETE\uc640 \ub2ec\ub9ac \uac12\uc744 \ubc18\ud658\ubc1b\uc544\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0 \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774 \ub54c \ucf5c\ubc31\uc774\ub77c\ub294 \uac83\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsxs)(n.admonition,{title:"\ucf5c\ubc31(Callback)",type:"note",children:[(0,r.jsxs)(n.p,{children:["\ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \ucf5c\ubc31\uc740 \ub2e4\ub978 \ucf54\ub4dc\uc758 \uc778\uc218\ub85c \ub118\uaca8\uc8fc\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ucf54\ub4dc\ub97c \ub73b\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\ubc14\uc5d0\uc11c\ub294 \ub78c\ub2e4\ub098 \uc775\uba85 \ud074\ub798\uc2a4\ub97c \ub118\uaca8\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),(0,r.jsx)(n.mermaid,{value:"flowchart LR\n \ud074\ub77c\uc774\uc5b8\ud2b8 -- \ucf5c\ubc31\uc804\ub2ec --\x3e \uba54\uc11c\ub4dc\n \uba54\uc11c\ub4dc -- \ub0b4\ubd80\ud638\ucd9c --\x3e \uc804\ub2ec\ubc1b\uc740\ucf5c\ubc31"})]}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uc870\ud68c\ud558\uace0, \ud574\ub2f9 \uac12\uc744 \uac1d\uccb4\ub85c \ub9e4\ud551\ud558\uc5ec \uac12\uc744 \ubc18\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","executeQuery\ub85c \uc870\ud68c\ud55c \uac12\uc740 ResultSet \uc548\uc5d0 \ub4e4\uc5b4\uac00\uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ub97c \uc6d0\ud558\ub294 \ud0c0\uc785\uc758 \uac12\uc73c\ub85c \ubcc0\ud658\ud574\uc57c\ud558\ub2c8 \uc77c\ub2e8 \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface RowMapper {\n User mapRow(final ResultSet resultSet) throws SQLException;\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---2-\ub2e8\uac74-\uc870\ud68c",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c"}),"\n",(0,r.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c \uc815\uc758\ud55c RowMapper\ub97c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c?",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc774 SQL \ucffc\ub9ac, RowMapper, \ud30c\ub77c\ubbf8\ud130\ub97c \ubd84\ub9ac\ud55c \uba54\uc11c\ub4dc\uc5d0 \ub118\uaca8\uc8fc\uace0 \ucffc\ub9ac \uc2e4\ud589 \ud6c4 \ub9e4\ud551\ud55c \uac12\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public User findById(final int userId) {\n final String query = "SELECT * FROM user WHERE id = ?";\n return queryForSingleResult(query, resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n }, userId);\n}\n\nprivate User queryForSingleResult(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n if (resultSet.next()) {\n return rowMapper.mapRow(resultSet);\n }\n return null;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n\nprivate ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---3-\ub2e4\uac74-\uc870\ud68c",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c"}),"\n",(0,r.jsx)(n.p,{children:"\ub2e8\uac74 \uc870\ud68c\uc640 \uc720\uc0ac\ud558\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public List findAll() {\n final String query = "SELECT * FROM user";\n return query(query, resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n });\n}\n\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(rowMapper.mapRow(resultSet));\n }\n return result;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n\nprivate ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc81c\ub124\ub9ad-\uc0ac\uc6a9\ud558\uae30",children:"\uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30"}),"\n",(0,r.jsxs)(n.p,{children:["\uc704\uc758 \ucf54\ub4dc\ub294 User\ub97c \uc870\ud68c\ud560 \ub54c\ub9cc \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc774 \uc81c\ub124\ub9ad\uc744 \uc801\uc6a9\ud558\uc5ec \ub2e4\ub978 Dao\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface RowMapper {\n T mapRow(final ResultSet resultSet) throws SQLException;\n}\n\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {...}\nprivate T queryForSingleResult(final String query, final RowMapper rowMapper, final Object... parameters) {...}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\uba54\uc11c\ub4dc-\ubd84\ub9ac\ud55c-\ubd80\ubd84-\ud074\ub798\uc2a4\ub85c-\ubd84\ub9ac\ud558\uae30--optional-\uc0ac\uc6a9\ud558\uae30",children:"\uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30"}),"\n",(0,r.jsxs)(n.p,{children:["\uba54\uc11c\ub4dc\ub85c \ubd84\ub9ac\ud55c \ubd80\ubd84\uc744 JdbcTemplate\uc774\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc62e\uae34\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c null\uc744 \ubc18\ud658\ud558\uae30 \ubcf4\ub2e8 Optional\ub85c \uac10\uc2f8\uc11c \ubc18\ud658\ud558\ub3c4\ub85d \ubcc0\uacbd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd5c\uc885\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uac00 \uc644\uc131\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(l.Z,{value:"UserDao",label:"UserDao",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class UserDao {\n private final RowMapper rowMapper = resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n };\n private final JdbcTemplate jdbcTemplate;\n\n public UserDao(final JdbcTemplate jdbcTemplate) {\n this.jdbcTemplate = jdbcTemplate;\n }\n\n public void insert(final String name) {\n final String query = "INSERT INTO User (name) VALUES (?)";\n jdbcTemplate.executeUpdate(query, name);\n }\n\n public void delete(final int userId) {\n final String query = "DELETE FROM user WHERE user_id = ?";\n jdbcTemplate.executeUpdate(query, userId);\n }\n\n public Optional findById(final int userId) {\n final String query = "SELECT * FROM user WHERE id = ?";\n return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);\n }\n\n public List findAll() {\n final String query = "SELECT * FROM user";\n return jdbcTemplate.query(query, rowMapper);\n }\n}\n'})})}),(0,r.jsx)(l.Z,{value:"JdbcTemplate",label:"JdbcTemplate",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public class JdbcTemplate {\n private final ConnectionPool connectionPool;\n\n public JdbcTemplate(final ConnectionPool connectionPool) {\n this.connectionPool = connectionPool;\n }\n\n public void executeUpdate(final String query, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public Optional queryForSingleResult(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n ) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n if (resultSet.next()) {\n return Optional.of(rowMapper.mapRow(resultSet));\n }\n return Optional.empty();\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n private ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters\n ) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n }\n\n public List query(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n ) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(rowMapper.mapRow(resultSet));\n }\n return result;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n}\n"})})})]})]})}function m(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>s});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=r.createContext({}),s=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),d=s(t),m=a,f=d["".concat(c,".").concat(m)]||d[m]||u[m]||i;return t?r.createElement(f,l(l({ref:n},p),{},{components:t})):r.createElement(f,l({ref:n},p))}));p.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>l});t(67294);var r=t(86010);const a={tabItem:"tabItem_Ymn6"};var i=t(85893);function l(e){let{children:n,hidden:t,className:l}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.Z)(a.tabItem,l),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>j});var r=t(67294),a=t(86010),i=t(12466),l=t(16550),o=t(20469),c=t(91980),s=t(67392),u=t(50012);function p(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function d(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return p(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:a}}=e;return{value:n,label:t,attributes:r,default:a}}))}(t);return function(e){const n=(0,s.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function m(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function f(e){let{queryString:n=!1,groupId:t}=e;const a=(0,l.k6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,c._X)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function S(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=d(e),[l,c]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!m({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[s,p]=f({queryString:t,groupId:a}),[S,g]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,u.Nk)(t);return[a,(0,r.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),b=(()=>{const e=s??S;return m({value:e,tabValues:i})?e:null})();(0,o.Z)((()=>{b&&c(b)}),[b]);return{selectedValue:l,selectValue:(0,r.useCallback)((e=>{if(!m({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),p(e),g(e)}),[p,g,i]),tabValues:i}}var g=t(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var h=t(85893);function x(e){let{className:n,block:t,selectedValue:r,selectValue:l,tabValues:o}=e;const c=[],{blockElementScrollPositionUntilNextRender:s}=(0,i.o5)(),u=e=>{const n=e.currentTarget,t=c.indexOf(n),a=o[t].value;a!==r&&(s(n),l(a))},p=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=c.indexOf(e.currentTarget)+1;n=c[t]??c[0];break}case"ArrowLeft":{const t=c.indexOf(e.currentTarget)-1;n=c[t]??c[c.length-1];break}}n?.focus()};return(0,h.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,h.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>c.push(e),onKeyDown:p,onClick:u,...i,className:(0,a.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function y(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,h.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function v(e){const n=S(e);return(0,h.jsxs)("div",{className:(0,a.Z)("tabs-container",b.tabList),children:[(0,h.jsx)(x,{...e,...n}),(0,h.jsx)(y,{...e,...n})]})}function j(e){const n=(0,g.Z)();return(0,h.jsx)(v,{...e,children:p(e.children)},String(n))}}}]); \ No newline at end of file diff --git a/assets/js/6f385a52.b5af1364.js b/assets/js/6f385a52.e1859e1c.js similarity index 98% rename from assets/js/6f385a52.b5af1364.js rename to assets/js/6f385a52.e1859e1c.js index d196759d2..8c85d7274 100644 --- a/assets/js/6f385a52.b5af1364.js +++ b/assets/js/6f385a52.e1859e1c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6608],{54413:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>o});var t=r(85893),c=r(3905);const i={title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",slug:"accidental-duplication",tags:["DTO"]},s=void 0,l={permalink:"/accidental-duplication",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",source:"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",description:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",date:"2023-05-24T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 24\uc77c",tags:[{label:"DTO",permalink:"/tags/dto"}],readingTime:7.525,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",slug:"accidental-duplication",tags:["DTO"]},unlisted:!1,prevItem:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",permalink:"/subway-retrospective"},nextItem:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",permalink:"/shopping-cart-retrospective"}},a={authorsImageUrls:[]},o=[{value:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815",id:"\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158\uc5d0\uc11c\uc758-\uc0c1\ud488-\ucd94\uac00-\ubc0f-\uc218\uc815",level:3},{value:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",id:"\uc911\ubcf5\uacfc-\uc6b0\ubc1c\uc801-\uc911\ubcf5",level:3},{value:"\ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c",id:"\ud558\ub098\ub85c-\uc0ac\uc6a9\ud558\ub294-\uac74-\uc548\uc88b\uc544\ubcf4\uc774\uace0-\uc911\ubcf5\uc740-\uc81c\uac70\ud558\uace0-\uc2f6\uc740-\ub9c8\uc74c",level:3},{value:"\uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc",id:"\uc911\ubcf5-\uc81c\uac70-\uc804-\ucf54\ub4dc",level:3},{value:"\uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30",id:"\uc778\ud130\ud398\uc774\uc2a4-\uc791\uc131\ud558\uae30",level:3},{value:"\uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30",id:"\uad6c\ud604\uccb4-\uc791\uc131\ud558\uae30",level:3},{value:"\uc815\ub9ac",id:"\uc815\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,c.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uccad\uc5d0 \ub2f4\uae34 Body\ub97c \ud1b5\ud574 \uc804\ub2ec\ubc1b\uc740 \uac12\uc744 DTO\ub85c \ub9e4\ud551\ud558\uc5ec \ucd94\uac00\uc640 \uc218\uc815\uc744 \ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158\uc5d0\uc11c\uc758-\uc0c1\ud488-\ucd94\uac00-\ubc0f-\uc218\uc815",children:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf51",src:r(92725).Z+"",width:"2028",height:"704"})}),"\n",(0,t.jsxs)(n.p,{children:["\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d\ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0\uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc704 \uacbd\uc6b0\ub294 \uc911\ubcf5\uc77c\uae4c? \uc911\ubcf5\uc774 \uc544\ub2d0\uae4c?"]}),"\n",(0,t.jsx)(n.p,{children:"\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ub9ac\ubdf0\ub97c \ubc1b\uc558\ub2e4."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ProductSaveRequest"}),"\uc640 ",(0,t.jsx)(n.code,{children:"ProductUpdateRequest"}),"\uac00 \uc644\uc804\ud788 \ub3d9\uc77c\ud55c\ub370, \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc744\uae4c? \ub77c\ub294 \ub9ac\ubdf0\ub97c \ub0a8\uacbc\uc5c8\uc5b4\uc694. \uc0ac\uc2e4 \uc0dd\uc131\uacfc \uc218\uc815\uc740 \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac1c\uc5f0\uc131\uc774 \ub192\uc544\uc11c \ubbf8\ub9ac \ubd84\ub9ac\ud574\ub193\ub294 \uac8c \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\uae34 \ud55c\ub370, \uadf8\ub798\ub3c4 \uc911\ubcf5\uc740 \uc2eb\uc5b4\uc11c \uc800\ub3c4 \uc694\uc998 \uc774\ub7f0\uc800\ub7f0 \ubc29\ubc95\ub4e4\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub294 \uc911 \uc785\ub2c8\ub2e4. \ud5c8\ube0c\ub294 \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc5b4\ub5a4 \uc0dd\uac01\uc744 \uac00\uc9c0\uace0 \uc788\uc744\uc9c0 \uad81\uae08\ud558\ub124\uc694 \u314e\u314e"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc9c8\ubb38\uc5d0 \ub300\ud574 \uc544\ub798\uc640 \uac19\uc774 \ub2f5\ubcc0\uc744 \ud588\ub2e4."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc800\uc7a5\uacfc \uc218\uc815\ud560 \ub54c \ud544\uc694\ud55c \ud544\ub4dc\uac12\uc774 \ub3d9\uc77c\ud558\uc5ec \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c\ub294 \ud558\ub098\ub85c \uc0ac\uc6a9\ud574\ub3c4 \ub41c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud558\uc9c0\ub9cc, \ub9d0\uc500\ud574\uc8fc\uc2e0\ub300\ub85c \uc694\uad6c\uc0ac\ud56d\uc774 \ubcc0\uacbd\ub41c\ub2e4\uba74 \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\ub2e4\uace0 \ud310\ub2e8\ud558\uc600\uc2b5\ub2c8\ub2e4!"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc911\ubcf5\uacfc-\uc6b0\ubc1c\uc801-\uc911\ubcf5",children:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5"}),"\n",(0,t.jsx)(n.p,{children:"\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec\uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uac70\uc9d3\ub41c \uc911\ubcf5, \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131\uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc704 \uc0c1\ud669\uc740 \uc6b0\ubc1c\uc801 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc778\ub2e4. \uadf8\ub798\ub3c4 \uc911\ubcf5\uc744 \uc81c\uac70\ud574\ubcfc \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?"}),"\n",(0,t.jsx)(n.h3,{id:"\ud558\ub098\ub85c-\uc0ac\uc6a9\ud558\ub294-\uac74-\uc548\uc88b\uc544\ubcf4\uc774\uace0-\uc911\ubcf5\uc740-\uc81c\uac70\ud558\uace0-\uc2f6\uc740-\ub9c8\uc74c",children:"\ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c0\uae08\uc740 \ucd94\uac00, \uc218\uc815 2\uac00\uc9c0 \uacbd\uc6b0 \ubc16\uc5d0 \uc5c6\uc9c0\ub9cc \uc870\uae08 \ub354 \ubcf5\uc7a1\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc8fc\uc5b4\uc838\uc11c 10\uac00\uc9c0 \uacbd\uc6b0\ub85c \uc785\ub825\uc744 \ubc1b\uc73c\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c?",(0,t.jsx)(n.br,{}),"\n","\uc11c\ube44\uc2a4 \uacc4\uce35\uc5d0\uc11c\ub3c4 \uacc4\uce35\uc758 \ubd84\ub9ac\ub97c \uc704\ud574\uc11c \ub2e4\ub978 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uba74 20\uac1c\uc758 DTO\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud560\uae4c?",(0,t.jsx)(n.br,{}),"\n","\ub9ac\ubdf0\uc5b4\uac00 \uc54c\ub824\uc900 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud55c \ubc29\ubc95\uc744 \ud1b5\ud574 \uc774\ub97c \ud574\uacb0\ud574\ubcf4\uc790!"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc911\ubcf5-\uc81c\uac70-\uc804-\ucf54\ub4dc",children:"\uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc"}),"\n",(0,t.jsxs)(n.p,{children:["\ud604\uc7ac \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Controller\uc640 Service\uc5d0\uc11c \uc800\uc7a5, \uc218\uc815\ud560 \ub54c \uac01\uac01\uc758 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.\n\ud604\uc7ac DTO\ub294 controller, service \ud328\ud0a4\uc9c0 \ub0b4\uc5d0 \uc788\ub294 \uac83\uc774 \uc544\ub2c8\ub77c dto\ub77c\ub294 \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\ud558\uace0 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductService\n\u251c\u2500\u2500 dto\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf52",src:r(12314).Z+"",width:"1528",height:"912"})}),"\n",(0,t.jsx)(n.h3,{id:"\uc778\ud130\ud398\uc774\uc2a4-\uc791\uc131\ud558\uae30",children:"\uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf53",src:r(56531).Z+"",width:"1518",height:"904"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc11c\ube44\uc2a4 \ub808\uc774\uc5b4\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uac12\ub4e4\uc744 \uc778\ud130\ud398\uc774\uc2a4\ub85c \uc815\uc758\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 service \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub85c \uc62e\uaca8\uc900\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public interface ProductSaveRequest {\n\n String getName();\n\n String getImage();\n\n Long getPrice();\n}\n\n// ProductService\npublic Long save(final ProductSaveRequest request) {\n final Product product = new Product(request.getName(), request.getImage(), request.getPrice());\n return productDao.saveAndGetId(product);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uad6c\ud604\uccb4-\uc791\uc131\ud558\uae30",children:"\uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf54",src:r(82237).Z+"",width:"1508",height:"896"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c \uc791\uc131\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc791\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uccad\uc740 ProductRequest \ud074\ub798\uc2a4\ub85c \ubc1b\uace0, \uc11c\ube44\uc2a4\uc5d0 \uc804\ub2ec\ud560 \ub550 \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\uc758 \uba85\uc138\ub9cc \ub9de\ucd94\uba74 \ubb38\uc81c\uc5c6\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductController\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductRequest\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'public class ProductRequest implements ProductSaveRequest, ProductUpdateRequest {\n\n @NotBlank(message = "\uc774\ub984\uc740 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.")\n @Size(min = 1, max = 100, message = "\uc774\ub984\uc740 \ucd5c\uc18c {min}\uc790 \uc774\uc0c1, {max}\uc790 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.")\n private final String name;\n\n @NotBlank(message = "\uc774\ubbf8\uc9c0\ub294 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.")\n private final String image;\n\n @Range(message = "\uac00\uaca9\uc740 \ucd5c\uc18c {min}\uc6d0 \uc774\uc0c1, {max}\uc6d0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.")\n private final long price;\n\n public ProductRequest(final String name, final String image, final long price) {\n this.name = name;\n this.image = image;\n this.price = price;\n }\n\n @Override\n public String getName() {\n return name;\n }\n\n @Override\n public String getImage() {\n return image;\n }\n\n @Override\n public long getPrice() {\n return price;\n }\n}\n\n// ProductController\n@PostMapping("/products")\npublic ResponseEntity save(@Valid @RequestBody final ProductRequest request) {\n final Long id = productService.save(request);\n return ResponseEntity.created(URI.create("/products/" + id)).build();\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\uc815\ub9ac",children:"\uc815\ub9ac"}),"\n",(0,t.jsx)(n.p,{children:"\uc704\uc640 \uac19\uc774 \uad6c\ud604\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Service\uc5d0\uc11c \ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc5d0 \ub300\ud55c DTO\ub97c \uc54c\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uacf5\ud1b5\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 DTO\ub97c \uc81c\uc678\ud558\uace0 DTO \ud328\ud0a4\uc9c0\uc5d0 \ub300\ud55c \uacb0\ud569\ub3c4\uac00 \ub0ae\uc544\uc9c0\uace0, \uac01 \ub808\uc774\uc5b4\uc758 \uc751\uc9d1\ub3c4\uac00 \uc99d\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc694\uccad \uac1d\uccb4\ub9cc \ub2e4\ub974\uace0 \uc11c\ube44\uc2a4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ud589\uc704\ub97c \uc218\ud589\ud558\ub294 \uacbd\uc6b0 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc704 \ubc29\ubc95\uc744 \uc9c0\uae08 \ubbf8\uc158\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560\uae4c \ud558\ub2e4\uac00, \ub098\uc911\uc5d0 \ud544\uc694\ud560 \ub54c \uc801\uc6a9\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\uc544\uc11c \ubbf8\uc158\uc5d0\ub294 \uc801\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0c1\ud669\uc5d0 \ub9de\ucdb0 \uc801\uc7ac\uc801\uc18c\uc5d0 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud574\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98 16\uc7a5 \ub3c5\ub9bd\uc131, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://techblog.woowahan.com/2647/",children:"https://techblog.woowahan.com/2647/"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/",children:"https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/"})]})]})}function u(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var t=r(67294);function c(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(c[r]=e[r]);return c}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var a=t.createContext({}),o=function(e){var n=t.useContext(a),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,c=e.mdxType,i=e.originalType,a=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=o(r),h=c,g=p["".concat(a,".").concat(h)]||p[h]||d[h]||i;return r?t.createElement(g,s(s({ref:n},u),{},{components:r})):t.createElement(g,s({ref:n},u))}));u.displayName="MDXCreateElement"},92725:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf51-ccd4f91674b224578f2b295b3fccaf2c.png"},12314:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf52-0b4f9f493909fc139f0e4579f7569a6b.png"},56531:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf53-1b6b93bc790ba29844083df5b70dbd2c.png"},82237:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf54-15b381e0a024487f54608d438e5385f9.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6608],{54413:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>o});var t=r(85893),c=r(3905);const i={title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",slug:"accidental-duplication",tags:["DTO"]},s=void 0,l={permalink:"/accidental-duplication",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",source:"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",description:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",date:"2023-05-24T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 24\uc77c",tags:[{label:"DTO",permalink:"/tags/dto"}],readingTime:7.525,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",slug:"accidental-duplication",tags:["DTO"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",permalink:"/shopping-cart-retrospective"},nextItem:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",permalink:"/subway-retrospective"}},a={authorsImageUrls:[]},o=[{value:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815",id:"\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158\uc5d0\uc11c\uc758-\uc0c1\ud488-\ucd94\uac00-\ubc0f-\uc218\uc815",level:3},{value:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",id:"\uc911\ubcf5\uacfc-\uc6b0\ubc1c\uc801-\uc911\ubcf5",level:3},{value:"\ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c",id:"\ud558\ub098\ub85c-\uc0ac\uc6a9\ud558\ub294-\uac74-\uc548\uc88b\uc544\ubcf4\uc774\uace0-\uc911\ubcf5\uc740-\uc81c\uac70\ud558\uace0-\uc2f6\uc740-\ub9c8\uc74c",level:3},{value:"\uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc",id:"\uc911\ubcf5-\uc81c\uac70-\uc804-\ucf54\ub4dc",level:3},{value:"\uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30",id:"\uc778\ud130\ud398\uc774\uc2a4-\uc791\uc131\ud558\uae30",level:3},{value:"\uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30",id:"\uad6c\ud604\uccb4-\uc791\uc131\ud558\uae30",level:3},{value:"\uc815\ub9ac",id:"\uc815\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,c.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uccad\uc5d0 \ub2f4\uae34 Body\ub97c \ud1b5\ud574 \uc804\ub2ec\ubc1b\uc740 \uac12\uc744 DTO\ub85c \ub9e4\ud551\ud558\uc5ec \ucd94\uac00\uc640 \uc218\uc815\uc744 \ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158\uc5d0\uc11c\uc758-\uc0c1\ud488-\ucd94\uac00-\ubc0f-\uc218\uc815",children:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf51",src:r(92725).Z+"",width:"2028",height:"704"})}),"\n",(0,t.jsxs)(n.p,{children:["\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d\ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0\uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc704 \uacbd\uc6b0\ub294 \uc911\ubcf5\uc77c\uae4c? \uc911\ubcf5\uc774 \uc544\ub2d0\uae4c?"]}),"\n",(0,t.jsx)(n.p,{children:"\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ub9ac\ubdf0\ub97c \ubc1b\uc558\ub2e4."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ProductSaveRequest"}),"\uc640 ",(0,t.jsx)(n.code,{children:"ProductUpdateRequest"}),"\uac00 \uc644\uc804\ud788 \ub3d9\uc77c\ud55c\ub370, \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc744\uae4c? \ub77c\ub294 \ub9ac\ubdf0\ub97c \ub0a8\uacbc\uc5c8\uc5b4\uc694. \uc0ac\uc2e4 \uc0dd\uc131\uacfc \uc218\uc815\uc740 \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac1c\uc5f0\uc131\uc774 \ub192\uc544\uc11c \ubbf8\ub9ac \ubd84\ub9ac\ud574\ub193\ub294 \uac8c \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\uae34 \ud55c\ub370, \uadf8\ub798\ub3c4 \uc911\ubcf5\uc740 \uc2eb\uc5b4\uc11c \uc800\ub3c4 \uc694\uc998 \uc774\ub7f0\uc800\ub7f0 \ubc29\ubc95\ub4e4\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub294 \uc911 \uc785\ub2c8\ub2e4. \ud5c8\ube0c\ub294 \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc5b4\ub5a4 \uc0dd\uac01\uc744 \uac00\uc9c0\uace0 \uc788\uc744\uc9c0 \uad81\uae08\ud558\ub124\uc694 \u314e\u314e"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc9c8\ubb38\uc5d0 \ub300\ud574 \uc544\ub798\uc640 \uac19\uc774 \ub2f5\ubcc0\uc744 \ud588\ub2e4."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc800\uc7a5\uacfc \uc218\uc815\ud560 \ub54c \ud544\uc694\ud55c \ud544\ub4dc\uac12\uc774 \ub3d9\uc77c\ud558\uc5ec \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c\ub294 \ud558\ub098\ub85c \uc0ac\uc6a9\ud574\ub3c4 \ub41c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud558\uc9c0\ub9cc, \ub9d0\uc500\ud574\uc8fc\uc2e0\ub300\ub85c \uc694\uad6c\uc0ac\ud56d\uc774 \ubcc0\uacbd\ub41c\ub2e4\uba74 \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\ub2e4\uace0 \ud310\ub2e8\ud558\uc600\uc2b5\ub2c8\ub2e4!"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc911\ubcf5\uacfc-\uc6b0\ubc1c\uc801-\uc911\ubcf5",children:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5"}),"\n",(0,t.jsx)(n.p,{children:"\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec\uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uac70\uc9d3\ub41c \uc911\ubcf5, \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131\uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc704 \uc0c1\ud669\uc740 \uc6b0\ubc1c\uc801 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc778\ub2e4. \uadf8\ub798\ub3c4 \uc911\ubcf5\uc744 \uc81c\uac70\ud574\ubcfc \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?"}),"\n",(0,t.jsx)(n.h3,{id:"\ud558\ub098\ub85c-\uc0ac\uc6a9\ud558\ub294-\uac74-\uc548\uc88b\uc544\ubcf4\uc774\uace0-\uc911\ubcf5\uc740-\uc81c\uac70\ud558\uace0-\uc2f6\uc740-\ub9c8\uc74c",children:"\ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c0\uae08\uc740 \ucd94\uac00, \uc218\uc815 2\uac00\uc9c0 \uacbd\uc6b0 \ubc16\uc5d0 \uc5c6\uc9c0\ub9cc \uc870\uae08 \ub354 \ubcf5\uc7a1\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc8fc\uc5b4\uc838\uc11c 10\uac00\uc9c0 \uacbd\uc6b0\ub85c \uc785\ub825\uc744 \ubc1b\uc73c\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c?",(0,t.jsx)(n.br,{}),"\n","\uc11c\ube44\uc2a4 \uacc4\uce35\uc5d0\uc11c\ub3c4 \uacc4\uce35\uc758 \ubd84\ub9ac\ub97c \uc704\ud574\uc11c \ub2e4\ub978 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uba74 20\uac1c\uc758 DTO\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud560\uae4c?",(0,t.jsx)(n.br,{}),"\n","\ub9ac\ubdf0\uc5b4\uac00 \uc54c\ub824\uc900 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud55c \ubc29\ubc95\uc744 \ud1b5\ud574 \uc774\ub97c \ud574\uacb0\ud574\ubcf4\uc790!"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc911\ubcf5-\uc81c\uac70-\uc804-\ucf54\ub4dc",children:"\uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc"}),"\n",(0,t.jsxs)(n.p,{children:["\ud604\uc7ac \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Controller\uc640 Service\uc5d0\uc11c \uc800\uc7a5, \uc218\uc815\ud560 \ub54c \uac01\uac01\uc758 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.\n\ud604\uc7ac DTO\ub294 controller, service \ud328\ud0a4\uc9c0 \ub0b4\uc5d0 \uc788\ub294 \uac83\uc774 \uc544\ub2c8\ub77c dto\ub77c\ub294 \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\ud558\uace0 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductService\n\u251c\u2500\u2500 dto\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf52",src:r(12314).Z+"",width:"1528",height:"912"})}),"\n",(0,t.jsx)(n.h3,{id:"\uc778\ud130\ud398\uc774\uc2a4-\uc791\uc131\ud558\uae30",children:"\uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf53",src:r(56531).Z+"",width:"1518",height:"904"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc11c\ube44\uc2a4 \ub808\uc774\uc5b4\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uac12\ub4e4\uc744 \uc778\ud130\ud398\uc774\uc2a4\ub85c \uc815\uc758\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 service \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub85c \uc62e\uaca8\uc900\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public interface ProductSaveRequest {\n\n String getName();\n\n String getImage();\n\n Long getPrice();\n}\n\n// ProductService\npublic Long save(final ProductSaveRequest request) {\n final Product product = new Product(request.getName(), request.getImage(), request.getPrice());\n return productDao.saveAndGetId(product);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uad6c\ud604\uccb4-\uc791\uc131\ud558\uae30",children:"\uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf54",src:r(82237).Z+"",width:"1508",height:"896"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c \uc791\uc131\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc791\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uccad\uc740 ProductRequest \ud074\ub798\uc2a4\ub85c \ubc1b\uace0, \uc11c\ube44\uc2a4\uc5d0 \uc804\ub2ec\ud560 \ub550 \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\uc758 \uba85\uc138\ub9cc \ub9de\ucd94\uba74 \ubb38\uc81c\uc5c6\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductController\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductRequest\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'public class ProductRequest implements ProductSaveRequest, ProductUpdateRequest {\n\n @NotBlank(message = "\uc774\ub984\uc740 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.")\n @Size(min = 1, max = 100, message = "\uc774\ub984\uc740 \ucd5c\uc18c {min}\uc790 \uc774\uc0c1, {max}\uc790 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.")\n private final String name;\n\n @NotBlank(message = "\uc774\ubbf8\uc9c0\ub294 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.")\n private final String image;\n\n @Range(message = "\uac00\uaca9\uc740 \ucd5c\uc18c {min}\uc6d0 \uc774\uc0c1, {max}\uc6d0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.")\n private final long price;\n\n public ProductRequest(final String name, final String image, final long price) {\n this.name = name;\n this.image = image;\n this.price = price;\n }\n\n @Override\n public String getName() {\n return name;\n }\n\n @Override\n public String getImage() {\n return image;\n }\n\n @Override\n public long getPrice() {\n return price;\n }\n}\n\n// ProductController\n@PostMapping("/products")\npublic ResponseEntity save(@Valid @RequestBody final ProductRequest request) {\n final Long id = productService.save(request);\n return ResponseEntity.created(URI.create("/products/" + id)).build();\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\uc815\ub9ac",children:"\uc815\ub9ac"}),"\n",(0,t.jsx)(n.p,{children:"\uc704\uc640 \uac19\uc774 \uad6c\ud604\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Service\uc5d0\uc11c \ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc5d0 \ub300\ud55c DTO\ub97c \uc54c\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uacf5\ud1b5\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 DTO\ub97c \uc81c\uc678\ud558\uace0 DTO \ud328\ud0a4\uc9c0\uc5d0 \ub300\ud55c \uacb0\ud569\ub3c4\uac00 \ub0ae\uc544\uc9c0\uace0, \uac01 \ub808\uc774\uc5b4\uc758 \uc751\uc9d1\ub3c4\uac00 \uc99d\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc694\uccad \uac1d\uccb4\ub9cc \ub2e4\ub974\uace0 \uc11c\ube44\uc2a4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ud589\uc704\ub97c \uc218\ud589\ud558\ub294 \uacbd\uc6b0 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc704 \ubc29\ubc95\uc744 \uc9c0\uae08 \ubbf8\uc158\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560\uae4c \ud558\ub2e4\uac00, \ub098\uc911\uc5d0 \ud544\uc694\ud560 \ub54c \uc801\uc6a9\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\uc544\uc11c \ubbf8\uc158\uc5d0\ub294 \uc801\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0c1\ud669\uc5d0 \ub9de\ucdb0 \uc801\uc7ac\uc801\uc18c\uc5d0 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud574\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98 16\uc7a5 \ub3c5\ub9bd\uc131, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://techblog.woowahan.com/2647/",children:"https://techblog.woowahan.com/2647/"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/",children:"https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/"})]})]})}function u(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var t=r(67294);function c(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(c[r]=e[r]);return c}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var a=t.createContext({}),o=function(e){var n=t.useContext(a),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,c=e.mdxType,i=e.originalType,a=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=o(r),h=c,g=p["".concat(a,".").concat(h)]||p[h]||d[h]||i;return r?t.createElement(g,s(s({ref:n},u),{},{components:r})):t.createElement(g,s({ref:n},u))}));u.displayName="MDXCreateElement"},92725:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf51-ccd4f91674b224578f2b295b3fccaf2c.png"},12314:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf52-0b4f9f493909fc139f0e4579f7569a6b.png"},56531:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf53-1b6b93bc790ba29844083df5b70dbd2c.png"},82237:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf54-15b381e0a024487f54608d438e5385f9.png"}}]); \ No newline at end of file diff --git a/assets/js/70834889.15e53e1e.js b/assets/js/70834889.29b52f30.js similarity index 97% rename from assets/js/70834889.15e53e1e.js rename to assets/js/70834889.29b52f30.js index 5a7fa11c8..036e73d48 100644 --- a/assets/js/70834889.15e53e1e.js +++ b/assets/js/70834889.29b52f30.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7344],{56135:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var r=n(85893),s=n(3905);const i={title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",slug:"performance-test-type",tags:["performance test"]},a=void 0,o={permalink:"/performance-test-type",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",source:"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",description:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8",date:"2023-09-10T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 10\uc77c",tags:[{label:"performance test",permalink:"/tags/performance-test"}],readingTime:5.8,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",slug:"performance-test-type",tags:["performance test"]},unlisted:!1,prevItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"},nextItem:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",permalink:"/db-replication"}},l={authorsImageUrls:[]},c=[{value:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8",id:"\uc131\ub2a5-\ud14c\uc2a4\ud2b8",level:2},{value:"\uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)",id:"\uc2a4\ubaa8\ud06c-\ud14c\uc2a4\ud2b8smoke-test",level:3},{value:"\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)",id:"\uc2a4\ud30c\uc774\ud06c-\ud14c\uc2a4\ud2b8spike-test",level:3},{value:"\ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)",id:"\ubd80\ud558-\ud14c\uc2a4\ud2b8load-test",level:3},{value:"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test)",id:"\uc2a4\ud2b8\ub808\uc2a4-\ud14c\uc2a4\ud2b8stress-test",level:3},{value:"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test)",id:"\ub0b4\uad6c-\ud14c\uc2a4\ud2b8endurance-test",level:3},{value:"\uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)",id:"\uc911\ub2e8\uc810-\ud14c\uc2a4\ud2b8breakpoint-test",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",h2:"h2",h3:"h3",img:"img",p:"p",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h2,{id:"\uc131\ub2a5-\ud14c\uc2a4\ud2b8",children:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsx)(t.p,{children:"API\uc758 \uc694\uccad\uc774 \ub9ce\uc740 \uc0c1\ud669\uc5d0\uc11c \uc11c\ubc84\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2dc\uc2a4\ud15c\uc5d0 \ubd80\ud558\uac00 \uac78\ub9ac\uba74 \ubb38\uc81c \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\uc591\ud55c \uc0c1\ud669\uc5d0 \ub300\ube44\ud574\uc11c \uc131\ub2a5 \ud14c\uc2a4\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"./test.png",src:n(38715).Z+"",width:"2168",height:"1002"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ubaa8\ud06c-\ud14c\uc2a4\ud2b8smoke-test",children:"\uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ucd5c\uc18c\ud55c\uc758 \ubd80\ud558\ub97c \uc8fc\uc5b4 \uc2dc\uc2a4\ud15c\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["VU\ub97c \ucd5c\uc18c\ud55c\uc73c\ub85c \ub450\uace0, \uc9e7\uc740 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \ud14c\uc2a4\ud2b8\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud568\uc73c\ub85c\uc368 \ud14c\uc2a4\ud2b8 \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc624\ub958\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uace0, \uc131\ub2a5 \uc9c0\ud45c\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc9d1, \ubaa8\ub2c8\ud130\ub9c1 \ub418\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"\uac00\uc0c1 \uc0ac\uc6a9\uc790(VU)",type:"note",children:(0,r.jsxs)(t.p,{children:["\uac00\uc0c1 \uc0ac\uc6a9\uc790\ub294 \uc11c\ubc84 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ub300\ud574 \ud2b9\uc815 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \ub2e4\ub978 \uac00\uc0c1 \uc0ac\uc6a9\uc790\uc640 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uba70, \uc5ec\ub7ec \uac00\uc0c1 \uc0ac\uc6a9\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc2dc \uc5f0\uacb0\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ub808\ub4dc\ub77c\uace0 \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud30c\uc774\ud06c-\ud14c\uc2a4\ud2b8spike-test",children:"\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc0ac\uc6a9\ub7c9\uc774 \uae09\uc99d\ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uacac\ub514\uace0 \uc131\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ud2f0\ucf13 \ubc1c\uae09, \ud560\uc778 \ucfe0\ud3f0 \ubc1c\uae09\uacfc \uac19\uc740 \uc774\ubca4\ud2b8\ub97c \ud558\ub294 \uacbd\uc6b0 \ub300\uaddc\ubaa8 \ud2b8\ub798\ud53d\uc774 \ub4e4\uc5b4\uc628\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uae09\uc99d\ud558\ub294 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\uace0, \ubd80\ud558\ub97c \uc798 \ubc84\ud2f0\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ubd80\ud558-\ud14c\uc2a4\ud2b8load-test",children:"\ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ubaa9\ud46f\uac12\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \uacac\ub51c \uc218 \uc788\uc744\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uc77c\ubc18\uc801\uc778 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub7a8\ud504\uc5c5 \ub610\ub294 \ubb19\ud46f\uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ubd80\ud558 \uae30\uac04\ub3d9\uc548 \uc131\ub2a5\uc774 \ubb38\uc81c\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uace0, \uc2dc\uc2a4\ud15c \ubcc0\uacbd \ud6c4\uc5d0\ub3c4 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ub3d9\uc77c\ud558\uac8c \ubaa9\ud46f\uac12\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"\ub7a8\ud504 \uc5c5(Ramp-up)",type:"note",children:(0,r.jsx)(t.p,{children:"\ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574 \uc124\uc815\ud55c \uac00\uc0c1 \uc0ac\uc6a9\uc790 \uc218\uc5d0 \ub3c4\ub2ec\ud558\ub294 \ub370 \uac78\ub9ac\ub294 \uc2dc\uac04"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud2b8\ub808\uc2a4-\ud14c\uc2a4\ud2b8stress-test",children:"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc2dc\uc2a4\ud15c\uc758 \ucd5c\ub300\uce58\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \ubc1b\uc558\uc744 \ub54c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uadf8\ub798\ud504\ub97c \ubd24\uc744 \ub54c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc640 \uc720\uc0ac\ud55c \ud615\ud0dc\ub85c \ubcf4\uc774\uc9c0\ub9cc, \ubd80\ud558\ub7c9\uc774 \ub2e4\ub974\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c \ud3c9\uade0\uc801\uc778 \ubaa9\ud46f\uac12 \ub300\ube44 \uc791\uac8c\ub294 50% \uc774\uc0c1, \ud544\uc694\uc758 \uacbd\uc6b0 \uadf8 \uc774\uc0c1\uc73c\ub85c \ubd80\ud558\ub97c \uc900\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub294 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c \ud6c4\uc5d0\ub9cc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4. \ubd80\ud558 \ud14c\uc2a4\ud2b8\uac00 \uc774\ub8e8\uc5b4\uc9c0\uc9c0 \uc54a\uc740 \uc0c1\ud669\uc5d0\uc11c \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \ubcd1\ubaa9 \uc9c0\uc810\uc774\ub098 \ubb38\uc81c \uc0c1\ud669\uc744 \ucc3e\uae30 \uc5b4\ub824\uc6cc\uc9c4\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub610\ud55c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c VU\uac12(\uc2a4\ub808\ub4dc \uc218)\ub9cc \uc218\uc815\ud558\uc5ec \uc7ac\uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ub0b4\uad6c-\ud14c\uc2a4\ud2b8endurance-test",children:"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ud3c9\uade0 \uc0ac\uc6a9\ub960\ub85c \uc77c\uc815 \ubd80\ud558\ub97c \uc9c0\uc18d\uc801\uc73c\ub85c \uc8fc\uba70 \uc2dc\uc2a4\ud15c\uc774 \ubb38\uc81c\ub418\ub294 \uc9c0\uc810\uc744 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ud761\uc218 \ud14c\uc2a4\ud2b8(Soak Test)\ub77c\uace0\ub3c4 \ud558\uba70, \uae30\ubcf8\uc801\uc778 \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc758 \ubcc0\ud615\uc774\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc640 \ub2ec\ub9ac \uae34 \uc2dc\uac04\ub3d9\uc548 \ud14c\uc2a4\ud2b8\ub97c \ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\uba70, \uba54\ubaa8\ub9ac \ub204\uc218 \ubb38\uc81c\uc640 \uac19\uc774 \uc7a5\uc2dc\uac04 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud560 \ub54c \uc2dc\uc2a4\ud15c\uc758 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \ubd80\ubd84\uc744 \ud655\uc778\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc911\ub2e8\uc810-\ud14c\uc2a4\ud2b8breakpoint-test",children:"\uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc784\uacc4 \uc9c0\uc810\uc744 \ucc3e\uae30 \uc704\ud574 \ubd80\ud558\ub97c \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a4\uba70 \uc9c4\ud589\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ubb38\uc81c\ub418\ub294 \ubd80\ubd84\uc744 \ub354 \ube68\ub9ac \ucc3e\uae30 \uc704\ud574 \ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\ud55c \ub2e4\uc74c\uc5d0 \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud558\uace0, \uc774 \ub54c \uc810\uc9c4\uc801\uc73c\ub85c \ubd80\ud558\ub97c \ub298\ub824\ub098\uac00\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc131\ub2a5 \ud29c\ub2dd\uacfc \ubc18\ubcf5\ud574\uc11c \uc9c4\ud589\ud55c\ub2e4\uba74, \uc2dc\uc2a4\ud15c\uc744 \ub354\uc6b1 \ubc1c\uc804\uc2dc\ud0ac \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub9cc Auto Scaling\uc774 \uc801\uc6a9\ub41c \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c\ub294 \uc9c4\ud589\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://k6.io/docs/test-types/load-test-types/",children:"Load test types, k6"}),(0,r.jsx)(t.br,{}),"\n","\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc",(0,r.jsx)(t.br,{}),"\n","\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"]})]})}function d(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),h=c(n),u=s,j=h["".concat(l,".").concat(u)]||h[u]||p[u]||i;return n?r.createElement(j,a(a({ref:t},d),{},{components:n})):r.createElement(j,a({ref:t},d))}));d.displayName="MDXCreateElement"},38715:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/test-355aba93f96ef7d6a0f3161bf6a9c25e.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7344],{56135:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var r=n(85893),s=n(3905);const i={title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",slug:"performance-test-type",tags:["performance test"]},a=void 0,o={permalink:"/performance-test-type",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",source:"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",description:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8",date:"2023-09-10T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 10\uc77c",tags:[{label:"performance test",permalink:"/tags/performance-test"}],readingTime:5.8,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",slug:"performance-test-type",tags:["performance test"]},unlisted:!1,prevItem:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",permalink:"/db-replication"},nextItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"}},l={authorsImageUrls:[]},c=[{value:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8",id:"\uc131\ub2a5-\ud14c\uc2a4\ud2b8",level:2},{value:"\uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)",id:"\uc2a4\ubaa8\ud06c-\ud14c\uc2a4\ud2b8smoke-test",level:3},{value:"\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)",id:"\uc2a4\ud30c\uc774\ud06c-\ud14c\uc2a4\ud2b8spike-test",level:3},{value:"\ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)",id:"\ubd80\ud558-\ud14c\uc2a4\ud2b8load-test",level:3},{value:"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test)",id:"\uc2a4\ud2b8\ub808\uc2a4-\ud14c\uc2a4\ud2b8stress-test",level:3},{value:"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test)",id:"\ub0b4\uad6c-\ud14c\uc2a4\ud2b8endurance-test",level:3},{value:"\uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)",id:"\uc911\ub2e8\uc810-\ud14c\uc2a4\ud2b8breakpoint-test",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",h2:"h2",h3:"h3",img:"img",p:"p",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h2,{id:"\uc131\ub2a5-\ud14c\uc2a4\ud2b8",children:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsx)(t.p,{children:"API\uc758 \uc694\uccad\uc774 \ub9ce\uc740 \uc0c1\ud669\uc5d0\uc11c \uc11c\ubc84\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2dc\uc2a4\ud15c\uc5d0 \ubd80\ud558\uac00 \uac78\ub9ac\uba74 \ubb38\uc81c \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\uc591\ud55c \uc0c1\ud669\uc5d0 \ub300\ube44\ud574\uc11c \uc131\ub2a5 \ud14c\uc2a4\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"./test.png",src:n(38715).Z+"",width:"2168",height:"1002"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ubaa8\ud06c-\ud14c\uc2a4\ud2b8smoke-test",children:"\uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ucd5c\uc18c\ud55c\uc758 \ubd80\ud558\ub97c \uc8fc\uc5b4 \uc2dc\uc2a4\ud15c\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["VU\ub97c \ucd5c\uc18c\ud55c\uc73c\ub85c \ub450\uace0, \uc9e7\uc740 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \ud14c\uc2a4\ud2b8\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud568\uc73c\ub85c\uc368 \ud14c\uc2a4\ud2b8 \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc624\ub958\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uace0, \uc131\ub2a5 \uc9c0\ud45c\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc9d1, \ubaa8\ub2c8\ud130\ub9c1 \ub418\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"\uac00\uc0c1 \uc0ac\uc6a9\uc790(VU)",type:"note",children:(0,r.jsxs)(t.p,{children:["\uac00\uc0c1 \uc0ac\uc6a9\uc790\ub294 \uc11c\ubc84 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ub300\ud574 \ud2b9\uc815 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \ub2e4\ub978 \uac00\uc0c1 \uc0ac\uc6a9\uc790\uc640 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uba70, \uc5ec\ub7ec \uac00\uc0c1 \uc0ac\uc6a9\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc2dc \uc5f0\uacb0\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ub808\ub4dc\ub77c\uace0 \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud30c\uc774\ud06c-\ud14c\uc2a4\ud2b8spike-test",children:"\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc0ac\uc6a9\ub7c9\uc774 \uae09\uc99d\ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uacac\ub514\uace0 \uc131\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ud2f0\ucf13 \ubc1c\uae09, \ud560\uc778 \ucfe0\ud3f0 \ubc1c\uae09\uacfc \uac19\uc740 \uc774\ubca4\ud2b8\ub97c \ud558\ub294 \uacbd\uc6b0 \ub300\uaddc\ubaa8 \ud2b8\ub798\ud53d\uc774 \ub4e4\uc5b4\uc628\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uae09\uc99d\ud558\ub294 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\uace0, \ubd80\ud558\ub97c \uc798 \ubc84\ud2f0\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ubd80\ud558-\ud14c\uc2a4\ud2b8load-test",children:"\ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ubaa9\ud46f\uac12\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \uacac\ub51c \uc218 \uc788\uc744\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uc77c\ubc18\uc801\uc778 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub7a8\ud504\uc5c5 \ub610\ub294 \ubb19\ud46f\uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ubd80\ud558 \uae30\uac04\ub3d9\uc548 \uc131\ub2a5\uc774 \ubb38\uc81c\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uace0, \uc2dc\uc2a4\ud15c \ubcc0\uacbd \ud6c4\uc5d0\ub3c4 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ub3d9\uc77c\ud558\uac8c \ubaa9\ud46f\uac12\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"\ub7a8\ud504 \uc5c5(Ramp-up)",type:"note",children:(0,r.jsx)(t.p,{children:"\ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574 \uc124\uc815\ud55c \uac00\uc0c1 \uc0ac\uc6a9\uc790 \uc218\uc5d0 \ub3c4\ub2ec\ud558\ub294 \ub370 \uac78\ub9ac\ub294 \uc2dc\uac04"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud2b8\ub808\uc2a4-\ud14c\uc2a4\ud2b8stress-test",children:"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc2dc\uc2a4\ud15c\uc758 \ucd5c\ub300\uce58\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \ubc1b\uc558\uc744 \ub54c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\uadf8\ub798\ud504\ub97c \ubd24\uc744 \ub54c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc640 \uc720\uc0ac\ud55c \ud615\ud0dc\ub85c \ubcf4\uc774\uc9c0\ub9cc, \ubd80\ud558\ub7c9\uc774 \ub2e4\ub974\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c \ud3c9\uade0\uc801\uc778 \ubaa9\ud46f\uac12 \ub300\ube44 \uc791\uac8c\ub294 50% \uc774\uc0c1, \ud544\uc694\uc758 \uacbd\uc6b0 \uadf8 \uc774\uc0c1\uc73c\ub85c \ubd80\ud558\ub97c \uc900\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub294 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c \ud6c4\uc5d0\ub9cc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4. \ubd80\ud558 \ud14c\uc2a4\ud2b8\uac00 \uc774\ub8e8\uc5b4\uc9c0\uc9c0 \uc54a\uc740 \uc0c1\ud669\uc5d0\uc11c \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \ubcd1\ubaa9 \uc9c0\uc810\uc774\ub098 \ubb38\uc81c \uc0c1\ud669\uc744 \ucc3e\uae30 \uc5b4\ub824\uc6cc\uc9c4\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub610\ud55c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c VU\uac12(\uc2a4\ub808\ub4dc \uc218)\ub9cc \uc218\uc815\ud558\uc5ec \uc7ac\uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ub0b4\uad6c-\ud14c\uc2a4\ud2b8endurance-test",children:"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test)"}),"\n",(0,r.jsx)(t.p,{children:"\ud3c9\uade0 \uc0ac\uc6a9\ub960\ub85c \uc77c\uc815 \ubd80\ud558\ub97c \uc9c0\uc18d\uc801\uc73c\ub85c \uc8fc\uba70 \uc2dc\uc2a4\ud15c\uc774 \ubb38\uc81c\ub418\ub294 \uc9c0\uc810\uc744 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ud761\uc218 \ud14c\uc2a4\ud2b8(Soak Test)\ub77c\uace0\ub3c4 \ud558\uba70, \uae30\ubcf8\uc801\uc778 \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc758 \ubcc0\ud615\uc774\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc640 \ub2ec\ub9ac \uae34 \uc2dc\uac04\ub3d9\uc548 \ud14c\uc2a4\ud2b8\ub97c \ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\uba70, \uba54\ubaa8\ub9ac \ub204\uc218 \ubb38\uc81c\uc640 \uac19\uc774 \uc7a5\uc2dc\uac04 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud560 \ub54c \uc2dc\uc2a4\ud15c\uc758 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \ubd80\ubd84\uc744 \ud655\uc778\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc911\ub2e8\uc810-\ud14c\uc2a4\ud2b8breakpoint-test",children:"\uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)"}),"\n",(0,r.jsx)(t.p,{children:"\uc784\uacc4 \uc9c0\uc810\uc744 \ucc3e\uae30 \uc704\ud574 \ubd80\ud558\ub97c \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a4\uba70 \uc9c4\ud589\ud558\ub294 \ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsxs)(t.p,{children:["\ubb38\uc81c\ub418\ub294 \ubd80\ubd84\uc744 \ub354 \ube68\ub9ac \ucc3e\uae30 \uc704\ud574 \ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\ud55c \ub2e4\uc74c\uc5d0 \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud558\uace0, \uc774 \ub54c \uc810\uc9c4\uc801\uc73c\ub85c \ubd80\ud558\ub97c \ub298\ub824\ub098\uac00\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc131\ub2a5 \ud29c\ub2dd\uacfc \ubc18\ubcf5\ud574\uc11c \uc9c4\ud589\ud55c\ub2e4\uba74, \uc2dc\uc2a4\ud15c\uc744 \ub354\uc6b1 \ubc1c\uc804\uc2dc\ud0ac \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub9cc Auto Scaling\uc774 \uc801\uc6a9\ub41c \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c\ub294 \uc9c4\ud589\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://k6.io/docs/test-types/load-test-types/",children:"Load test types, k6"}),(0,r.jsx)(t.br,{}),"\n","\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc",(0,r.jsx)(t.br,{}),"\n","\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"]})]})}function d(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>c});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),h=c(n),u=s,j=h["".concat(l,".").concat(u)]||h[u]||p[u]||i;return n?r.createElement(j,a(a({ref:t},d),{},{components:n})):r.createElement(j,a({ref:t},d))}));d.displayName="MDXCreateElement"},38715:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/test-355aba93f96ef7d6a0f3161bf6a9c25e.png"}}]); \ No newline at end of file diff --git a/assets/js/7159c7ff.9f77b884.js b/assets/js/7159c7ff.97797bc2.js similarity index 99% rename from assets/js/7159c7ff.9f77b884.js rename to assets/js/7159c7ff.97797bc2.js index 89b6abf50..17b7dad07 100644 --- a/assets/js/7159c7ff.9f77b884.js +++ b/assets/js/7159c7ff.97797bc2.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3287],{67219:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>d});var i=t(85893),r=t(3905);const o={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",slug:"route-image-implementation",tags:["image","awt"]},a=void 0,s={permalink:"/route-image-implementation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",source:"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",description:"\uac1c\uc694",date:"2023-08-02T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 2\uc77c",tags:[{label:"image",permalink:"/tags/image"},{label:"awt",permalink:"/tags/awt"}],readingTime:11.665,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",slug:"route-image-implementation",tags:["image","awt"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",permalink:"/route-image-async-with-event"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",permalink:"/route-image-python"}},l={authorsImageUrls:[]},d=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:2},{value:"\uad6c\ud604 \uacb0\uacfc",id:"\uad6c\ud604-\uacb0\uacfc",level:3},{value:"IMAGE_SIZE & ROUTE_SIZE",id:"image_size--route_size",level:3},{value:"\uc8fc\uc694 \ud074\ub798\uc2a4",id:"\uc8fc\uc694-\ud074\ub798\uc2a4",level:2},{value:"\uc694\uc57d",id:"\uc694\uc57d",level:3},{value:"\uc758\uc874\uad00\uacc4",id:"\uc758\uc874\uad00\uacc4",level:3},{value:"Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)",id:"coordinates\uc704\ub3c4-\uacbd\ub3c4\uc758-\uc77c\uae09-\uceec\ub809\uc158",level:3},{value:"Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)",id:"positions\uc2e4\uc81c-\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc5d0-\uc0ac\uc6a9\ud560-\uc704\uce58",level:3},{value:"RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)",id:"routeimagedrawer\uc2e4\uc81c-\uc774\ubbf8\uc9c0\uc5d0-\uacbd\ub85c\ub97c-\uadf8\ub824\uc8fc\ub294-\ud074\ub798\uc2a4",level:3},{value:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow",id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131-flow",level:2},{value:"1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44",id:"1-\uc774\ubbf8\uc9c0-\uc0dd\uc131-\uc900\ube44",level:3},{value:"2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad",id:"2-\uc120-\uadf8\ub9ac\uae30-\uc694\uccad",level:3},{value:"3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad",id:"3-\uc704\uce58-\uc810-\uadf8\ub9ac\uae30-\uc694\uccad",level:3},{value:"4. \uc5c5\ub85c\ub4dc \uc694\uccad",id:"4-\uc5c5\ub85c\ub4dc-\uc694\uccad",level:3},{value:"\uc804\uccb4 Flow",id:"\uc804\uccb4-flow",level:3}];function c(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,i.jsxs)(n.p,{children:["\uc5ec\ud589\uc5d0 \ub300\ud55c \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\uae30 \uc704\ud574 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d \ubc0f \uae30\uc220 \uc120\ud0dd\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 ",(0,i.jsx)(n.a,{href:"./route-image-intro",children:"\ub9c1\ud06c"}),"\uc5d0 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\uad6c\ud604-\uacb0\uacfc",children:"\uad6c\ud604 \uacb0\uacfc"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./result.png",src:t(59563).Z+"",width:"1840",height:"714"})}),"\n",(0,i.jsxs)(n.p,{children:["\uc608\uc2dc \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.strong,{children:"\uc11c\uc6b8\uc5ed(\uc810)"})," \u2192 \uc2e0\uc0ac\uc5ed \u2192 \ub178\ub7c9\uc9c4\uc5ed \u2192 \ud64d\ub300\uc785\uad6c\uc5ed \u2192 \uc885\ub85c3\uac00\uc5ed \u2192 \uc625\uc218\uc5ed \u2192 ",(0,i.jsx)(n.strong,{children:"\uad6c\ub85c\uc5ed(\uc810)"})," \u2192 \uc2e0\ub9bc\uc5ed \u2192 \ubc1c\uc0b0\uc5ed"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="\uc608\uc2dc \ub370\uc774\ud130"',children:"List x = List.of(\n 126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,\n 126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639\n);\nList y = List.of(\n 37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,\n 37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184\n);\nList xPoints = List.of(126.97094933811682, 126.88474839801178);\nList yPoints = List.of(37.55302829553499, 37.50129417536773);\n"})}),"\n",(0,i.jsx)(n.h3,{id:"image_size--route_size",children:"IMAGE_SIZE & ROUTE_SIZE"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageGenerator.java"',children:"private static final int IMAGE_SIZE = 800;\nprivate static final int ROUTE_SIZE = 600;\n"})}),"\n",(0,i.jsxs)(n.p,{children:["\ucf54\ub4dc\ub97c \ubcf4\uba74 IMAGE_SIZE\uc640 ROUTE_SIZE\uac00 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","IMAGE_SIZE\ub294 \ub9d0 \uadf8\ub300\ub85c \uc774\ubbf8\uc9c0\uc758 width\uc640 height\ub97c \uc758\ubbf8\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","ROUTE_SIZE\uc758 \uacbd\uc6b0 \uc0c1\ud558\uc88c\uc6b0 100px \ub9cc\ud07c\uc758 \uac04\uaca9\uc744 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc2e4\uc81c \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub294 600 * 600 \uc0ac\uc774\uc988\ub85c \uc0dd\uc131\ub41c\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./600.png",src:t(49812).Z+"",width:"976",height:"970"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"\uc0ac\uc774\uc988 \ubcc0\uacbd\uc758 \uc774\uc720"})}),"\n",(0,i.jsx)(n.p,{children:"255 * 255 \uc815\ub3c4\uc758 \uc791\uc740 \uc0ac\uc774\uc988\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud574\ubcf4\ub824\uace0 \ud588\ub294\ub370, \uc774\ubbf8\uc9c0\uc758 \uc120\uba85\ub3c4\uac00 \uc88b\uc9c0 \uc54a\uc544 800 * 800 \uc0ac\uc774\uc988\ub85c \ubcc0\uacbd\ud588\ub2e4."}),"\n",(0,i.jsx)(n.h2,{id:"\uc8fc\uc694-\ud074\ub798\uc2a4",children:"\uc8fc\uc694 \ud074\ub798\uc2a4"}),"\n",(0,i.jsx)(n.h3,{id:"\uc694\uc57d",children:"\uc694\uc57d"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"\ud074\ub798\uc2a4\uba85"}),(0,i.jsx)(n.th,{children:"\uc124\uba85"}),(0,i.jsx)(n.th,{children:"\ud2b9\uc774\uc0ac\ud56d"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Coordinate"}),(0,i.jsx)(n.td,{children:"\uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \uc704\uce58 \uac12"}),(0,i.jsx)(n.td,{children:"\uc88c\ud45c\ub97c \ub73b\ud558\uc9c0\ub9cc \uc5ec\ud589 \ub3c4\uba54\uc778\uc5d0 \ud3ec\ud568\ub41c Point \ud074\ub798\uc2a4\uc640 \uad6c\ubd84\ud558\uae30 \uc704\ud574 longitude, latitude\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 x, y \uc0ac\uc6a9"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Coordinates"}),(0,i.jsx)(n.td,{children:"Coordinate\uc758 \uc77c\uae09 \uceec\ub809\uc158"}),(0,i.jsx)(n.td,{children:"-"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Position"}),(0,i.jsx)(n.td,{children:"\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58 \uac12"}),(0,i.jsx)(n.td,{children:"Integer \ud0c0\uc785\uc758 x, y \uc0ac\uc6a9"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Positions"}),(0,i.jsx)(n.td,{children:"Positions\uc758 \uc77c\uae09 \uceec\ub809\uc158"}),(0,i.jsx)(n.td,{children:"-"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageDrawer"}),(0,i.jsx)(n.td,{children:"\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4 BufferedImage, Graphics2D\ub97c \uac00\uc9c0\uace0 \uc788\uc74c"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc0c1\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc74c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageUploader"}),(0,i.jsx)(n.td,{children:"BufferedImage\ub97c \ubc1b\uc544 \uc11c\ubc84\uc5d0 \uc5c5\ub85c\ub4dc \ud558\ub294 \ud074\ub798\uc2a4"}),(0,i.jsx)(n.td,{children:"\ud604\uc7ac \uc5c5\ub85c\ub4dc \uc704\uce58\uac00 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc544 \uc77c\ub2e8 \uae30\ubcf8(\ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8) \uc704\uce58\uc5d0 \uc0dd\uc131"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageGenerator"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uace0 \uc5c5\ub85c\ub4dc\ud558\ub294 \uc11c\ube44\uc2a4"}),(0,i.jsx)(n.td,{children:"\uc5ec\ud589 \uc885\ub8cc, \uac10\uc0c1 \uc800\uc7a5\uc2dc \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"BufferedImage(AWT)"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0 \ub370\uc774\ud130\ub97c \ucc98\ub9ac\ud558\uace0 \uc870\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9"}),(0,i.jsx)(n.td,{children:"\uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c\uac00 (0, 0)"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Graphics2D(AWT)"}),(0,i.jsx)(n.td,{children:"\uc120 \uadf8\ub9ac\uae30, \uc0c9\uc0c1 \uad00\ub9ac \ub4f1\uc744 \uc9c0\uc6d0\ud558\ub294 \ud074\ub798\uc2a4 \uc2e4\uc81c \ud574\ub2f9 \ud074\ub798\uc2a4\uc758 draw \uba54\uc11c\ub4dc\ub97c \uacbd\ub85c\ub97c \uadf8\ub9bc"}),(0,i.jsx)(n.td,{children:"JDK 1.2 \uc774\ud6c4\uc5d0 \ucd94\uac00\ub428, 2D(\ud3c9\uba74) \uadf8\ub798\ud53d \ud658\uacbd\uc744 \uc9c0\uc6d0, bufferedImage.createGraphics \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \uc0dd\uc131"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"\uc758\uc874\uad00\uacc4",children:"\uc758\uc874\uad00\uacc4"}),"\n",(0,i.jsx)(n.mermaid,{value:'graph TD\n C1[Coordinates] --\x3e C[Coordinate]\n P1[Positions] --\x3e P[Position]\n\n\tRID[RouteImageDrawer] -- "\uc911\uc559 \uc815\ub82c\ub41c Positions\ub97c \ubc1b\uc544 \uc774\ubbf8\uc9c0 \uc0dd\uc131" --\x3e P1\n\tRID --\x3e B[BufferedImage]\n\tRID --\x3e G[Graphics2D]\n\n\tC1 -- "calculatePositions \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc704\uce58 \uacc4\uc0b0" --\x3e P1\n\n\tRIU[RouteImageUploader] --\x3e B\n\tRIG[RouteImageGenerator] --\x3e RID\n\tRIG --\x3e RIU\n\tRIG --\x3e C1\n\tRIG --\x3e P1'}),"\n",(0,i.jsx)(n.h3,{id:"coordinates\uc704\ub3c4-\uacbd\ub3c4\uc758-\uc77c\uae09-\uceec\ub809\uc158",children:"Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"List"})," 2\uac1c(\uc704\ub3c4, \uacbd\ub3c4)\uc778 \ud615\ud0dc\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uc5c8\uc9c0\ub9cc, \uc704\uce58 \uc810\uc744 \uc5ec\ub7ec\uac1c \ucc0d\ub294 \ubd80\ubd84\uc5d0\uc11c \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud574 \uc9c8 \uac83 \uac19\uc544\uc11c Coordinate(x, y)\uc640 \uc77c\uae09 \uceec\ub809\uc158\uc778 Coordinates\ub85c \uad00\ub9ac\ud558\uae30\ub85c \ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Coordinates \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub450 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"calculatePositions: \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub97c \ubc1b\uc544 \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \uc0ac\uc6a9\ub420 Positions\ub97c \ubc18\ud658"}),"\n",(0,i.jsx)(n.li,{children:"indexOf: \ub2e4\ub978 Coordinates\ub97c \ubc1b\uc544 \ub3d9\uc77c\ud55c \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4\ub97c \ubc18\ud658\ud558\ub294"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Positions \uacc4\uc0b0 \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc704\ub3c4, \uacbd\ub3c4 \uac01\uac01\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \ud544\uc694\ud55c \uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="Coordinates.java"',children:"// \ud638\ucd9c\n// List xPositions = toPositions(xValues, maxDifference, routeImageSize);\n// List yPositions = toPositions(yValues, maxDifference, routeImageSize);\n\nprivate List toPositions(List values, Double maxDifference, Integer routeImageSize) {\n Double minValue = Collections.min(values);\n return values.stream()\n .map(value -> normalizeCoordinate(value, maxDifference, minValue))\n .map(value -> mapToPosition(value, routeImageSize))\n .toList();\n}\n\nprivate double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {\n return (coordinate - minValue) / maxDifference;\n}\n\nprivate int mapToPosition(Double coordinate, Integer routeImageSize) {\n return (int) (coordinate * routeImageSize);\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\uc704\ub3c4\ub85c \uc608\uc2dc\ub4e0 \ub0b4\uc6a9\uc774\ub2e4."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Collections.min(values) \u2192 \uc704\ub3c4 \ub9ac\uc2a4\ud2b8\uc758 \ucd5c\uc18c\uac12\uc744 \uad6c\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.li,{children:["normalizeCoordinate \u2192 \uac01\uac01\uc758 \uc704\ub3c4 \uac12\uc5d0\uc11c \ucd5c\uc18c\uac12\uc744 \ube7c\uace0 0 ~ 1 \uc0ac\uc774 \uac12\uc73c\ub85c \ubcc0\ud658 \ud6c4 ",(0,i.jsx)(n.strong,{children:"\uc704\uacbd\ub3c4\uc758 \ucd5c\ub300 \ucc28\uc774"}),"\ub85c \ub098\ub208\ub2e4."]}),"\n",(0,i.jsx)(n.li,{children:"mapToPosition \u2192 \uadf8\ub798\ud504 \ud06c\uae30\ub97c \ubc1b\uc544 0 ~ 1 \uc0ac\uc774 \uac12\uc744 \uc2e4\uc81c \uc774\ubbf8\uc9c0\ub97c \uc704\ud55c \uc704\uce58\uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"positions\uc2e4\uc81c-\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc5d0-\uc0ac\uc6a9\ud560-\uc704\uce58",children:"Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)"}),"\n",(0,i.jsx)(n.p,{children:"Positions \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub2e4\uc12f \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"align: \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\uc640 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\ub97c \ubc1b\uc544 Position \uac12\ub4e4\uc744 \uc911\uc559 \uc815\ub82c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"getPositionsByIndexes: \uc778\ub371\uc2a4 \ub9ac\uc2a4\ud2b8\ub97c \ubc1b\uc544 \uc785\ub825\ubc1b\uc740 \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"size: \ud06c\uae30\ub97c \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"xPositions: x \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"yPositions: y \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uc559 \uc815\ub82c \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="Positions.java"',children:"public Positions align(int imageSize, int routeSize) {\n int xOffset = calculateOffset(Position::x, imageSize);\n int yOffset = calculateOffset(Position::y, imageSize);\n\n return items.stream()\n .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))\n .collect(collectingAndThen(toList(), Positions::new));\n}\n\nprivate int calculateOffset(ToIntFunction positionToInteger, int imageSize) {\n List positions = items.stream()\n .mapToInt(positionToInteger)\n .boxed()\n .toList();\n\n int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;\n return imageSize / 2 - midValue;\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["\uc0c1\ud558\uc88c\uc6b0 \uc5ec\ubc31\uc744 \ub3d9\uc77c\ud558\uac8c \uc8fc\uae30 \uc704\ud574\uc11c offset \uac12\uc744 \uad6c\ud574\uc11c x, y \uac12\uc5d0 \uac01\uac01 \ub354\ud558\ub294 \ud615\ud0dc\ub85c \uc911\uc559 \uc815\ub82c\uc744 \uc218\ud589\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","BufferedImage\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c (0, 0) \uae30\uc900\uc73c\ub85c \uc544\ub798\ub85c \ub0b4\ub824\uac08\uc218\ub85d y \uac12\uc774 \ucee4\uc9c0\uace0, \uc624\ub978\ucabd\uc73c\ub85c \uac08 \uc218\ub85d x \uac12\uc774 \ucee4\uc9c4\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./800.png",src:t(77421).Z+"",width:"968",height:"978"})}),"\n",(0,i.jsx)(n.p,{children:"\ub530\ub77c\uc11c \ucd5c\uc885\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c \uac12\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud588\ub2e4."}),"\n",(0,i.jsxs)(n.p,{children:["x \uac12 \u2192 \uacc4\uc0b0\ud55c offset \uadf8\ub300\ub85c \ub354\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","y \uac12 \u2192 imageSize(800)\uc5d0\uc11c y + offset \uac12\uc744 \ube80\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"routeimagedrawer\uc2e4\uc81c-\uc774\ubbf8\uc9c0\uc5d0-\uacbd\ub85c\ub97c-\uadf8\ub824\uc8fc\ub294-\ud074\ub798\uc2a4",children:"RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)"}),"\n",(0,i.jsxs)(n.p,{children:["BufferedImage, Graphics2D\ub97c \ud544\ub4dc\ub85c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uadf8\ub9bc\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \uc124\uc815\ud55c \uc0c1\uc218\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageDrawer.java"',children:"// RGB\uc5d0 \uac01\uac01 8\ube44\ud2b8\uc529 \ud560\ub2f9\ud55c \uac12\uc744 24\ube44\ud2b8 \ud2b8\ub8e8\uceec\ub7ec\ub77c \ubd80\ub978\ub2e4.\n// \ud574\ub2f9 \uc124\uc815\uc740 24\ube44\ud2b8 + 8\ube44\ud2b8(alpha, \ud22c\uba85\ub3c4)\ub97c \ucd94\uac00\ud55c 32\ube44\ud2b8 \uc774\ubbf8\uc9c0 \ud0c0\uc785\uc774\ub2e4.\n// \uc774\ub97c RGBA\ub77c\uace0 \ubd80\ub978\ub2e4.\nprivate static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;\n// \ubc30\uacbd \ud22c\uba85\uc0c9\nprivate static final Color TRANSPARENT = new Color(0, 0, 0, 0);\n// \uacbd\ub85c\ub97c \uc704\ud55c STROKE\nprivate static final int LINE_STROKE_WIDTH = 7;\nprivate static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\n// \uc704\uce58 \uc810\uc744 \uc704\ud55c STROKE\nprivate static final int POINT_STROKE_WIDTH = 20;\nprivate static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\n// \uc548\ud2f0\uc568\ub9ac\uc5b4\uc2f1 \ub4f1 \ud654\uc9c8 \uac1c\uc120\uc744 \uc704\ud55c \uc124\uc815\nprivate static final Map renderingHints = Map.of(\n RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,\n RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,\n RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC\n);\n"})}),"\n",(0,i.jsx)(n.p,{children:"RouteImageDrawer \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \uc138 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"drawLine: \uc120\uc744 \uadf8\ub9b0\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"drawPoint: \uc810\uc744 \ucc0d\ub294\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"dispose: \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"dispose\uc758 \uacbd\uc6b0 \ub0b4\ubd80\uc5d0\uc11c \uc0dd\uc131\ub41c graphics2D\uc5d0 \ub300\ud55c \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud558\ub294 \uba54\uc11c\ub4dc\uc778 graphics2D.dispose\ub97c \ud638\ucd9c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h2,{id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131-flow",children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow"}),"\n",(0,i.jsx)(n.h3,{id:"1-\uc774\ubbf8\uc9c0-\uc0dd\uc131-\uc900\ube44",children:"1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\n"}),"\n",(0,i.jsx)(n.h3,{id:"2-\uc120-\uadf8\ub9ac\uae30-\uc694\uccad",children:"2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.h3,{id:"3-\uc704\uce58-\uc810-\uadf8\ub9ac\uae30-\uc694\uccad",children:"3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\n\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.h3,{id:"4-\uc5c5\ub85c\ub4dc-\uc694\uccad",children:"4. \uc5c5\ub85c\ub4dc \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \tRouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\n \tRouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n \tRouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658"}),"\n",(0,i.jsx)(n.h3,{id:"\uc804\uccb4-flow",children:"\uc804\uccb4 Flow"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\n\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\n RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\n RouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n RouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n\t"})]})}function u(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var i=t(67294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),d=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=d(t),g=r,h=m["".concat(l,".").concat(g)]||m[g]||c[g]||o;return t?i.createElement(h,a(a({ref:n},u),{},{components:t})):i.createElement(h,a({ref:n},u))}));u.displayName="MDXCreateElement"},49812:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/600-50ee65176288cb73d2c777d255460f4f.png"},77421:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/800-88542ba3914ad40b45b999e95df96cdf.png"},59563:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/result-c2887223d62510a96c9c8f733bf5edf6.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3287],{67219:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>d});var i=t(85893),r=t(3905);const o={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",slug:"route-image-implementation",tags:["image","awt"]},a=void 0,s={permalink:"/route-image-implementation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",source:"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",description:"\uac1c\uc694",date:"2023-08-02T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 2\uc77c",tags:[{label:"image",permalink:"/tags/image"},{label:"awt",permalink:"/tags/awt"}],readingTime:11.665,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",slug:"route-image-implementation",tags:["image","awt"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",permalink:"/route-image-python"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",permalink:"/route-image-async-with-event"}},l={authorsImageUrls:[]},d=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:2},{value:"\uad6c\ud604 \uacb0\uacfc",id:"\uad6c\ud604-\uacb0\uacfc",level:3},{value:"IMAGE_SIZE & ROUTE_SIZE",id:"image_size--route_size",level:3},{value:"\uc8fc\uc694 \ud074\ub798\uc2a4",id:"\uc8fc\uc694-\ud074\ub798\uc2a4",level:2},{value:"\uc694\uc57d",id:"\uc694\uc57d",level:3},{value:"\uc758\uc874\uad00\uacc4",id:"\uc758\uc874\uad00\uacc4",level:3},{value:"Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)",id:"coordinates\uc704\ub3c4-\uacbd\ub3c4\uc758-\uc77c\uae09-\uceec\ub809\uc158",level:3},{value:"Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)",id:"positions\uc2e4\uc81c-\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc5d0-\uc0ac\uc6a9\ud560-\uc704\uce58",level:3},{value:"RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)",id:"routeimagedrawer\uc2e4\uc81c-\uc774\ubbf8\uc9c0\uc5d0-\uacbd\ub85c\ub97c-\uadf8\ub824\uc8fc\ub294-\ud074\ub798\uc2a4",level:3},{value:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow",id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131-flow",level:2},{value:"1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44",id:"1-\uc774\ubbf8\uc9c0-\uc0dd\uc131-\uc900\ube44",level:3},{value:"2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad",id:"2-\uc120-\uadf8\ub9ac\uae30-\uc694\uccad",level:3},{value:"3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad",id:"3-\uc704\uce58-\uc810-\uadf8\ub9ac\uae30-\uc694\uccad",level:3},{value:"4. \uc5c5\ub85c\ub4dc \uc694\uccad",id:"4-\uc5c5\ub85c\ub4dc-\uc694\uccad",level:3},{value:"\uc804\uccb4 Flow",id:"\uc804\uccb4-flow",level:3}];function c(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,i.jsxs)(n.p,{children:["\uc5ec\ud589\uc5d0 \ub300\ud55c \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\uae30 \uc704\ud574 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d \ubc0f \uae30\uc220 \uc120\ud0dd\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 ",(0,i.jsx)(n.a,{href:"./route-image-intro",children:"\ub9c1\ud06c"}),"\uc5d0 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\uad6c\ud604-\uacb0\uacfc",children:"\uad6c\ud604 \uacb0\uacfc"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./result.png",src:t(59563).Z+"",width:"1840",height:"714"})}),"\n",(0,i.jsxs)(n.p,{children:["\uc608\uc2dc \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.strong,{children:"\uc11c\uc6b8\uc5ed(\uc810)"})," \u2192 \uc2e0\uc0ac\uc5ed \u2192 \ub178\ub7c9\uc9c4\uc5ed \u2192 \ud64d\ub300\uc785\uad6c\uc5ed \u2192 \uc885\ub85c3\uac00\uc5ed \u2192 \uc625\uc218\uc5ed \u2192 ",(0,i.jsx)(n.strong,{children:"\uad6c\ub85c\uc5ed(\uc810)"})," \u2192 \uc2e0\ub9bc\uc5ed \u2192 \ubc1c\uc0b0\uc5ed"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="\uc608\uc2dc \ub370\uc774\ud130"',children:"List x = List.of(\n 126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,\n 126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639\n);\nList y = List.of(\n 37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,\n 37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184\n);\nList xPoints = List.of(126.97094933811682, 126.88474839801178);\nList yPoints = List.of(37.55302829553499, 37.50129417536773);\n"})}),"\n",(0,i.jsx)(n.h3,{id:"image_size--route_size",children:"IMAGE_SIZE & ROUTE_SIZE"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageGenerator.java"',children:"private static final int IMAGE_SIZE = 800;\nprivate static final int ROUTE_SIZE = 600;\n"})}),"\n",(0,i.jsxs)(n.p,{children:["\ucf54\ub4dc\ub97c \ubcf4\uba74 IMAGE_SIZE\uc640 ROUTE_SIZE\uac00 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","IMAGE_SIZE\ub294 \ub9d0 \uadf8\ub300\ub85c \uc774\ubbf8\uc9c0\uc758 width\uc640 height\ub97c \uc758\ubbf8\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","ROUTE_SIZE\uc758 \uacbd\uc6b0 \uc0c1\ud558\uc88c\uc6b0 100px \ub9cc\ud07c\uc758 \uac04\uaca9\uc744 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc2e4\uc81c \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub294 600 * 600 \uc0ac\uc774\uc988\ub85c \uc0dd\uc131\ub41c\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./600.png",src:t(49812).Z+"",width:"976",height:"970"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"\uc0ac\uc774\uc988 \ubcc0\uacbd\uc758 \uc774\uc720"})}),"\n",(0,i.jsx)(n.p,{children:"255 * 255 \uc815\ub3c4\uc758 \uc791\uc740 \uc0ac\uc774\uc988\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud574\ubcf4\ub824\uace0 \ud588\ub294\ub370, \uc774\ubbf8\uc9c0\uc758 \uc120\uba85\ub3c4\uac00 \uc88b\uc9c0 \uc54a\uc544 800 * 800 \uc0ac\uc774\uc988\ub85c \ubcc0\uacbd\ud588\ub2e4."}),"\n",(0,i.jsx)(n.h2,{id:"\uc8fc\uc694-\ud074\ub798\uc2a4",children:"\uc8fc\uc694 \ud074\ub798\uc2a4"}),"\n",(0,i.jsx)(n.h3,{id:"\uc694\uc57d",children:"\uc694\uc57d"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"\ud074\ub798\uc2a4\uba85"}),(0,i.jsx)(n.th,{children:"\uc124\uba85"}),(0,i.jsx)(n.th,{children:"\ud2b9\uc774\uc0ac\ud56d"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Coordinate"}),(0,i.jsx)(n.td,{children:"\uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \uc704\uce58 \uac12"}),(0,i.jsx)(n.td,{children:"\uc88c\ud45c\ub97c \ub73b\ud558\uc9c0\ub9cc \uc5ec\ud589 \ub3c4\uba54\uc778\uc5d0 \ud3ec\ud568\ub41c Point \ud074\ub798\uc2a4\uc640 \uad6c\ubd84\ud558\uae30 \uc704\ud574 longitude, latitude\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 x, y \uc0ac\uc6a9"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Coordinates"}),(0,i.jsx)(n.td,{children:"Coordinate\uc758 \uc77c\uae09 \uceec\ub809\uc158"}),(0,i.jsx)(n.td,{children:"-"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Position"}),(0,i.jsx)(n.td,{children:"\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58 \uac12"}),(0,i.jsx)(n.td,{children:"Integer \ud0c0\uc785\uc758 x, y \uc0ac\uc6a9"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Positions"}),(0,i.jsx)(n.td,{children:"Positions\uc758 \uc77c\uae09 \uceec\ub809\uc158"}),(0,i.jsx)(n.td,{children:"-"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageDrawer"}),(0,i.jsx)(n.td,{children:"\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4 BufferedImage, Graphics2D\ub97c \uac00\uc9c0\uace0 \uc788\uc74c"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc0c1\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc74c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageUploader"}),(0,i.jsx)(n.td,{children:"BufferedImage\ub97c \ubc1b\uc544 \uc11c\ubc84\uc5d0 \uc5c5\ub85c\ub4dc \ud558\ub294 \ud074\ub798\uc2a4"}),(0,i.jsx)(n.td,{children:"\ud604\uc7ac \uc5c5\ub85c\ub4dc \uc704\uce58\uac00 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc544 \uc77c\ub2e8 \uae30\ubcf8(\ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8) \uc704\uce58\uc5d0 \uc0dd\uc131"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageGenerator"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uace0 \uc5c5\ub85c\ub4dc\ud558\ub294 \uc11c\ube44\uc2a4"}),(0,i.jsx)(n.td,{children:"\uc5ec\ud589 \uc885\ub8cc, \uac10\uc0c1 \uc800\uc7a5\uc2dc \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"BufferedImage(AWT)"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0 \ub370\uc774\ud130\ub97c \ucc98\ub9ac\ud558\uace0 \uc870\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9"}),(0,i.jsx)(n.td,{children:"\uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c\uac00 (0, 0)"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Graphics2D(AWT)"}),(0,i.jsx)(n.td,{children:"\uc120 \uadf8\ub9ac\uae30, \uc0c9\uc0c1 \uad00\ub9ac \ub4f1\uc744 \uc9c0\uc6d0\ud558\ub294 \ud074\ub798\uc2a4 \uc2e4\uc81c \ud574\ub2f9 \ud074\ub798\uc2a4\uc758 draw \uba54\uc11c\ub4dc\ub97c \uacbd\ub85c\ub97c \uadf8\ub9bc"}),(0,i.jsx)(n.td,{children:"JDK 1.2 \uc774\ud6c4\uc5d0 \ucd94\uac00\ub428, 2D(\ud3c9\uba74) \uadf8\ub798\ud53d \ud658\uacbd\uc744 \uc9c0\uc6d0, bufferedImage.createGraphics \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \uc0dd\uc131"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"\uc758\uc874\uad00\uacc4",children:"\uc758\uc874\uad00\uacc4"}),"\n",(0,i.jsx)(n.mermaid,{value:'graph TD\n C1[Coordinates] --\x3e C[Coordinate]\n P1[Positions] --\x3e P[Position]\n\n\tRID[RouteImageDrawer] -- "\uc911\uc559 \uc815\ub82c\ub41c Positions\ub97c \ubc1b\uc544 \uc774\ubbf8\uc9c0 \uc0dd\uc131" --\x3e P1\n\tRID --\x3e B[BufferedImage]\n\tRID --\x3e G[Graphics2D]\n\n\tC1 -- "calculatePositions \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc704\uce58 \uacc4\uc0b0" --\x3e P1\n\n\tRIU[RouteImageUploader] --\x3e B\n\tRIG[RouteImageGenerator] --\x3e RID\n\tRIG --\x3e RIU\n\tRIG --\x3e C1\n\tRIG --\x3e P1'}),"\n",(0,i.jsx)(n.h3,{id:"coordinates\uc704\ub3c4-\uacbd\ub3c4\uc758-\uc77c\uae09-\uceec\ub809\uc158",children:"Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"List"})," 2\uac1c(\uc704\ub3c4, \uacbd\ub3c4)\uc778 \ud615\ud0dc\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uc5c8\uc9c0\ub9cc, \uc704\uce58 \uc810\uc744 \uc5ec\ub7ec\uac1c \ucc0d\ub294 \ubd80\ubd84\uc5d0\uc11c \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud574 \uc9c8 \uac83 \uac19\uc544\uc11c Coordinate(x, y)\uc640 \uc77c\uae09 \uceec\ub809\uc158\uc778 Coordinates\ub85c \uad00\ub9ac\ud558\uae30\ub85c \ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Coordinates \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub450 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"calculatePositions: \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub97c \ubc1b\uc544 \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \uc0ac\uc6a9\ub420 Positions\ub97c \ubc18\ud658"}),"\n",(0,i.jsx)(n.li,{children:"indexOf: \ub2e4\ub978 Coordinates\ub97c \ubc1b\uc544 \ub3d9\uc77c\ud55c \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4\ub97c \ubc18\ud658\ud558\ub294"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Positions \uacc4\uc0b0 \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc704\ub3c4, \uacbd\ub3c4 \uac01\uac01\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \ud544\uc694\ud55c \uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="Coordinates.java"',children:"// \ud638\ucd9c\n// List xPositions = toPositions(xValues, maxDifference, routeImageSize);\n// List yPositions = toPositions(yValues, maxDifference, routeImageSize);\n\nprivate List toPositions(List values, Double maxDifference, Integer routeImageSize) {\n Double minValue = Collections.min(values);\n return values.stream()\n .map(value -> normalizeCoordinate(value, maxDifference, minValue))\n .map(value -> mapToPosition(value, routeImageSize))\n .toList();\n}\n\nprivate double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {\n return (coordinate - minValue) / maxDifference;\n}\n\nprivate int mapToPosition(Double coordinate, Integer routeImageSize) {\n return (int) (coordinate * routeImageSize);\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\uc704\ub3c4\ub85c \uc608\uc2dc\ub4e0 \ub0b4\uc6a9\uc774\ub2e4."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Collections.min(values) \u2192 \uc704\ub3c4 \ub9ac\uc2a4\ud2b8\uc758 \ucd5c\uc18c\uac12\uc744 \uad6c\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.li,{children:["normalizeCoordinate \u2192 \uac01\uac01\uc758 \uc704\ub3c4 \uac12\uc5d0\uc11c \ucd5c\uc18c\uac12\uc744 \ube7c\uace0 0 ~ 1 \uc0ac\uc774 \uac12\uc73c\ub85c \ubcc0\ud658 \ud6c4 ",(0,i.jsx)(n.strong,{children:"\uc704\uacbd\ub3c4\uc758 \ucd5c\ub300 \ucc28\uc774"}),"\ub85c \ub098\ub208\ub2e4."]}),"\n",(0,i.jsx)(n.li,{children:"mapToPosition \u2192 \uadf8\ub798\ud504 \ud06c\uae30\ub97c \ubc1b\uc544 0 ~ 1 \uc0ac\uc774 \uac12\uc744 \uc2e4\uc81c \uc774\ubbf8\uc9c0\ub97c \uc704\ud55c \uc704\uce58\uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"positions\uc2e4\uc81c-\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc5d0-\uc0ac\uc6a9\ud560-\uc704\uce58",children:"Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)"}),"\n",(0,i.jsx)(n.p,{children:"Positions \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub2e4\uc12f \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"align: \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\uc640 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\ub97c \ubc1b\uc544 Position \uac12\ub4e4\uc744 \uc911\uc559 \uc815\ub82c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"getPositionsByIndexes: \uc778\ub371\uc2a4 \ub9ac\uc2a4\ud2b8\ub97c \ubc1b\uc544 \uc785\ub825\ubc1b\uc740 \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"size: \ud06c\uae30\ub97c \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"xPositions: x \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"yPositions: y \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uc559 \uc815\ub82c \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="Positions.java"',children:"public Positions align(int imageSize, int routeSize) {\n int xOffset = calculateOffset(Position::x, imageSize);\n int yOffset = calculateOffset(Position::y, imageSize);\n\n return items.stream()\n .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))\n .collect(collectingAndThen(toList(), Positions::new));\n}\n\nprivate int calculateOffset(ToIntFunction positionToInteger, int imageSize) {\n List positions = items.stream()\n .mapToInt(positionToInteger)\n .boxed()\n .toList();\n\n int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;\n return imageSize / 2 - midValue;\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["\uc0c1\ud558\uc88c\uc6b0 \uc5ec\ubc31\uc744 \ub3d9\uc77c\ud558\uac8c \uc8fc\uae30 \uc704\ud574\uc11c offset \uac12\uc744 \uad6c\ud574\uc11c x, y \uac12\uc5d0 \uac01\uac01 \ub354\ud558\ub294 \ud615\ud0dc\ub85c \uc911\uc559 \uc815\ub82c\uc744 \uc218\ud589\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","BufferedImage\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c (0, 0) \uae30\uc900\uc73c\ub85c \uc544\ub798\ub85c \ub0b4\ub824\uac08\uc218\ub85d y \uac12\uc774 \ucee4\uc9c0\uace0, \uc624\ub978\ucabd\uc73c\ub85c \uac08 \uc218\ub85d x \uac12\uc774 \ucee4\uc9c4\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./800.png",src:t(77421).Z+"",width:"968",height:"978"})}),"\n",(0,i.jsx)(n.p,{children:"\ub530\ub77c\uc11c \ucd5c\uc885\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c \uac12\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud588\ub2e4."}),"\n",(0,i.jsxs)(n.p,{children:["x \uac12 \u2192 \uacc4\uc0b0\ud55c offset \uadf8\ub300\ub85c \ub354\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","y \uac12 \u2192 imageSize(800)\uc5d0\uc11c y + offset \uac12\uc744 \ube80\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"routeimagedrawer\uc2e4\uc81c-\uc774\ubbf8\uc9c0\uc5d0-\uacbd\ub85c\ub97c-\uadf8\ub824\uc8fc\ub294-\ud074\ub798\uc2a4",children:"RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)"}),"\n",(0,i.jsxs)(n.p,{children:["BufferedImage, Graphics2D\ub97c \ud544\ub4dc\ub85c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uadf8\ub9bc\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \uc124\uc815\ud55c \uc0c1\uc218\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageDrawer.java"',children:"// RGB\uc5d0 \uac01\uac01 8\ube44\ud2b8\uc529 \ud560\ub2f9\ud55c \uac12\uc744 24\ube44\ud2b8 \ud2b8\ub8e8\uceec\ub7ec\ub77c \ubd80\ub978\ub2e4.\n// \ud574\ub2f9 \uc124\uc815\uc740 24\ube44\ud2b8 + 8\ube44\ud2b8(alpha, \ud22c\uba85\ub3c4)\ub97c \ucd94\uac00\ud55c 32\ube44\ud2b8 \uc774\ubbf8\uc9c0 \ud0c0\uc785\uc774\ub2e4.\n// \uc774\ub97c RGBA\ub77c\uace0 \ubd80\ub978\ub2e4.\nprivate static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;\n// \ubc30\uacbd \ud22c\uba85\uc0c9\nprivate static final Color TRANSPARENT = new Color(0, 0, 0, 0);\n// \uacbd\ub85c\ub97c \uc704\ud55c STROKE\nprivate static final int LINE_STROKE_WIDTH = 7;\nprivate static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\n// \uc704\uce58 \uc810\uc744 \uc704\ud55c STROKE\nprivate static final int POINT_STROKE_WIDTH = 20;\nprivate static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\n// \uc548\ud2f0\uc568\ub9ac\uc5b4\uc2f1 \ub4f1 \ud654\uc9c8 \uac1c\uc120\uc744 \uc704\ud55c \uc124\uc815\nprivate static final Map renderingHints = Map.of(\n RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,\n RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,\n RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC\n);\n"})}),"\n",(0,i.jsx)(n.p,{children:"RouteImageDrawer \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \uc138 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"drawLine: \uc120\uc744 \uadf8\ub9b0\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"drawPoint: \uc810\uc744 \ucc0d\ub294\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"dispose: \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"dispose\uc758 \uacbd\uc6b0 \ub0b4\ubd80\uc5d0\uc11c \uc0dd\uc131\ub41c graphics2D\uc5d0 \ub300\ud55c \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud558\ub294 \uba54\uc11c\ub4dc\uc778 graphics2D.dispose\ub97c \ud638\ucd9c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h2,{id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131-flow",children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow"}),"\n",(0,i.jsx)(n.h3,{id:"1-\uc774\ubbf8\uc9c0-\uc0dd\uc131-\uc900\ube44",children:"1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\n"}),"\n",(0,i.jsx)(n.h3,{id:"2-\uc120-\uadf8\ub9ac\uae30-\uc694\uccad",children:"2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.h3,{id:"3-\uc704\uce58-\uc810-\uadf8\ub9ac\uae30-\uc694\uccad",children:"3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\n\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.h3,{id:"4-\uc5c5\ub85c\ub4dc-\uc694\uccad",children:"4. \uc5c5\ub85c\ub4dc \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \tRouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\n \tRouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n \tRouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658"}),"\n",(0,i.jsx)(n.h3,{id:"\uc804\uccb4-flow",children:"\uc804\uccb4 Flow"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\n\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\n RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\n RouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n RouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n\t"})]})}function u(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var i=t(67294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),d=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=d(t),g=r,h=m["".concat(l,".").concat(g)]||m[g]||c[g]||o;return t?i.createElement(h,a(a({ref:n},u),{},{components:t})):i.createElement(h,a({ref:n},u))}));u.displayName="MDXCreateElement"},49812:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/600-50ee65176288cb73d2c777d255460f4f.png"},77421:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/800-88542ba3914ad40b45b999e95df96cdf.png"},59563:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/result-c2887223d62510a96c9c8f733bf5edf6.png"}}]); \ No newline at end of file diff --git a/assets/js/72657f57.cd507c93.js b/assets/js/72657f57.6d0bc2e8.js similarity index 97% rename from assets/js/72657f57.cd507c93.js rename to assets/js/72657f57.6d0bc2e8.js index b27b43506..514a6ff33 100644 --- a/assets/js/72657f57.cd507c93.js +++ b/assets/js/72657f57.6d0bc2e8.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9581],{32262:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>o,default:()=>u,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var t=n(85893),s=n(3905);const c={title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",slug:"web-racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,a={permalink:"/web-racing-car-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-racingcar/pull/24",date:"2023-05-02T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 2\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.6,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",slug:"web-racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",permalink:"/shopping-cart-retrospective"},nextItem:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",permalink:"/tecochat-retrospective-2"}},i={authorsImageUrls:[]},l=[{value:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158",id:"\uc6f9-\uc790\ub3d9\ucc28-\ubbf8\uc158",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-racingcar/pull/24",children:"https://github.com/woowacourse/jwp-racingcar/pull/24"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-racingcar/pull/128",children:"https://github.com/woowacourse/jwp-racingcar/pull/128"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\uc6f9-\uc790\ub3d9\ucc28-\ubbf8\uc158",children:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158"}),"\n",(0,t.jsxs)(r.p,{children:["\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud55c\ub2e4\uace0 \uc2dc\uac04\uc774 \ub9ce\uc774 \uc5c6\uc5b4\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc84c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\uc5d0\uc11c\ub294 \ube44\ubc84\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub808\ubca8 2\uc5d0\uc11c \uc9c4\ud589\ud558\ub294 \uccab \ubbf8\uc158\uc774\ub77c \ub9ce\uc774 \uae34\uc7a5\ub418\uc5c8\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ube44\ubc84\ub791 \ucd08\ubc18\uc5d0 \ub9db\uc788\ub294 \uac83\ub3c4 \ub9ce\uc774 \uba39\uc73c\uba74\uc11c \ube68\ub9ac \uce5c\ud574\uc838\uc11c \uc7ac\ubc0c\uac8c \ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc2a4\ud504\ub9c1\uc744 \uc870\uae08 \uc0ac\uc6a9\ud560 \uc904 \uc54c\uc544\uc11c, \ube44\ubc84\ub791 \uac19\uc774 \ud559\uc2b5\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uccab \ubbf8\uc158\uc774\ub77c \uadf8\ub7f0\uc9c0 \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc740 \uc5c6\uc5c8\uace0, \ucd5c\ub300\ud55c \uae54\ub054\ud558\uac8c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub09c\uc774\ub3c4 \ub192\uc740 \ubbf8\uc158\uc774 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ub9ac\ubdf0\uc5b4\uc778 \ub77c\ube48\uc5d0\uac8c \uce6d\ucc2c\uc744 \ub9ce\uc774 \ubc1b\uc544\uc11c \uae30\ubd84\uc774 \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub77c\ube48 \uac10\uc0ac\ud569\ub2c8\ub2e4!"]}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\ucee8\ub514\uc158\ub3c4 \uc88b\uc9c0 \uc54a\uace0 \uc5f4\uc815\ub3c4 \uc2dd\uc740 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc774 \ub2e4\uc18c \uc5ec\uc720\ub86d\ub2e4\uace0 \ub290\uaef4\uc838\uc11c, \uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ubd84\ub3c4 \uc798 \uad00\ub9ac\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud574\uc11c \ud398\uc5b4\uc5d0\uac8c \ub9ce\uc774 \ubbf8\uc548\ud588\uace0, \ub098 \uc790\uc2e0\uc5d0\uac8c \uc544\uc26c\uc6e0\ub358 \ubd80\ubd84\uc774 \ub9ce\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc9c0\ub09c\ubc88 \ud68c\uace0\ub97c \ub2e4\uc2dc \ubcf4\ub294\ub370 \uc9d1\uc911\uc744 \uc798 \ubabb\ud55c \uacbd\uc6b0\uac00 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub3c4\uc804\uc801\uc774\uc9c0 \uc54a\uac70\ub098 \uc2dc\uac04\uc774 \ubd80\uc871\ud558\uc9c0 \uc54a\uc73c\uba74 \uc9d1\uc911\uc744 \uc798 \ubabb\ud558\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uba38\ub9bf\uc18d\uc5d0\uc11c \uc2dc\uac04\uc801 \uc5ec\uc720\uac00 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \ub54c\uac00 \uac00\uc7a5 \uc704\ud5d8\ud55c \uc21c\uac04\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ud568\uaed8 \uc790\ub77c\uae30\uc5d0\uc11c \ub098\uc628 ",(0,t.jsx)(r.code,{children:"\ub09c\uc774\ub3c4 \ub192\uc774\uae30"}),"\uac00 \ud544\uc694\ud574\uc9c0\ub294 \uc21c\uac04\uc774\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc911\uc694\ub3c4\uac00 \uc788\ub294 \uc5b4\ub178\ud14c\uc774\uc158\ubd80\ud130 \ud074\ub798\uc2a4 \uc774\ub984\uc5d0 \uac00\uae5d\uac8c \uba85\uc2dc\ud558\uae30"})}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'@SuppressWarnings("NonAsciiCharacters")\n@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)\n@Transactional\n@AutoConfigureMockMvc\n@SpringBootTest\npublic class RacingGameIntegrationTest {\n'})}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ube44\ubc84\uc758 \uc131\uaca9"}),(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uac00 \uc131\uaca9\uc774 \uc88b\uc544\uc11c \ud3b8\ud558\uac8c \ud398\uc5b4\ub97c \ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc131\uae09\ud558\uc9c0 \uc54a\uace0 \uc5ec\uc720\ub85c\uc6cc\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ubbf8\uc158\uc5d0 \uc9d1\uc911\ud558\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud588\ub294\ub370\ub3c4 \uac19\uc774 \ud398\uc5b4\ub97c \uc798 \uc9c4\ud589\ud55c \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud574\uc11c \uadf8\ub807\uc9c0 \uc54a\uc558\ub098 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadfc\uc721\ub9e8 \ube44\ubc84\ub77c \uadf8\ub7f0\uc9c0 \uccb4\ub825\uc774 \uc88b\uc544\uc11c \uadf8\ub7f0\uac00?",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04\uc5d0 \uc798 \uc548 \uc26c\uace0\ub3c4 \uc9d1\uc911\ud574\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac78 \ubcf4\uace0 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ud559\uc2b5\uc5d0 \ub300\ud55c \uc5f4\uc815"}),(0,t.jsx)(r.br,{}),"\n","\ucd94\uac00\uc801\uc73c\ub85c \uc54c\uace0 \uc2f6\uc740 \ubd80\ubd84\uc744 \ub530\ub85c \ud559\uc2b5\ud558\ub294 \uc5f4\uc815\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uc640 \uc2a4\ud504\ub9c1\uc5d0 \ub300\ud574 \uc54c\uc544\uac00\ub294 \uc2dc\uac04\uc744 \ub9ce\uc774 \uac00\uc9c4 \ubd80\ubd84\uc774 \ub9e4\uc6b0 \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 5\uc6d4\ubd80\ud130 \uc870\uae08 \ub354 \ud654\uc774\ud305 \ud574\uc57c\uaca0\ub2e4."]})]})}function u(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function c(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),l=function(e){var r=t.useContext(i),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},u=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,c=e.originalType,i=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),h=l(n),j=s,d=h["".concat(i,".").concat(j)]||h[j]||p[j]||c;return n?t.createElement(d,o(o({ref:r},u),{},{components:n})):t.createElement(d,o({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9581],{32262:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>o,default:()=>u,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var t=n(85893),s=n(3905);const c={title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",slug:"web-racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},o=void 0,a={permalink:"/web-racing-car-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-racingcar/pull/24",date:"2023-05-02T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 2\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.6,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",slug:"web-racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",permalink:"/tecochat-retrospective-2"},nextItem:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",permalink:"/shopping-cart-retrospective"}},i={authorsImageUrls:[]},l=[{value:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158",id:"\uc6f9-\uc790\ub3d9\ucc28-\ubbf8\uc158",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",strong:"strong",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-racingcar/pull/24",children:"https://github.com/woowacourse/jwp-racingcar/pull/24"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-racingcar/pull/128",children:"https://github.com/woowacourse/jwp-racingcar/pull/128"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\uc6f9-\uc790\ub3d9\ucc28-\ubbf8\uc158",children:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158"}),"\n",(0,t.jsxs)(r.p,{children:["\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud55c\ub2e4\uace0 \uc2dc\uac04\uc774 \ub9ce\uc774 \uc5c6\uc5b4\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc84c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\uc5d0\uc11c\ub294 \ube44\ubc84\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub808\ubca8 2\uc5d0\uc11c \uc9c4\ud589\ud558\ub294 \uccab \ubbf8\uc158\uc774\ub77c \ub9ce\uc774 \uae34\uc7a5\ub418\uc5c8\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ube44\ubc84\ub791 \ucd08\ubc18\uc5d0 \ub9db\uc788\ub294 \uac83\ub3c4 \ub9ce\uc774 \uba39\uc73c\uba74\uc11c \ube68\ub9ac \uce5c\ud574\uc838\uc11c \uc7ac\ubc0c\uac8c \ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc2a4\ud504\ub9c1\uc744 \uc870\uae08 \uc0ac\uc6a9\ud560 \uc904 \uc54c\uc544\uc11c, \ube44\ubc84\ub791 \uac19\uc774 \ud559\uc2b5\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uccab \ubbf8\uc158\uc774\ub77c \uadf8\ub7f0\uc9c0 \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc740 \uc5c6\uc5c8\uace0, \ucd5c\ub300\ud55c \uae54\ub054\ud558\uac8c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub09c\uc774\ub3c4 \ub192\uc740 \ubbf8\uc158\uc774 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ub9ac\ubdf0\uc5b4\uc778 \ub77c\ube48\uc5d0\uac8c \uce6d\ucc2c\uc744 \ub9ce\uc774 \ubc1b\uc544\uc11c \uae30\ubd84\uc774 \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub77c\ube48 \uac10\uc0ac\ud569\ub2c8\ub2e4!"]}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\ucee8\ub514\uc158\ub3c4 \uc88b\uc9c0 \uc54a\uace0 \uc5f4\uc815\ub3c4 \uc2dd\uc740 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc774 \ub2e4\uc18c \uc5ec\uc720\ub86d\ub2e4\uace0 \ub290\uaef4\uc838\uc11c, \uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ubd84\ub3c4 \uc798 \uad00\ub9ac\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud574\uc11c \ud398\uc5b4\uc5d0\uac8c \ub9ce\uc774 \ubbf8\uc548\ud588\uace0, \ub098 \uc790\uc2e0\uc5d0\uac8c \uc544\uc26c\uc6e0\ub358 \ubd80\ubd84\uc774 \ub9ce\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc9c0\ub09c\ubc88 \ud68c\uace0\ub97c \ub2e4\uc2dc \ubcf4\ub294\ub370 \uc9d1\uc911\uc744 \uc798 \ubabb\ud55c \uacbd\uc6b0\uac00 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub3c4\uc804\uc801\uc774\uc9c0 \uc54a\uac70\ub098 \uc2dc\uac04\uc774 \ubd80\uc871\ud558\uc9c0 \uc54a\uc73c\uba74 \uc9d1\uc911\uc744 \uc798 \ubabb\ud558\ub294 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uba38\ub9bf\uc18d\uc5d0\uc11c \uc2dc\uac04\uc801 \uc5ec\uc720\uac00 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \ub54c\uac00 \uac00\uc7a5 \uc704\ud5d8\ud55c \uc21c\uac04\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ud568\uaed8 \uc790\ub77c\uae30\uc5d0\uc11c \ub098\uc628 ",(0,t.jsx)(r.code,{children:"\ub09c\uc774\ub3c4 \ub192\uc774\uae30"}),"\uac00 \ud544\uc694\ud574\uc9c0\ub294 \uc21c\uac04\uc774\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc911\uc694\ub3c4\uac00 \uc788\ub294 \uc5b4\ub178\ud14c\uc774\uc158\ubd80\ud130 \ud074\ub798\uc2a4 \uc774\ub984\uc5d0 \uac00\uae5d\uac8c \uba85\uc2dc\ud558\uae30"})}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'@SuppressWarnings("NonAsciiCharacters")\n@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)\n@Transactional\n@AutoConfigureMockMvc\n@SpringBootTest\npublic class RacingGameIntegrationTest {\n'})}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ube44\ubc84\uc758 \uc131\uaca9"}),(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uac00 \uc131\uaca9\uc774 \uc88b\uc544\uc11c \ud3b8\ud558\uac8c \ud398\uc5b4\ub97c \ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc131\uae09\ud558\uc9c0 \uc54a\uace0 \uc5ec\uc720\ub85c\uc6cc\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ubbf8\uc158\uc5d0 \uc9d1\uc911\ud558\ub294 \ubd80\ubd84"}),(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud588\ub294\ub370\ub3c4 \uac19\uc774 \ud398\uc5b4\ub97c \uc798 \uc9c4\ud589\ud55c \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud574\uc11c \uadf8\ub807\uc9c0 \uc54a\uc558\ub098 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadfc\uc721\ub9e8 \ube44\ubc84\ub77c \uadf8\ub7f0\uc9c0 \uccb4\ub825\uc774 \uc88b\uc544\uc11c \uadf8\ub7f0\uac00?",(0,t.jsx)(r.br,{}),"\n","\uc911\uac04\uc5d0 \uc798 \uc548 \uc26c\uace0\ub3c4 \uc9d1\uc911\ud574\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac78 \ubcf4\uace0 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.strong,{children:"\ud559\uc2b5\uc5d0 \ub300\ud55c \uc5f4\uc815"}),(0,t.jsx)(r.br,{}),"\n","\ucd94\uac00\uc801\uc73c\ub85c \uc54c\uace0 \uc2f6\uc740 \ubd80\ubd84\uc744 \ub530\ub85c \ud559\uc2b5\ud558\ub294 \uc5f4\uc815\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube44\ubc84\uc640 \uc2a4\ud504\ub9c1\uc5d0 \ub300\ud574 \uc54c\uc544\uac00\ub294 \uc2dc\uac04\uc744 \ub9ce\uc774 \uac00\uc9c4 \ubd80\ubd84\uc774 \ub9e4\uc6b0 \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 5\uc6d4\ubd80\ud130 \uc870\uae08 \ub354 \ud654\uc774\ud305 \ud574\uc57c\uaca0\ub2e4."]})]})}function u(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function c(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),l=function(e){var r=t.useContext(i),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},u=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,c=e.originalType,i=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),h=l(n),j=s,d=h["".concat(i,".").concat(j)]||h[j]||p[j]||c;return n?t.createElement(d,o(o({ref:r},u),{},{components:n})):t.createElement(d,o({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/73688d5c.50416e9c.js b/assets/js/73688d5c.124e0ac3.js similarity index 99% rename from assets/js/73688d5c.50416e9c.js rename to assets/js/73688d5c.124e0ac3.js index 772c500c6..1ecde4053 100644 --- a/assets/js/73688d5c.50416e9c.js +++ b/assets/js/73688d5c.124e0ac3.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6908],{90465:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>b,frontMatter:()=>i,metadata:()=>s,toc:()=>o});var t=a(85893),r=a(3905);const i={title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",slug:"transaction-and-isolation",tags:["DataBase","Transaction","Isolation"]},l=void 0,s={permalink:"/transaction-and-isolation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",source:"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",description:"\ud2b8\ub79c\uc7ad\uc158(Transaction)",date:"2023-04-05T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 5\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Transaction",permalink:"/tags/transaction"},{label:"Isolation",permalink:"/tags/isolation"}],readingTime:9.57,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",slug:"transaction-and-isolation",tags:["DataBase","Transaction","Isolation"]},unlisted:!1,prevItem:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/mysql-lock"},nextItem:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",permalink:"/test-double"}},c={authorsImageUrls:[]},o=[{value:"\ud2b8\ub79c\uc7ad\uc158(Transaction)",id:"\ud2b8\ub79c\uc7ad\uc158transaction",level:2},{value:"\ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)",id:"\ud2b8\ub79c\uc7ad\uc158\uc758-\uc18d\uc131acid",level:3},{value:"\ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d",id:"\ud2b8\ub79c\uc7ad\uc158-\uc8fc\uc758\uc0ac\ud56d",level:3},{value:"\uaca9\ub9ac \uc218\uc900(Isolation level)",id:"\uaca9\ub9ac-\uc218\uc900isolation-level",level:2},{value:"READ UNCOMMITTED",id:"read-uncommitted",level:3},{value:"READ COMMITTED",id:"read-committed",level:3},{value:"REPEATABLE READ",id:"repeatable-read",level:3},{value:"SERIALIZABLE",id:"serializable",level:3},{value:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c",id:"\uaca9\ub9ac-\uc218\uc900\uc5d0-\ub530\ub978-\ubd80\uc815\ud569-\ubb38\uc81c",level:2},{value:"\ub354\ud2f0 \ub9ac\ub4dc(Dirty read)",id:"\ub354\ud2f0-\ub9ac\ub4dcdirty-read",level:3},{value:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)",id:"\ubc18\ubcf5-\uac00\ub2a5\ud558\uc9c0-\uc54a\uc740-\uc870\ud68cnon-repeatable-read",level:3},{value:"\ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)",id:"\ud32c\ud140-\ub9ac\ub4dcphantom-read-phantom-row",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"\ud2b8\ub79c\uc7ad\uc158transaction",children:"\ud2b8\ub79c\uc7ad\uc158(Transaction)"}),"\n",(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub17c\ub9ac\uc801 \uae30\ub2a5\uc744 \uc218\ud589\ud558\uae30 \uc704\ud55c \uc791\uc5c5\uc758 \ub2e8\uc704\ub97c \ub9d0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc740 \uc791\uc5c5\uc758 \uc644\uc804\uc131\uacfc \ub370\uc774\ud130\uc758 \uc815\ud569\uc131\uc744 \ubcf4\uc7a5\ud574 \uc900\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub17c\ub9ac\uc801\uc778 \uc791\uc5c5 \uc14b\uc744 \uc644\ubcbd\ud558\uac8c \ucc98\ub9ac\ud558\uac70\ub098, \uc624\ub958 \uc2dc \uc791\uc5c5\uc758 \uc77c\ubd80\ub9cc \uc801\uc6a9\ub418\ub294 \ud604\uc0c1\uc744 \ub9c9\uc544\uc900\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud2b8\ub79c\uc7ad\uc158\uc758-\uc18d\uc131acid",children:"\ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc6d0\uc790\uc131(Atomicity): \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \uc2e4\ud589\ub41c \uc791\uc5c5\ub4e4\uc740 \ubaa8\ub450 \uc131\uacf5\ud558\uac70\ub098, \uc2e4\ud328\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc77c\uad00\uc131(Consistency): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc218\ud589\ub418\uae30 \uc804\uacfc \ud6c4\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc77c\uad00\ub41c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uaca9\ub9ac\uc131(Isolation): \uac01\uac01\uc758 \ud2b8\ub79c\uc7ad\uc158\uc740 \ub3c5\ub9bd\uc801\uc774\ub77c \uc11c\ub85c\uc5d0\uac8c \uc601\ud5a5\uc744 \uc8fc\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc9c0\uc18d\uc131(Durability): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c\ub2e4\uba74 \uc601\uad6c\uc801\uc73c\ub85c \uacb0\uacfc\uc5d0 \ubc18\uc601\ub418\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud2b8\ub79c\uc7ad\uc158-\uc8fc\uc758\uc0ac\ud56d",children:"\ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc740 \uaf2d \ud544\uc694\ud55c \ucd5c\uc18c\uc758 \ucf54\ub4dc\uc5d0\ub9cc \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.(\ud2b8\ub79c\uc7ad\uc158\uc758 \ubc94\uc704\ub97c \ucd5c\uc18c\ud654\ud558\ub77c)",(0,t.jsx)(n.br,{}),"\n","\uad6c\ud604\ud574\uc57c \ud558\ub294 \uc5c5\ubb34\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158\uc744 \ubb36\uac70\ub098 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\ub294 \uacbd\uc6b0 \ubc18\ub4dc\uc2dc \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsxs)(n.admonition,{title:"\uc65c \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\uc744 \ub54c \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud560\uae4c? \ud83e\udd14",type:"info",children:[(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\uc758 \uc77c\uad00\uc131\uacfc \uc548\uc804\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc744 \ud2b8\ub79c\uc7ad\uc158 \ub0b4\ubd80\uc5d0 \ud3ec\ud568\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4."]}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc911\uac04\uc5d0 \uc2e4\ud328\ud560 \uac00\ub2a5\uc131(\uc548\uc804\uc131 X)"}),"\n",(0,t.jsx)(n.li,{children:"\ud1b5\uc2e0\uc73c\ub85c \uc778\ud574 \ub370\uc774\ud130\uac00 \ubcc0\uacbd\ub420 \uc218 \uc788\ub294 \ubd80\ubd84(\uc77c\uad00\uc131 X)"}),"\n"]})]}),"\n",(0,t.jsx)(n.h2,{id:"\uaca9\ub9ac-\uc218\uc900isolation-level",children:"\uaca9\ub9ac \uc218\uc900(Isolation level)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc5ec\ub7ec \ud2b8\ub79c\uc7ad\uc158\uc774 \ub3d9\uc2dc\uc5d0 \ucc98\ub9ac\ub420 \ub54c \ud2b9\uc815 \ud2b8\ub79c\uc7ad\uc158\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\uc758 \uc870\ud68c \ubc0f \ubcc0\uacbd\uc744 \ud5c8\uc6a9\ud560\uc9c0 \uacb0\uc815\ud558\ub294 \uac83\uc744 \ub9d0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uaca9\ub9ac \uc218\uc900\uc774 \ub192\uc544\uc9c8 \uc218\ub85d \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\uc774 \ub5a8\uc5b4\uc9c0\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\uc9c0\ub9cc, ",(0,t.jsx)(n.code,{children:"SERIALIZABLE"}),"\uc774 \uc544\ub2c8\ub77c\uba74 \ud06c\uac8c \uc131\ub2a5\uc758 \uc800\ud558\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"read-uncommitted",children:"READ UNCOMMITTED"}),"\n",(0,t.jsxs)(n.p,{children:["\uac01 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\uc758 \ubcc0\uacbd \ub0b4\uc6a9\uc774 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774\ub098 ",(0,t.jsx)(n.code,{children:"ROLLBACK"})," \uc5ec\ubd80\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcf4\uc778\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub354\ud2f0 \ub9ac\ub4dc \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud558\uae30 \ub54c\ubb38\uc5d0 \uc815\ud569\uc131\uc758 \ubb38\uc81c\uac00 \ub9ce\uc740 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL \uc0ac\uc6a9\uc2dc \ucd5c\uc18c ",(0,t.jsx)(n.code,{children:"READ COMMITTED"})," \uc774\uc0c1\uc758 \uaca9\ub9ac \uc218\uc900 \uc0ac\uc6a9\uc744 \uad8c\uc7a5\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: READ UNCOMMITTED\n---\nsequenceDiagram\n Alice->>Database: BEGIN\n Alice->>Database: INSERT(Alice)\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: COMMIT(Alice)"}),"\n",(0,t.jsx)(n.h3,{id:"read-committed",children:"READ COMMITTED"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774 \uc644\ub8cc\ub41c \ub370\uc774\ud130\ub9cc \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc870\ud68c\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub77c\ud074 DBMS\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.code,{children:"REPEATABLE READ"}),"\uac00 \ubcf4\uc7a5\ub418\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 ",(0,t.jsx)(n.code,{children:"NON-REPEATABLE READ"})," \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: READ COMMITTED\n---\nsequenceDiagram\n Alice->>Database: BEGIN\n Alice->>Database: UPDATE(Alice to Bob)\n Bob->>Database: SELECT\n Database->>+Bob: Alice(Undo log)\n Alice->>Database: COMMIT"}),"\n",(0,t.jsx)(n.h3,{id:"repeatable-read",children:"REPEATABLE READ"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc774 \uc2dc\uc791\ub418\uae30 \uc804\uc5d0 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774 \uc644\ub8cc\ub41c \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub9cc \uc870\ud68c\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL\uc758 InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MVCC\ub97c \uc774\uc6a9\ud574 \uc5b8\ub450(Undo) \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \uc774\uc804 \ub370\uc774\ud130\ub97c \uc774\uc6a9\ud574 \ub3d9\uc77c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc5ec\uc904 \uc218 \uc788\uac8c \ubcf4\uc7a5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc7a5\ud558\ub294 \ubc29\ubc95\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ubaa8\ub4e0 InnoDB \ud2b8\ub79c\uc7ad\uc158\uc740 \uc21c\ucc28\uc801\uc73c\ub85c \uc99d\uac00\ud558\ub294 \uace0\uc720\ud55c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ub97c \uac00\uc9c4\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Undo \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \ub808\ucf54\ub4dc\uc5d0\ub294 \ubcc0\uacbd\uc744 \ubc1c\uc0dd\uc2dc\ud0a8 \ud2b8\ub79c\uc7ad\uc158\uc758 \ubc88\ud638\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Undo \uc601\uc5ed\uc758 \ubc31\uc5c5\ub41c \ub370\uc774\ud130\ub294 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774 \ubd88\ud544\uc694\ud558\ub2e4\uace0 \ud310\ub2e8\ud558\ub294 \uacbd\uc6b0 \uc0ad\uc81c\ub41c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c\ub294 MVCC\ub97c \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \uac00\uc7a5 \uc624\ub798\ub41c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ubcf4\ub2e4 \uc55e\uc120 Undo \uc601\uc5ed\uc758 \ub370\uc774\ud130\ub294 \uc0ad\uc81c\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"InnoDB\uc5d0\uc11c\ub294 \uac2d \ub77d\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc744 \uc774\uc6a9\ud558\uc5ec \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc744 \ubc29\uc9c0\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: REPEATABLE READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN(TRX-ID: 1)\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: BEGIN(TRX-ID: 2)\n Alice->>Database: UPDATE(Alice to Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT\n Database->>+Bob: Alice(Undo log)"}),"\n",(0,t.jsx)(n.admonition,{title:"\uac2d \ub78d(Gap lock)\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d(Next-key lock)",type:"note",children:(0,t.jsxs)(n.p,{children:["\uac2d \ub77d: \ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub125\uc2a4\ud2b8 \ud0a4 \ub77d: \ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4."]})}),"\n",(0,t.jsxs)(n.admonition,{title:"MVCC(Multi Version Concurrency Control)",type:"note",children:[(0,t.jsx)(n.p,{children:"\ub3d9\uc2dc\uc131\uc744 \uc81c\uc5b4\ud558\ub294 \ubc29\ubc95 \uc911 \ud558\ub098\ub85c \ud558\ub098\uc758 \ub808\ucf54\ub4dc\uc5d0 \ub300\ud574 \uc5ec\ub7ec \uac1c\uc758 \ubc84\uc804\uc774 \ub3d9\uc2dc\uc5d0 \uad00\ub9ac\ub418\ub294 \uac83\uc774\ub2e4."}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"PostgreSQL\uc740 \ub2e4\uc911 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uac83\uc73c\ub85c MVCC\ub97c \uad6c\ud604\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:["Oracle, InnoDB\ub294 ",(0,t.jsx)(n.code,{children:"Undo log"}),"\ub97c \uc774\uc6a9\ud574 \uc774 \uae30\ub2a5\uc744 \uad6c\ud604\ud55c\ub2e4.(\ucd5c\uc2e0 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub9cc DB\uc5d0 \uc800\uc7a5)"]}),"\n"]}),(0,t.jsx)(n.p,{children:"\uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc77d\uad00\ub41c \uc77d\uae30\ub97c \uc81c\uacf5\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4."})]}),"\n",(0,t.jsx)(n.h3,{id:"serializable",children:"SERIALIZABLE"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc9c4\ud589\uc2dc\ud0a4\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uace0 \ub530\ub77c\uc11c \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\ub3c4 \ub2e4\ub978 \uaca9\ub9ac \uc218\uc900\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c4\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uace0 \uc4f0\ub294 \ub808\ucf54\ub4dc\ub97c \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\ub294 \uc811\uadfc\ud560 \uc218 \uc5c6\uace0 \ub2e8\uc21c\ud55c \uc77d\uae30 \uc791\uc5c5\ub3c4 \uacf5\uc720 \uc7a0\uae08(\uc77d\uae30 \uc7a0\uae08)\uc744 \ud68d\ub4dd\ud574\uc57c\ub9cc \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB\uc5d0\uc11c\ub294 \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc774 ",(0,t.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uad73\uc774 \uc0ac\uc6a9\ud560 \ud544\uc694\ub294 \uc5c6\ub2e4."]}),"\n",(0,t.jsx)(n.h2,{id:"\uaca9\ub9ac-\uc218\uc900\uc5d0-\ub530\ub978-\ubd80\uc815\ud569-\ubb38\uc81c",children:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c"}),"\n",(0,t.jsx)(n.p,{children:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ub354\ud2f0 \ub9ac\ub4dc, \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c, \ud32c\ud140 \ub9ac\ub4dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"\uaca9\ub9ac \uc218\uc900 / \ubd80\uc815\ud569 \ubb38\uc81c"}),(0,t.jsx)(n.th,{children:"\ub354\ud2f0 \ub9ac\ub4dc"}),(0,t.jsx)(n.th,{children:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c"}),(0,t.jsx)(n.th,{children:"\ud32c\ud140 \ub9ac\ub4dc"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"READ UNCOMMITTED"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"READ COMMITTED"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"REPEATABLE READ"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"O(InnoDB\ub294 X)"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SERIALIZABLE"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"\ub354\ud2f0-\ub9ac\ub4dcdirty-read",children:"\ub354\ud2f0 \ub9ac\ub4dc(Dirty read)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc5b4\ub5a4 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c \uc791\uc5c5\uc774 \uc644\ub8cc\ub418\uc9c0 \uc54a\uc558\uc5b4\ub3c4 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcfc \uc218 \uc788\ub294 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \uc218\uc900\uc774 READ UNCOMMITTED\uc77c \ub54c \ubc1c\uc0dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc608) B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uace0 \ucee4\ubc0b\uc744 \ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, A\uac00 \ud574\ub2f9 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud560 \uc218 \uc788\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc18\ubcf5-\uac00\ub2a5\ud558\uc9c0-\uc54a\uc740-\uc870\ud68cnon-repeatable-read",children:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)"}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc758 \uac19\uc740 \ud589\uc5d0 \ub450 \ubc88 \uc774\uc0c1 \uc870\ud68c\uac00 \ubc1c\uc0dd\ud588\ub294\ub370, \uadf8 \uac12\uc774 \ub2e4\ub978 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc5ec\ub7ec \ubc88 \uc870\ud68c\ud558\ub358 \uc911 B\uac00 \ub808\ucf54\ub4dc\ub97c \ubcc0\uacbd\ud558\uc5ec A\uac00 \uc870\ud68c\ud55c \uac12\uc774 \ub2ec\ub77c\uc9c0\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: NON REPEATABLE READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: BEGIN\n Alice->>Database: UPDATE(Alice to Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT\n Database->>+Bob: Bob"}),"\n",(0,t.jsx)(n.h3,{id:"\ud32c\ud140-\ub9ac\ub4dcphantom-read-phantom-row",children:"\ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)"}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ucffc\ub9ac \uc218\ud589\uc2dc, \uc218\ud589 \uacb0\uacfc\uac00 \ub2e4\ub978 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud558\uace0 B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uc5ec A\uac00 \ub2e4\uc2dc \uc870\ud68c\ud560 \ub54c \uc874\uc7ac\ud558\uc9c0 \uc54a\uc740 \ub808\ucf54\ub4dc\uac00 \uc870\ud68c\ub418\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: PHANTOM READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN(TRX-ID: 1)\n Bob->>Database: SELECT COUNT\n Database->>+Bob: 1\n Alice->>Database: BEGIN(TRX-ID: 2)\n Alice->>Database: INSERT(Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT COUNT\n Database->>+Bob: 2"}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html",children:"Isolation Level, MySQL"})]})]})}function b(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,a)=>{a.d(n,{ah:()=>o});var t=a(67294);function r(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function i(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),a.push.apply(a,t)}return a}function l(e){for(var n=1;n=0||(r[a]=e[a]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var c=t.createContext({}),o=function(e){var n=t.useContext(c),a=n;return e&&(a="function"==typeof e?e(n):l(l({},n),e)),a},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},b=t.forwardRef((function(e,n){var a=e.components,r=e.mdxType,i=e.originalType,c=e.parentName,b=s(e,["components","mdxType","originalType","parentName"]),h=o(a),j=r,x=h["".concat(c,".").concat(j)]||h[j]||d[j]||i;return a?t.createElement(x,l(l({ref:n},b),{},{components:a})):t.createElement(x,l({ref:n},b))}));b.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6908],{90465:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>b,frontMatter:()=>i,metadata:()=>s,toc:()=>o});var t=a(85893),r=a(3905);const i={title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",slug:"transaction-and-isolation",tags:["DataBase","Transaction","Isolation"]},l=void 0,s={permalink:"/transaction-and-isolation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",source:"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",description:"\ud2b8\ub79c\uc7ad\uc158(Transaction)",date:"2023-04-05T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 5\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Transaction",permalink:"/tags/transaction"},{label:"Isolation",permalink:"/tags/isolation"}],readingTime:9.57,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",slug:"transaction-and-isolation",tags:["DataBase","Transaction","Isolation"]},unlisted:!1,prevItem:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",permalink:"/test-double"},nextItem:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/mysql-lock"}},c={authorsImageUrls:[]},o=[{value:"\ud2b8\ub79c\uc7ad\uc158(Transaction)",id:"\ud2b8\ub79c\uc7ad\uc158transaction",level:2},{value:"\ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)",id:"\ud2b8\ub79c\uc7ad\uc158\uc758-\uc18d\uc131acid",level:3},{value:"\ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d",id:"\ud2b8\ub79c\uc7ad\uc158-\uc8fc\uc758\uc0ac\ud56d",level:3},{value:"\uaca9\ub9ac \uc218\uc900(Isolation level)",id:"\uaca9\ub9ac-\uc218\uc900isolation-level",level:2},{value:"READ UNCOMMITTED",id:"read-uncommitted",level:3},{value:"READ COMMITTED",id:"read-committed",level:3},{value:"REPEATABLE READ",id:"repeatable-read",level:3},{value:"SERIALIZABLE",id:"serializable",level:3},{value:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c",id:"\uaca9\ub9ac-\uc218\uc900\uc5d0-\ub530\ub978-\ubd80\uc815\ud569-\ubb38\uc81c",level:2},{value:"\ub354\ud2f0 \ub9ac\ub4dc(Dirty read)",id:"\ub354\ud2f0-\ub9ac\ub4dcdirty-read",level:3},{value:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)",id:"\ubc18\ubcf5-\uac00\ub2a5\ud558\uc9c0-\uc54a\uc740-\uc870\ud68cnon-repeatable-read",level:3},{value:"\ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)",id:"\ud32c\ud140-\ub9ac\ub4dcphantom-read-phantom-row",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"\ud2b8\ub79c\uc7ad\uc158transaction",children:"\ud2b8\ub79c\uc7ad\uc158(Transaction)"}),"\n",(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub17c\ub9ac\uc801 \uae30\ub2a5\uc744 \uc218\ud589\ud558\uae30 \uc704\ud55c \uc791\uc5c5\uc758 \ub2e8\uc704\ub97c \ub9d0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc740 \uc791\uc5c5\uc758 \uc644\uc804\uc131\uacfc \ub370\uc774\ud130\uc758 \uc815\ud569\uc131\uc744 \ubcf4\uc7a5\ud574 \uc900\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub17c\ub9ac\uc801\uc778 \uc791\uc5c5 \uc14b\uc744 \uc644\ubcbd\ud558\uac8c \ucc98\ub9ac\ud558\uac70\ub098, \uc624\ub958 \uc2dc \uc791\uc5c5\uc758 \uc77c\ubd80\ub9cc \uc801\uc6a9\ub418\ub294 \ud604\uc0c1\uc744 \ub9c9\uc544\uc900\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud2b8\ub79c\uc7ad\uc158\uc758-\uc18d\uc131acid",children:"\ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc6d0\uc790\uc131(Atomicity): \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \uc2e4\ud589\ub41c \uc791\uc5c5\ub4e4\uc740 \ubaa8\ub450 \uc131\uacf5\ud558\uac70\ub098, \uc2e4\ud328\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc77c\uad00\uc131(Consistency): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc218\ud589\ub418\uae30 \uc804\uacfc \ud6c4\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc77c\uad00\ub41c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uaca9\ub9ac\uc131(Isolation): \uac01\uac01\uc758 \ud2b8\ub79c\uc7ad\uc158\uc740 \ub3c5\ub9bd\uc801\uc774\ub77c \uc11c\ub85c\uc5d0\uac8c \uc601\ud5a5\uc744 \uc8fc\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc9c0\uc18d\uc131(Durability): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c\ub2e4\uba74 \uc601\uad6c\uc801\uc73c\ub85c \uacb0\uacfc\uc5d0 \ubc18\uc601\ub418\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud2b8\ub79c\uc7ad\uc158-\uc8fc\uc758\uc0ac\ud56d",children:"\ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc740 \uaf2d \ud544\uc694\ud55c \ucd5c\uc18c\uc758 \ucf54\ub4dc\uc5d0\ub9cc \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.(\ud2b8\ub79c\uc7ad\uc158\uc758 \ubc94\uc704\ub97c \ucd5c\uc18c\ud654\ud558\ub77c)",(0,t.jsx)(n.br,{}),"\n","\uad6c\ud604\ud574\uc57c \ud558\ub294 \uc5c5\ubb34\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158\uc744 \ubb36\uac70\ub098 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\ub294 \uacbd\uc6b0 \ubc18\ub4dc\uc2dc \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsxs)(n.admonition,{title:"\uc65c \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\uc744 \ub54c \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud560\uae4c? \ud83e\udd14",type:"info",children:[(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\uc758 \uc77c\uad00\uc131\uacfc \uc548\uc804\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc744 \ud2b8\ub79c\uc7ad\uc158 \ub0b4\ubd80\uc5d0 \ud3ec\ud568\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4."]}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc911\uac04\uc5d0 \uc2e4\ud328\ud560 \uac00\ub2a5\uc131(\uc548\uc804\uc131 X)"}),"\n",(0,t.jsx)(n.li,{children:"\ud1b5\uc2e0\uc73c\ub85c \uc778\ud574 \ub370\uc774\ud130\uac00 \ubcc0\uacbd\ub420 \uc218 \uc788\ub294 \ubd80\ubd84(\uc77c\uad00\uc131 X)"}),"\n"]})]}),"\n",(0,t.jsx)(n.h2,{id:"\uaca9\ub9ac-\uc218\uc900isolation-level",children:"\uaca9\ub9ac \uc218\uc900(Isolation level)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc5ec\ub7ec \ud2b8\ub79c\uc7ad\uc158\uc774 \ub3d9\uc2dc\uc5d0 \ucc98\ub9ac\ub420 \ub54c \ud2b9\uc815 \ud2b8\ub79c\uc7ad\uc158\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\uc758 \uc870\ud68c \ubc0f \ubcc0\uacbd\uc744 \ud5c8\uc6a9\ud560\uc9c0 \uacb0\uc815\ud558\ub294 \uac83\uc744 \ub9d0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uaca9\ub9ac \uc218\uc900\uc774 \ub192\uc544\uc9c8 \uc218\ub85d \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\uc774 \ub5a8\uc5b4\uc9c0\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\uc9c0\ub9cc, ",(0,t.jsx)(n.code,{children:"SERIALIZABLE"}),"\uc774 \uc544\ub2c8\ub77c\uba74 \ud06c\uac8c \uc131\ub2a5\uc758 \uc800\ud558\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"read-uncommitted",children:"READ UNCOMMITTED"}),"\n",(0,t.jsxs)(n.p,{children:["\uac01 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\uc758 \ubcc0\uacbd \ub0b4\uc6a9\uc774 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774\ub098 ",(0,t.jsx)(n.code,{children:"ROLLBACK"})," \uc5ec\ubd80\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcf4\uc778\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub354\ud2f0 \ub9ac\ub4dc \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud558\uae30 \ub54c\ubb38\uc5d0 \uc815\ud569\uc131\uc758 \ubb38\uc81c\uac00 \ub9ce\uc740 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL \uc0ac\uc6a9\uc2dc \ucd5c\uc18c ",(0,t.jsx)(n.code,{children:"READ COMMITTED"})," \uc774\uc0c1\uc758 \uaca9\ub9ac \uc218\uc900 \uc0ac\uc6a9\uc744 \uad8c\uc7a5\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: READ UNCOMMITTED\n---\nsequenceDiagram\n Alice->>Database: BEGIN\n Alice->>Database: INSERT(Alice)\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: COMMIT(Alice)"}),"\n",(0,t.jsx)(n.h3,{id:"read-committed",children:"READ COMMITTED"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774 \uc644\ub8cc\ub41c \ub370\uc774\ud130\ub9cc \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc870\ud68c\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub77c\ud074 DBMS\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.code,{children:"REPEATABLE READ"}),"\uac00 \ubcf4\uc7a5\ub418\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 ",(0,t.jsx)(n.code,{children:"NON-REPEATABLE READ"})," \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: READ COMMITTED\n---\nsequenceDiagram\n Alice->>Database: BEGIN\n Alice->>Database: UPDATE(Alice to Bob)\n Bob->>Database: SELECT\n Database->>+Bob: Alice(Undo log)\n Alice->>Database: COMMIT"}),"\n",(0,t.jsx)(n.h3,{id:"repeatable-read",children:"REPEATABLE READ"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc774 \uc2dc\uc791\ub418\uae30 \uc804\uc5d0 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774 \uc644\ub8cc\ub41c \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub9cc \uc870\ud68c\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL\uc758 InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MVCC\ub97c \uc774\uc6a9\ud574 \uc5b8\ub450(Undo) \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \uc774\uc804 \ub370\uc774\ud130\ub97c \uc774\uc6a9\ud574 \ub3d9\uc77c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc5ec\uc904 \uc218 \uc788\uac8c \ubcf4\uc7a5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc7a5\ud558\ub294 \ubc29\ubc95\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ubaa8\ub4e0 InnoDB \ud2b8\ub79c\uc7ad\uc158\uc740 \uc21c\ucc28\uc801\uc73c\ub85c \uc99d\uac00\ud558\ub294 \uace0\uc720\ud55c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ub97c \uac00\uc9c4\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Undo \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \ub808\ucf54\ub4dc\uc5d0\ub294 \ubcc0\uacbd\uc744 \ubc1c\uc0dd\uc2dc\ud0a8 \ud2b8\ub79c\uc7ad\uc158\uc758 \ubc88\ud638\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Undo \uc601\uc5ed\uc758 \ubc31\uc5c5\ub41c \ub370\uc774\ud130\ub294 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774 \ubd88\ud544\uc694\ud558\ub2e4\uace0 \ud310\ub2e8\ud558\ub294 \uacbd\uc6b0 \uc0ad\uc81c\ub41c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c\ub294 MVCC\ub97c \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \uac00\uc7a5 \uc624\ub798\ub41c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ubcf4\ub2e4 \uc55e\uc120 Undo \uc601\uc5ed\uc758 \ub370\uc774\ud130\ub294 \uc0ad\uc81c\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"InnoDB\uc5d0\uc11c\ub294 \uac2d \ub77d\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc744 \uc774\uc6a9\ud558\uc5ec \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc744 \ubc29\uc9c0\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: REPEATABLE READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN(TRX-ID: 1)\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: BEGIN(TRX-ID: 2)\n Alice->>Database: UPDATE(Alice to Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT\n Database->>+Bob: Alice(Undo log)"}),"\n",(0,t.jsx)(n.admonition,{title:"\uac2d \ub78d(Gap lock)\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d(Next-key lock)",type:"note",children:(0,t.jsxs)(n.p,{children:["\uac2d \ub77d: \ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub125\uc2a4\ud2b8 \ud0a4 \ub77d: \ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4."]})}),"\n",(0,t.jsxs)(n.admonition,{title:"MVCC(Multi Version Concurrency Control)",type:"note",children:[(0,t.jsx)(n.p,{children:"\ub3d9\uc2dc\uc131\uc744 \uc81c\uc5b4\ud558\ub294 \ubc29\ubc95 \uc911 \ud558\ub098\ub85c \ud558\ub098\uc758 \ub808\ucf54\ub4dc\uc5d0 \ub300\ud574 \uc5ec\ub7ec \uac1c\uc758 \ubc84\uc804\uc774 \ub3d9\uc2dc\uc5d0 \uad00\ub9ac\ub418\ub294 \uac83\uc774\ub2e4."}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"PostgreSQL\uc740 \ub2e4\uc911 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uac83\uc73c\ub85c MVCC\ub97c \uad6c\ud604\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:["Oracle, InnoDB\ub294 ",(0,t.jsx)(n.code,{children:"Undo log"}),"\ub97c \uc774\uc6a9\ud574 \uc774 \uae30\ub2a5\uc744 \uad6c\ud604\ud55c\ub2e4.(\ucd5c\uc2e0 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub9cc DB\uc5d0 \uc800\uc7a5)"]}),"\n"]}),(0,t.jsx)(n.p,{children:"\uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc77d\uad00\ub41c \uc77d\uae30\ub97c \uc81c\uacf5\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4."})]}),"\n",(0,t.jsx)(n.h3,{id:"serializable",children:"SERIALIZABLE"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc9c4\ud589\uc2dc\ud0a4\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uace0 \ub530\ub77c\uc11c \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\ub3c4 \ub2e4\ub978 \uaca9\ub9ac \uc218\uc900\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c4\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uace0 \uc4f0\ub294 \ub808\ucf54\ub4dc\ub97c \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\ub294 \uc811\uadfc\ud560 \uc218 \uc5c6\uace0 \ub2e8\uc21c\ud55c \uc77d\uae30 \uc791\uc5c5\ub3c4 \uacf5\uc720 \uc7a0\uae08(\uc77d\uae30 \uc7a0\uae08)\uc744 \ud68d\ub4dd\ud574\uc57c\ub9cc \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB\uc5d0\uc11c\ub294 \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc774 ",(0,t.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uad73\uc774 \uc0ac\uc6a9\ud560 \ud544\uc694\ub294 \uc5c6\ub2e4."]}),"\n",(0,t.jsx)(n.h2,{id:"\uaca9\ub9ac-\uc218\uc900\uc5d0-\ub530\ub978-\ubd80\uc815\ud569-\ubb38\uc81c",children:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c"}),"\n",(0,t.jsx)(n.p,{children:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ub354\ud2f0 \ub9ac\ub4dc, \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c, \ud32c\ud140 \ub9ac\ub4dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"\uaca9\ub9ac \uc218\uc900 / \ubd80\uc815\ud569 \ubb38\uc81c"}),(0,t.jsx)(n.th,{children:"\ub354\ud2f0 \ub9ac\ub4dc"}),(0,t.jsx)(n.th,{children:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c"}),(0,t.jsx)(n.th,{children:"\ud32c\ud140 \ub9ac\ub4dc"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"READ UNCOMMITTED"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"READ COMMITTED"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"REPEATABLE READ"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"O(InnoDB\ub294 X)"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SERIALIZABLE"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"\ub354\ud2f0-\ub9ac\ub4dcdirty-read",children:"\ub354\ud2f0 \ub9ac\ub4dc(Dirty read)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc5b4\ub5a4 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c \uc791\uc5c5\uc774 \uc644\ub8cc\ub418\uc9c0 \uc54a\uc558\uc5b4\ub3c4 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcfc \uc218 \uc788\ub294 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \uc218\uc900\uc774 READ UNCOMMITTED\uc77c \ub54c \ubc1c\uc0dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc608) B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uace0 \ucee4\ubc0b\uc744 \ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, A\uac00 \ud574\ub2f9 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud560 \uc218 \uc788\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc18\ubcf5-\uac00\ub2a5\ud558\uc9c0-\uc54a\uc740-\uc870\ud68cnon-repeatable-read",children:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)"}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc758 \uac19\uc740 \ud589\uc5d0 \ub450 \ubc88 \uc774\uc0c1 \uc870\ud68c\uac00 \ubc1c\uc0dd\ud588\ub294\ub370, \uadf8 \uac12\uc774 \ub2e4\ub978 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc5ec\ub7ec \ubc88 \uc870\ud68c\ud558\ub358 \uc911 B\uac00 \ub808\ucf54\ub4dc\ub97c \ubcc0\uacbd\ud558\uc5ec A\uac00 \uc870\ud68c\ud55c \uac12\uc774 \ub2ec\ub77c\uc9c0\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: NON REPEATABLE READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: BEGIN\n Alice->>Database: UPDATE(Alice to Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT\n Database->>+Bob: Bob"}),"\n",(0,t.jsx)(n.h3,{id:"\ud32c\ud140-\ub9ac\ub4dcphantom-read-phantom-row",children:"\ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)"}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ucffc\ub9ac \uc218\ud589\uc2dc, \uc218\ud589 \uacb0\uacfc\uac00 \ub2e4\ub978 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud558\uace0 B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uc5ec A\uac00 \ub2e4\uc2dc \uc870\ud68c\ud560 \ub54c \uc874\uc7ac\ud558\uc9c0 \uc54a\uc740 \ub808\ucf54\ub4dc\uac00 \uc870\ud68c\ub418\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: PHANTOM READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN(TRX-ID: 1)\n Bob->>Database: SELECT COUNT\n Database->>+Bob: 1\n Alice->>Database: BEGIN(TRX-ID: 2)\n Alice->>Database: INSERT(Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT COUNT\n Database->>+Bob: 2"}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html",children:"Isolation Level, MySQL"})]})]})}function b(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,a)=>{a.d(n,{ah:()=>o});var t=a(67294);function r(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function i(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),a.push.apply(a,t)}return a}function l(e){for(var n=1;n=0||(r[a]=e[a]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var c=t.createContext({}),o=function(e){var n=t.useContext(c),a=n;return e&&(a="function"==typeof e?e(n):l(l({},n),e)),a},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},b=t.forwardRef((function(e,n){var a=e.components,r=e.mdxType,i=e.originalType,c=e.parentName,b=s(e,["components","mdxType","originalType","parentName"]),h=o(a),j=r,x=h["".concat(c,".").concat(j)]||h[j]||d[j]||i;return a?t.createElement(x,l(l({ref:n},b),{},{components:a})):t.createElement(x,l({ref:n},b))}));b.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/79a97f4e.6cfb3091.js b/assets/js/79a97f4e.d4ad7d18.js similarity index 96% rename from assets/js/79a97f4e.6cfb3091.js rename to assets/js/79a97f4e.d4ad7d18.js index 0c63cac48..ce6afd102 100644 --- a/assets/js/79a97f4e.6cfb3091.js +++ b/assets/js/79a97f4e.d4ad7d18.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6412],{13408:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>s,metadata:()=>i,toc:()=>l});var n=t(85893),o=t(3905);const s={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",slug:"woowacourse-level2-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/woowacourse-level2-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",description:"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.",date:"2023-06-11T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:2.545,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",slug:"woowacourse-level2-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"Docusaurus",permalink:"/docusaurus"},nextItem:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",permalink:"/level2-interview-retrospective"}},a={authorsImageUrls:[]},l=[{value:"\ud559\uc2b5",id:"\ud559\uc2b5",level:3},{value:"\uc218\uba74",id:"\uc218\uba74",level:3},{value:"\ud611\uc5c5",id:"\ud611\uc5c5",level:3},{value:"\ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70",id:"\ub808\ubca8-2\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70",level:3}];function p(e){const r={br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(r.p,{children:["23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ube60\ub974\uac8c \uc9c0\ub098\uac00\uc11c \uc870\uae08 \uc544\uc27d\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud559\uc2b5",children:"\ud559\uc2b5"}),"\n",(0,n.jsxs)(r.p,{children:["\ud68c\uace0\ub97c \uc791\uc131\ud558\uae30 \uc804\uc5d0 \ub808\ubca8 2 \ub3d9\uc548 \ubcf4\ub0c8\ub358 PR\uacfc \ud68c\uace0\ub97c \ucb49 \uc77d\uc5b4\ubd24\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud56d\uc0c1 \uc544\uc26c\uc6b4 \uacf3\uc740 \uc788\uae30 \ub9c8\ub828\uc774\uc9c0\ub9cc, \uc798 \ud559\uc2b5\ud55c \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc744 \ud558\uba74\uc11c \uae30\uc220\uc744 \uc5b4\ub5bb\uac8c \uc120\ud0dd\ud558\uace0, \uc801\uc6a9\ud560 \uac83\uc778\uc9c0 \uace0\ubbfc\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \uaf64\ub098 \ub9ce\uc740 \uc131\uc7a5\uc744 \ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\uace0\ubbfc\uc740 \uae4a\uc5c8\uc9c0\ub9cc \uc774\ub860\uc801\uc778 \ud559\uc2b5\uc774 \ubd80\uc871\ud55c \ub808\ubca8 2\uc600\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc29\ud559 \uadf8\ub9ac\uace0 \ub808\ubca8 3 \ub54c\ub294 \uc870\uae08 \ub354 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc744 \ud559\uc2b5\ud558\ub294\ub370 \uc9d1\uc911\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\uc810\ucc28 \ud559\uc2b5 \ubc94\uc704\uac00 \ub113\uc5b4\uc9c0\uba74\uc11c \uc790\uc5f0\uc2a4\ub7fd\uac8c \ubaa8\ub974\ub294 \ub0b4\uc6a9\uc774 \uc313\uc5ec\uac04\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud544\uc694\ud55c \ub0b4\uc6a9\uc740 \uc55e\uc73c\ub85c \ucc9c\ucc9c\ud788 \ud559\uc2b5\ud558\uba74 \ub418\ub2c8\uae4c \uc870\uae09\ud574\uc9c0\uc9c0 \ub9d0\uc544\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc218\uba74",children:"\uc218\uba74"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 2\ub97c \uc9c4\ud589\ud558\ub294 \ub3d9\uc548 \uc218\uba74\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\uc5c8\uace0, \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \uadf8\ub0a0\uc758 \ucee8\ub514\uc158\uc744 \ub9ce\uc774 \uc88c\uc6b0\ud588\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc218\uba74 \uc2dc\uac04\uc744 \ub298\ub9ac\uace0, \uc88b\uc740 \uc218\uba74 \uc2b5\uad00\uc744 \uac00\uc9c0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud611\uc5c5",children:"\ud611\uc5c5"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 2 \ub9c8\uc9c0\ub9c9\uc5d0 \ud611\uc5c5 \ubbf8\uc158\uc774 \uc788\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc9c0\uae08\uae4c\uc9c0\ub294 \ubc31\uc5d4\ub4dc \ud06c\ub8e8\ub4e4\uacfc \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \ud611\uc5c5\uc744 \uacbd\ud5d8\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \ud504\ub7f0\ud2b8\uc5d4\ub4dc \ud06c\ub8e8\uc640 \ud611\uc5c5\uc744 \ud588\ub2e4. \uc18c\ud1b5\uc740 \uc798 \ub41c \uac83 \uac19\uc9c0\ub9cc API \uba85\uc138\ub97c \uc815\ud558\ub294 \ubd80\ubd84\uc774 \uc544\uc9c1 \ubbf8\uc219\ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 3 \ub54c\ubd80\ud130 \ubcf8\uaca9\uc801\uc73c\ub85c \ud504\ub85c\uc81d\ud2b8\uac00 \uc2dc\uc791\ub41c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud300\uc744 \uc704\ud574 \uc5b4\ub5a4 \uac83\uc744 \ud560 \uc218 \uc788\uc744\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud574\ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ub808\ubca8-2\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70",children:"\ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70"}),"\n",(0,n.jsx)(r.p,{children:"\ud68c\uace0 \uc791\uc131\ud558\uba74\uc11c \ub808\ubca8 2\uc5d0\uc11c \ud588\ub358 \uac83\ub4e4\uc744 \ubc18\ucd94\ud574 \ubd24\ub294\ub370 \ubd80\uc871\ud55c \uc810\uc740 \ub9ce\uc558\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \uac00\uace0 \uc788\ub294 \uac83 \uac19\ub2e4.\n\uc77d\uace0 \uc2f6\uc740 \ucc45\ub3c4 \uc77d\uace0, \ubd80\uc871\ud55c \ubd80\ubd84 \ucc44\uc6b0\uba74\uc11c \uc26c\uc5b4\uc57c\uaca0\ub2e4."})]})}function u(e={}){const{wrapper:r}={...(0,o.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function s(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,s=e.originalType,a=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),d=l(t),h=o,b=d["".concat(a,".").concat(h)]||d[h]||p[h]||s;return t?n.createElement(b,c(c({ref:r},u),{},{components:t})):n.createElement(b,c({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6412],{13408:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>s,metadata:()=>i,toc:()=>l});var n=t(85893),o=t(3905);const s={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",slug:"woowacourse-level2-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/woowacourse-level2-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",description:"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.",date:"2023-06-11T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:2.545,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",slug:"woowacourse-level2-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",permalink:"/level2-interview-retrospective"},nextItem:{title:"Docusaurus",permalink:"/docusaurus"}},a={authorsImageUrls:[]},l=[{value:"\ud559\uc2b5",id:"\ud559\uc2b5",level:3},{value:"\uc218\uba74",id:"\uc218\uba74",level:3},{value:"\ud611\uc5c5",id:"\ud611\uc5c5",level:3},{value:"\ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70",id:"\ub808\ubca8-2\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70",level:3}];function p(e){const r={br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(r.p,{children:["23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ube60\ub974\uac8c \uc9c0\ub098\uac00\uc11c \uc870\uae08 \uc544\uc27d\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud559\uc2b5",children:"\ud559\uc2b5"}),"\n",(0,n.jsxs)(r.p,{children:["\ud68c\uace0\ub97c \uc791\uc131\ud558\uae30 \uc804\uc5d0 \ub808\ubca8 2 \ub3d9\uc548 \ubcf4\ub0c8\ub358 PR\uacfc \ud68c\uace0\ub97c \ucb49 \uc77d\uc5b4\ubd24\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud56d\uc0c1 \uc544\uc26c\uc6b4 \uacf3\uc740 \uc788\uae30 \ub9c8\ub828\uc774\uc9c0\ub9cc, \uc798 \ud559\uc2b5\ud55c \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc744 \ud558\uba74\uc11c \uae30\uc220\uc744 \uc5b4\ub5bb\uac8c \uc120\ud0dd\ud558\uace0, \uc801\uc6a9\ud560 \uac83\uc778\uc9c0 \uace0\ubbfc\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \uaf64\ub098 \ub9ce\uc740 \uc131\uc7a5\uc744 \ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\uace0\ubbfc\uc740 \uae4a\uc5c8\uc9c0\ub9cc \uc774\ub860\uc801\uc778 \ud559\uc2b5\uc774 \ubd80\uc871\ud55c \ub808\ubca8 2\uc600\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc29\ud559 \uadf8\ub9ac\uace0 \ub808\ubca8 3 \ub54c\ub294 \uc870\uae08 \ub354 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc744 \ud559\uc2b5\ud558\ub294\ub370 \uc9d1\uc911\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\uc810\ucc28 \ud559\uc2b5 \ubc94\uc704\uac00 \ub113\uc5b4\uc9c0\uba74\uc11c \uc790\uc5f0\uc2a4\ub7fd\uac8c \ubaa8\ub974\ub294 \ub0b4\uc6a9\uc774 \uc313\uc5ec\uac04\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud544\uc694\ud55c \ub0b4\uc6a9\uc740 \uc55e\uc73c\ub85c \ucc9c\ucc9c\ud788 \ud559\uc2b5\ud558\uba74 \ub418\ub2c8\uae4c \uc870\uae09\ud574\uc9c0\uc9c0 \ub9d0\uc544\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc218\uba74",children:"\uc218\uba74"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 2\ub97c \uc9c4\ud589\ud558\ub294 \ub3d9\uc548 \uc218\uba74\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\uc5c8\uace0, \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \uadf8\ub0a0\uc758 \ucee8\ub514\uc158\uc744 \ub9ce\uc774 \uc88c\uc6b0\ud588\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc218\uba74 \uc2dc\uac04\uc744 \ub298\ub9ac\uace0, \uc88b\uc740 \uc218\uba74 \uc2b5\uad00\uc744 \uac00\uc9c0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud611\uc5c5",children:"\ud611\uc5c5"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 2 \ub9c8\uc9c0\ub9c9\uc5d0 \ud611\uc5c5 \ubbf8\uc158\uc774 \uc788\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc9c0\uae08\uae4c\uc9c0\ub294 \ubc31\uc5d4\ub4dc \ud06c\ub8e8\ub4e4\uacfc \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \ud611\uc5c5\uc744 \uacbd\ud5d8\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \ud504\ub7f0\ud2b8\uc5d4\ub4dc \ud06c\ub8e8\uc640 \ud611\uc5c5\uc744 \ud588\ub2e4. \uc18c\ud1b5\uc740 \uc798 \ub41c \uac83 \uac19\uc9c0\ub9cc API \uba85\uc138\ub97c \uc815\ud558\ub294 \ubd80\ubd84\uc774 \uc544\uc9c1 \ubbf8\uc219\ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 3 \ub54c\ubd80\ud130 \ubcf8\uaca9\uc801\uc73c\ub85c \ud504\ub85c\uc81d\ud2b8\uac00 \uc2dc\uc791\ub41c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud300\uc744 \uc704\ud574 \uc5b4\ub5a4 \uac83\uc744 \ud560 \uc218 \uc788\uc744\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud574\ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ub808\ubca8-2\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70",children:"\ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70"}),"\n",(0,n.jsx)(r.p,{children:"\ud68c\uace0 \uc791\uc131\ud558\uba74\uc11c \ub808\ubca8 2\uc5d0\uc11c \ud588\ub358 \uac83\ub4e4\uc744 \ubc18\ucd94\ud574 \ubd24\ub294\ub370 \ubd80\uc871\ud55c \uc810\uc740 \ub9ce\uc558\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \uac00\uace0 \uc788\ub294 \uac83 \uac19\ub2e4.\n\uc77d\uace0 \uc2f6\uc740 \ucc45\ub3c4 \uc77d\uace0, \ubd80\uc871\ud55c \ubd80\ubd84 \ucc44\uc6b0\uba74\uc11c \uc26c\uc5b4\uc57c\uaca0\ub2e4."})]})}function u(e={}){const{wrapper:r}={...(0,o.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function s(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,s=e.originalType,a=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),d=l(t),h=o,b=d["".concat(a,".").concat(h)]||d[h]||p[h]||s;return t?n.createElement(b,c(c({ref:r},u),{},{components:t})):n.createElement(b,c({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/814f3328.2e60c17f.js b/assets/js/814f3328.2e60c17f.js deleted file mode 100644 index 0dd126537..000000000 --- a/assets/js/814f3328.2e60c17f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2535],{45641:e=>{e.exports=JSON.parse('{"title":"Recent posts","items":[{"title":"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0","permalink":"/refactoring-retrospective","unlisted":false},{"title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/jdbc-retrospective","unlisted":false},{"title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/mvc-retrospective","unlisted":false},{"title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","permalink":"/spring-test-isolation","unlisted":false},{"title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","permalink":"/web-application-evolution","unlisted":false}]}')}}]); \ No newline at end of file diff --git a/assets/js/814f3328.e1e03de9.js b/assets/js/814f3328.e1e03de9.js new file mode 100644 index 000000000..83043222a --- /dev/null +++ b/assets/js/814f3328.e1e03de9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2535],{45641:e=>{e.exports=JSON.parse('{"title":"Recent posts","items":[{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","permalink":"/book-writer","unlisted":false},{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective","unlisted":false},{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation","unlisted":false},{"title":"JSR-310","permalink":"/jsr-310","unlisted":false},{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null","unlisted":false}]}')}}]); \ No newline at end of file diff --git a/assets/js/829fa7b9.c29a2b79.js b/assets/js/829fa7b9.893198b6.js similarity index 97% rename from assets/js/829fa7b9.c29a2b79.js rename to assets/js/829fa7b9.893198b6.js index 556f05e63..22cc14b37 100644 --- a/assets/js/829fa7b9.c29a2b79.js +++ b/assets/js/829fa7b9.893198b6.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9391],{4565:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>i,toc:()=>a});var t=r(85893),s=r(3905);const l={title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",slug:"book-leadership-and-self-deception",tags:["Book"]},o=void 0,i={permalink:"/book-leadership-and-self-deception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",source:"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",description:"\ucc45 \uc815\ubcf4",date:"2023-04-08T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 8\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:5.16,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",slug:"book-leadership-and-self-deception",tags:["Book"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",permalink:"/tecochat-retrospective-1"},nextItem:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/innodb-lock"}},c={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18",id:"\uc790\uae30\uae30\ub9cc\uacfc-\uc790\uae30\ubc30\ubc18",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function b(e){const n={blockquote:"blockquote",br:"br",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",(0,t.jsx)(n.br,{}),"\n","\uc544\ube48\uc800\uc5f0\uad6c\uc18c"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc790\uae30\uae30\ub9cc\uacfc-\uc790\uae30\ubc30\ubc18",children:"\uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18"}),"\n",(0,t.jsx)(n.p,{children:"\ucc45\uc5d0\uc11c\ub294 \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc744 \ub2e4\ub8ec\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc790\uae30\uae30\ub9cc: \uc790\uc2e0\uc758 \ubb38\uc81c\ub97c \uc778\uc815\ud558\uc9c0 \uc54a\ub294 \uac83"}),"\n",(0,t.jsx)(n.li,{children:"\uc790\uae30\ubc30\ubc18: \ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ubb34\uc5b8\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uc744 \ubc18\ud558\ub294 \ud589\uc704"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc790\uae30\ubc30\ubc18\uc744 \ud55c\ub2e4\uba74 \uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uc5d0 \ube60\uc9c0\ub294 \uac83\uc744 \ucc45\uc5d0\uc11c\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac04\ub2e4\uace0 \ud45c\ud604\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\ucd5c\uadfc\uc5d0 \uc77d\uc740 \ucc45 \uc911 \uac00\uc7a5 \ub9c8\uc74c\uc774 \ubd88\ud3b8\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub807\uae30\uc5d0 \ub354\ub354\uc6b1 \ub098\uc5d0\uac8c \ud544\uc694\ud55c \ub0b4\uc6a9\uc774 \ub2f4\uaca8\uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\uc0b4\uba74\uc11c \ub9ce\uc740 \uc120\ud0dd\uc758 \uc21c\uac04\uc774 \uc874\uc7ac\ud588\uace0, \uadf8 \uc21c\uac04\ub9c8\ub2e4 \uc790\uae30\ubc30\ubc18\uc744 \ud0dd\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc791\uac8c\ub294 \uc9d1\uc548\uc77c\uc744 \ud574\uc57c \ud558\ub294\ub370 \ubab8\uc774 \uc870\uae08 \ud798\ub4e4\ub2e4\uace0 \ud558\uc9c0 \uc54a\uac70\ub098",(0,t.jsx)(n.br,{}),"\n","\ud06c\uac8c\ub294 \uc798\ubabb\uc744 \uc778\uc815\ud574\uc57c \ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uadf8\ub7ec\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub7f0 \uc0c1\ud669\uc774 \ubc18\ubcf5\ub418\uc5b4 \uacb0\uad6d \uc0c1\uc790 \uc548\uc5d0 \ub098 \uc790\uc2e0\uc744 \uac00\ub450\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ub354 \ub098\uc740 \uc0b6\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \uc9c0\uc18d\uc801\uc73c\ub85c \ud655\uc778\ud558\uace0, \uc0c1\uc790 \ubc16\uc73c\ub85c \ub098\uac00\ub824\ub294 \uc5f0\uc2b5\uc744 \ud574\uc57c\uaca0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub113\uc740 \uc2dc\uc120\uc744 \uac00\uc9c0\uace0, \ud56d\uc0c1 \ub0b4\uac00 \ud2c0\ub9b4 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc0dd\uac01\ud558\uace0 \uc0b4\uc544\uac00\uc790."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uc758 \uc0dd\uac01\uc740 \uc9c0\uc2dd\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc9c0\uc2dd\uc740 \uc0ac\ub791\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc0ac\ub791\uc740 \uc874\uc7ac\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc0dd\uac01\ud558\ub294 \ub098\ub294 \uc2e4\uc81c\uc758 \ub098\ubcf4\ub2e4 \uadf8\ub9cc\ud07c \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","R. D. \ub7ad",(0,t.jsx)(n.br,{}),"\n","p.19"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uac00 \uc678\uc801\uc73c\ub85c \uc5b4\ub5a4 \ud589\ub3d9\uc744 \ud558\ub4e0\uc9c0 \uac04\uc5d0, \uc0ac\ub78c\ub4e4\uc740 \uc6b0\ub9ac \ub9c8\uc74c\uc5d0\uc11c \uadf8\ub4e4\uc744 \uc5b4\ub5bb\uac8c \ub300\ud558\uace0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \uc8fc\ub85c \ubc18\uc751\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uac00 \uc0ac\ub78c\ub4e4\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \ub290\ub07c\uac8c \ub418\ub294\uc9c0\ub294 \uc6b0\ub9ac\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \ud639\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c0\uac8c \ub429\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.66"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ube44\ub09c\uc740 \uac10\uc815\uc5d0 \uc18d\ud558\uace0 \ub099\uad00\uc740 \uc758\uc9c0\uc5d0 \uc18d\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc778\uac04\uc740 \uac10\uc815\ubcf4\ub2e4 \ub354 \ud070 \uc874\uc7ac\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc54c\ub7ad, \ud0c1\ub2db\ud55c",(0,t.jsx)(n.br,{}),"\n","p.103"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uac00 \uc790\uc2e0\uc5d0\uac8c\ub9cc \uc9d1\uc911\ud558\uace0 \uc788\ub294 \ud55c, \ud63c\uc790\uc11c \uc77c\ud558\ub294 \uac83 \uc774\uc0c1\uc758 \ucc3d\uc870\uc801\uc778 \uacb0\uacfc\ub098 \ud611\ub825\uc744 \uc774\ub04c\uc5b4 \ub0b8\ub2e4\ub294 \uac83\uc740 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub298\ub0a0 \uacbd\uc81c \ud658\uacbd\uc5d0\uc11c\ub294 \ud63c\uc790\uc11c\ub294 \uc77c\uc758 \uacb0\uacfc\ub97c \ud0c1\uc6d4\ud558\uac8c \ub9cc\ub4e4\uc5b4 \ub0b4\uae30\uac00 \uc5b4\ub835\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub0b4\uac00 \uc911\uc2ec\uc774\uc5b4\uc57c \ub41c\ub2e4\ub294 \ud3d0\uc1c4\uc801\uc778 \uc0ac\uace0\ub294 \ud568\uaed8 \uc77c\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uc5f4\uc815\uc744 \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.175"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc194\uc9c1\ud568\uc740 \uc6b0\ub9ac\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\ub294 \uc5f4\uc1e0\uc785\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\uc740 \uc790\uc2e0\uc758 \ud589\ub3d9\uacfc \uad00\ub828\ub41c \uc0ac\ub78c\uc5d0 \ub300\ud574 \uae30\uaebc\uc774 \uc0ac\uacfc\ub97c \ud558\ub294 \uac83\uc785\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\ub9cc\uc774 \uc2e4\ud0c0\ub798\ucc98\ub7fc \uc5c9\ud0a8 \uad00\uacc4\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\uc8e0.",(0,t.jsx)(n.br,{}),"\n","p.188"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ub204\uad70\uac00\ub97c \ub098\uc640 \uac19\uc774 \ub3d9\uc77c\ud55c \uac00\uce58\ub97c \uc9c0\ub2cc \ud55c \uc778\uac04\uc73c\ub85c \uc0dd\uac01\ud574\uc11c \uadf8 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \ubc16\uc5d0 \uacc4\uc18d \uba38\ubb34\ub974\uace0 \uc2f6\uc740 \uc5f4\ub9dd\uc774 \uc0dd\uae38 \ub54c, \ub098\ub294 \uc774\ubbf8 \uadf8 \uc0ac\ub78c\uc5d0 \ub300\ud574 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.214"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ub300\ubd80\ubd84\uc758 \uc0ac\ub78c\ub4e4\uc774 \uad00\uacc4 \uae30\uc220\uc744 \uac00\uc9c0\uace0 \uadf8\ub4e4\uc774 \uacaa\uace0 \uc788\ub294 \ubb38\uc81c\ub97c \ubc14\ub85c\uc7a1\uc73c\ub824\uace0 \ud558\ub294 \ub178\ub825\uc774 \uacb0\uc2e4\uc744 \uc5bb\uc9c0 \ubabb\ud558\ub294 \uac83\uc740 \uacb0\ucf54 \uadf8\ub7ec\ud55c \uae30\uc220 \ubd80\uc871 \ub54c\ubb38\uc5d0 \uc0dd\uae30\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\ub4e4\uc740 \uc790\uae30\ubc30\ubc18 \ub54c\ubb38\uc5d0 \uc0dd\uaca8\ub0a9\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.224"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\ub294 \ud568\uaed8 \uc77c\ud558\uace0 \uc6b0\ub9ac\uc640 \ud568\uaed8 \uc0b4\uc544\uac00\ub294 \uc0ac\ub78c\uc774 \uc9c4\uc815\uc73c\ub85c \ub204\uad6c\uc778\uc9c0 \uc54c\uc9c0 \ubabb\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uac00 \uadf8\ub4e4\uacfc \uc9c4\uc815\uc73c\ub85c \ud568\uaed8 \uc18c\ud1b5\ud558\uae30 \uc804\uae4c\uc9c0\ub294 \uc6b0\ub9ac\ub294 \uadf8\ub4e4\uc758 \uac00\uce58\ub97c \uc798 \ubaa8\ub985\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc704\ub300\ud568\uc774\ub780 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc704\ub300\ud55c \uc810\uc744 \ubc1c\uacac\ud574 \uc8fc\ub294 \uac83\uc5d0 \uc788\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.280"]}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(b,{...e})}):b(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var c=t.createContext({}),a=function(e){var n=t.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},b={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,l=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),j=a(r),d=s,x=j["".concat(c,".").concat(d)]||j[d]||b[d]||l;return r?t.createElement(x,o(o({ref:n},p),{},{components:r})):t.createElement(x,o({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9391],{4565:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>i,toc:()=>a});var t=r(85893),s=r(3905);const l={title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",slug:"book-leadership-and-self-deception",tags:["Book"]},o=void 0,i={permalink:"/book-leadership-and-self-deception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",source:"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",description:"\ucc45 \uc815\ubcf4",date:"2023-04-08T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 8\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:5.16,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",slug:"book-leadership-and-self-deception",tags:["Book"]},unlisted:!1,prevItem:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/innodb-lock"},nextItem:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",permalink:"/tecochat-retrospective-1"}},c={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18",id:"\uc790\uae30\uae30\ub9cc\uacfc-\uc790\uae30\ubc30\ubc18",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function b(e){const n={blockquote:"blockquote",br:"br",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",(0,t.jsx)(n.br,{}),"\n","\uc544\ube48\uc800\uc5f0\uad6c\uc18c"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc790\uae30\uae30\ub9cc\uacfc-\uc790\uae30\ubc30\ubc18",children:"\uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18"}),"\n",(0,t.jsx)(n.p,{children:"\ucc45\uc5d0\uc11c\ub294 \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc744 \ub2e4\ub8ec\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc790\uae30\uae30\ub9cc: \uc790\uc2e0\uc758 \ubb38\uc81c\ub97c \uc778\uc815\ud558\uc9c0 \uc54a\ub294 \uac83"}),"\n",(0,t.jsx)(n.li,{children:"\uc790\uae30\ubc30\ubc18: \ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ubb34\uc5b8\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uc744 \ubc18\ud558\ub294 \ud589\uc704"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc790\uae30\ubc30\ubc18\uc744 \ud55c\ub2e4\uba74 \uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uc5d0 \ube60\uc9c0\ub294 \uac83\uc744 \ucc45\uc5d0\uc11c\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac04\ub2e4\uace0 \ud45c\ud604\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\ucd5c\uadfc\uc5d0 \uc77d\uc740 \ucc45 \uc911 \uac00\uc7a5 \ub9c8\uc74c\uc774 \ubd88\ud3b8\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub807\uae30\uc5d0 \ub354\ub354\uc6b1 \ub098\uc5d0\uac8c \ud544\uc694\ud55c \ub0b4\uc6a9\uc774 \ub2f4\uaca8\uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\uc0b4\uba74\uc11c \ub9ce\uc740 \uc120\ud0dd\uc758 \uc21c\uac04\uc774 \uc874\uc7ac\ud588\uace0, \uadf8 \uc21c\uac04\ub9c8\ub2e4 \uc790\uae30\ubc30\ubc18\uc744 \ud0dd\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc791\uac8c\ub294 \uc9d1\uc548\uc77c\uc744 \ud574\uc57c \ud558\ub294\ub370 \ubab8\uc774 \uc870\uae08 \ud798\ub4e4\ub2e4\uace0 \ud558\uc9c0 \uc54a\uac70\ub098",(0,t.jsx)(n.br,{}),"\n","\ud06c\uac8c\ub294 \uc798\ubabb\uc744 \uc778\uc815\ud574\uc57c \ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uadf8\ub7ec\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub7f0 \uc0c1\ud669\uc774 \ubc18\ubcf5\ub418\uc5b4 \uacb0\uad6d \uc0c1\uc790 \uc548\uc5d0 \ub098 \uc790\uc2e0\uc744 \uac00\ub450\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ub354 \ub098\uc740 \uc0b6\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \uc9c0\uc18d\uc801\uc73c\ub85c \ud655\uc778\ud558\uace0, \uc0c1\uc790 \ubc16\uc73c\ub85c \ub098\uac00\ub824\ub294 \uc5f0\uc2b5\uc744 \ud574\uc57c\uaca0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub113\uc740 \uc2dc\uc120\uc744 \uac00\uc9c0\uace0, \ud56d\uc0c1 \ub0b4\uac00 \ud2c0\ub9b4 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc0dd\uac01\ud558\uace0 \uc0b4\uc544\uac00\uc790."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uc758 \uc0dd\uac01\uc740 \uc9c0\uc2dd\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc9c0\uc2dd\uc740 \uc0ac\ub791\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc0ac\ub791\uc740 \uc874\uc7ac\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc0dd\uac01\ud558\ub294 \ub098\ub294 \uc2e4\uc81c\uc758 \ub098\ubcf4\ub2e4 \uadf8\ub9cc\ud07c \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","R. D. \ub7ad",(0,t.jsx)(n.br,{}),"\n","p.19"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uac00 \uc678\uc801\uc73c\ub85c \uc5b4\ub5a4 \ud589\ub3d9\uc744 \ud558\ub4e0\uc9c0 \uac04\uc5d0, \uc0ac\ub78c\ub4e4\uc740 \uc6b0\ub9ac \ub9c8\uc74c\uc5d0\uc11c \uadf8\ub4e4\uc744 \uc5b4\ub5bb\uac8c \ub300\ud558\uace0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \uc8fc\ub85c \ubc18\uc751\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uac00 \uc0ac\ub78c\ub4e4\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \ub290\ub07c\uac8c \ub418\ub294\uc9c0\ub294 \uc6b0\ub9ac\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \ud639\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c0\uac8c \ub429\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.66"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ube44\ub09c\uc740 \uac10\uc815\uc5d0 \uc18d\ud558\uace0 \ub099\uad00\uc740 \uc758\uc9c0\uc5d0 \uc18d\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc778\uac04\uc740 \uac10\uc815\ubcf4\ub2e4 \ub354 \ud070 \uc874\uc7ac\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc54c\ub7ad, \ud0c1\ub2db\ud55c",(0,t.jsx)(n.br,{}),"\n","p.103"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uac00 \uc790\uc2e0\uc5d0\uac8c\ub9cc \uc9d1\uc911\ud558\uace0 \uc788\ub294 \ud55c, \ud63c\uc790\uc11c \uc77c\ud558\ub294 \uac83 \uc774\uc0c1\uc758 \ucc3d\uc870\uc801\uc778 \uacb0\uacfc\ub098 \ud611\ub825\uc744 \uc774\ub04c\uc5b4 \ub0b8\ub2e4\ub294 \uac83\uc740 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub298\ub0a0 \uacbd\uc81c \ud658\uacbd\uc5d0\uc11c\ub294 \ud63c\uc790\uc11c\ub294 \uc77c\uc758 \uacb0\uacfc\ub97c \ud0c1\uc6d4\ud558\uac8c \ub9cc\ub4e4\uc5b4 \ub0b4\uae30\uac00 \uc5b4\ub835\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub0b4\uac00 \uc911\uc2ec\uc774\uc5b4\uc57c \ub41c\ub2e4\ub294 \ud3d0\uc1c4\uc801\uc778 \uc0ac\uace0\ub294 \ud568\uaed8 \uc77c\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uc5f4\uc815\uc744 \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.175"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc194\uc9c1\ud568\uc740 \uc6b0\ub9ac\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\ub294 \uc5f4\uc1e0\uc785\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\uc740 \uc790\uc2e0\uc758 \ud589\ub3d9\uacfc \uad00\ub828\ub41c \uc0ac\ub78c\uc5d0 \ub300\ud574 \uae30\uaebc\uc774 \uc0ac\uacfc\ub97c \ud558\ub294 \uac83\uc785\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\ub9cc\uc774 \uc2e4\ud0c0\ub798\ucc98\ub7fc \uc5c9\ud0a8 \uad00\uacc4\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\uc8e0.",(0,t.jsx)(n.br,{}),"\n","p.188"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ub204\uad70\uac00\ub97c \ub098\uc640 \uac19\uc774 \ub3d9\uc77c\ud55c \uac00\uce58\ub97c \uc9c0\ub2cc \ud55c \uc778\uac04\uc73c\ub85c \uc0dd\uac01\ud574\uc11c \uadf8 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \ubc16\uc5d0 \uacc4\uc18d \uba38\ubb34\ub974\uace0 \uc2f6\uc740 \uc5f4\ub9dd\uc774 \uc0dd\uae38 \ub54c, \ub098\ub294 \uc774\ubbf8 \uadf8 \uc0ac\ub78c\uc5d0 \ub300\ud574 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.214"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ub300\ubd80\ubd84\uc758 \uc0ac\ub78c\ub4e4\uc774 \uad00\uacc4 \uae30\uc220\uc744 \uac00\uc9c0\uace0 \uadf8\ub4e4\uc774 \uacaa\uace0 \uc788\ub294 \ubb38\uc81c\ub97c \ubc14\ub85c\uc7a1\uc73c\ub824\uace0 \ud558\ub294 \ub178\ub825\uc774 \uacb0\uc2e4\uc744 \uc5bb\uc9c0 \ubabb\ud558\ub294 \uac83\uc740 \uacb0\ucf54 \uadf8\ub7ec\ud55c \uae30\uc220 \ubd80\uc871 \ub54c\ubb38\uc5d0 \uc0dd\uae30\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\ub4e4\uc740 \uc790\uae30\ubc30\ubc18 \ub54c\ubb38\uc5d0 \uc0dd\uaca8\ub0a9\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.224"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\ub294 \ud568\uaed8 \uc77c\ud558\uace0 \uc6b0\ub9ac\uc640 \ud568\uaed8 \uc0b4\uc544\uac00\ub294 \uc0ac\ub78c\uc774 \uc9c4\uc815\uc73c\ub85c \ub204\uad6c\uc778\uc9c0 \uc54c\uc9c0 \ubabb\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uac00 \uadf8\ub4e4\uacfc \uc9c4\uc815\uc73c\ub85c \ud568\uaed8 \uc18c\ud1b5\ud558\uae30 \uc804\uae4c\uc9c0\ub294 \uc6b0\ub9ac\ub294 \uadf8\ub4e4\uc758 \uac00\uce58\ub97c \uc798 \ubaa8\ub985\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc704\ub300\ud568\uc774\ub780 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc704\ub300\ud55c \uc810\uc744 \ubc1c\uacac\ud574 \uc8fc\ub294 \uac83\uc5d0 \uc788\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.280"]}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(b,{...e})}):b(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var c=t.createContext({}),a=function(e){var n=t.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},b={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,l=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),j=a(r),d=s,x=j["".concat(c,".").concat(d)]||j[d]||b[d]||l;return r?t.createElement(x,o(o({ref:n},p),{},{components:r})):t.createElement(x,o({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/8720c147.b6a4b7a3.js b/assets/js/8720c147.5c511468.js similarity index 98% rename from assets/js/8720c147.b6a4b7a3.js rename to assets/js/8720c147.5c511468.js index 2c226fe5a..a7c127804 100644 --- a/assets/js/8720c147.b6a4b7a3.js +++ b/assets/js/8720c147.5c511468.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[470],{75712:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>c,contentTitle:()=>d,default:()=>j,frontMatter:()=>l,metadata:()=>i,toc:()=>a});var r=n(85893),t=n(3905);const l={title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",slug:"java-class-file",tags:["Java","Class"]},d=void 0,i={permalink:"/java-class-file",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",source:"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",description:"\ud074\ub798\uc2a4 \ud30c\uc77c",date:"2023-04-03T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 3\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Class",permalink:"/tags/class"}],readingTime:5.63,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",slug:"java-class-file",tags:["Java","Class"]},unlisted:!1,prevItem:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",permalink:"/test-double"},nextItem:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",permalink:"/custom-jdbc-template"}},c={authorsImageUrls:[]},a=[{value:"\ud074\ub798\uc2a4 \ud30c\uc77c",id:"\ud074\ub798\uc2a4-\ud30c\uc77c",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd",id:"\ud074\ub798\uc2a4-\ud30c\uc77c\uc758-\ub370\uc774\ud130-\ud615\uc2dd",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\uad6c\uc870",level:3},{value:"\ub9e4\uc9c1\ub118\ubc84",id:"\ub9e4\uc9c1\ub118\ubc84",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud3ec\ub9f7-\ubc84\uc804",level:3},{value:"\uc0c1\uc218 \ud480",id:"\uc0c1\uc218-\ud480",level:3},{value:"\uc561\uc138\uc2a4 \ud50c\ub798\uadf8",id:"\uc561\uc138\uc2a4-\ud50c\ub798\uadf8",level:3},{value:"this_class",id:"this_class",level:3},{value:"super_class",id:"super_class",level:3},{value:"interface, field, method",id:"interface-field-method",level:3},{value:"attributes",id:"attributes",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud655\uc778\ud558\uba74\uc11c-\uc0ac\uc6a9\ud55c-\ud234",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function h(e){const s={a:"a",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c",children:"\ud074\ub798\uc2a4 \ud30c\uc77c"}),"\n",(0,r.jsxs)(s.p,{children:["\uc790\ubc14 \uc18c\uc2a4\ucf54\ub4dc\uac00 \uc2e4\ud589\uc774 \ub418\ub824\uba74 \uc790\ubc14 \ucef4\ud30c\uc77c\ub7ec(javac)\ub97c \ud1b5\ud574 \uc18c\uc2a4\ucf54\ub4dc\ub97c \ud074\ub798\uc2a4\ud30c\uc77c\ub85c \ubcc0\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ucef4\ud30c\uc77c\ub41c \ud074\ub798\uc2a4\ud30c\uc77c\uc740 \uc5b4\ub5a4 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744\uae4c?"]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c\uc758-\ub370\uc774\ud130-\ud615\uc2dd",children:"\ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd"}),"\n",(0,r.jsxs)(s.p,{children:["8\ube44\ud2b8 \ubc14\uc774\ud2b8\uc758 \uc2a4\ud2b8\ub9bc\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","16\ube44\ud2b8 \ubc0f 32\ube44\ud2b8\uc758 \ub370\uc774\ud130\ub294 \uac01\uac01 2\uac1c, 4\uac1c\uc758 \uc5f0\uc18d\ub41c 8\ube44\ud2b8\ub97c \uc77d\uc5b4\uc11c \uad6c\uc131\ub41c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uba40\ud2f0\ubc14\uc774\ud2b8\uc758 \uacbd\uc6b0 \ud56d\uc0c1 big endian \uc21c\uc11c\ub85c \uc800\uc7a5\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(s.p,{children:["u1 \u2192 unsigned 1byte",(0,r.jsx)(s.br,{}),"\n","u2 \u2192 unsigned 2byte",(0,r.jsx)(s.br,{}),"\n","u4 \u2192 unsigned 4byte"]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\uad6c\uc870",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{children:"ClassFile {\n u4 magic;\n u2 minor_version;\n u2 major_version;\n u2 constant_pool_count;\n cp_info constant_pool[constant_pool_count-1];\n u2 access_flags;\n u2 this_class;\n u2 super_class;\n u2 interfaces_count;\n u2 interfaces[interfaces_count];\n u2 fields_count;\n field_info fields[fields_count];\n u2 methods_count;\n method_info methods[methods_count];\n u2 attributes_count;\n attribute_info attributes[attributes_count];\n}\n"})}),"\n",(0,r.jsx)(s.h3,{id:"\ub9e4\uc9c1\ub118\ubc84",children:"\ub9e4\uc9c1\ub118\ubc84"}),"\n",(0,r.jsxs)(s.p,{children:["\ubaa8\ub4e0 \ud074\ub798\uc2a4 \ud30c\uc77c\uc740 0xCAFEBABE\ub77c\ub294 \ub9e4\uc9c1\ub118\ubc84\ub85c \uc2dc\uc791\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ubcf4\ud1b5 \ub9e4\uc9c1\ub118\ubc84\ub294 \ud30c\uc77c \uc885\ub958\ub97c \uc2dd\ubcc4\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud3ec\ub9f7-\ubc84\uc804",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804"}),"\n",(0,r.jsx)(s.p,{children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ubc84\uc804 \uac12\uc740 \ud074\ub798\uc2a4\ub85c\ub354\uc758 \ud638\ud658\uc131 \ubcf4\uc7a5\uc744 \uc704\ud574 \uaf2d \ud544\uc694\ud55c \uac12\uc774\ub2e4."}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Java 17 \ubc84\uc804\uc73c\ub85c \ube4c\ub4dc\ud55c\ub2e4\uba74 class version 61 ex) 00 00 00 3D"}),"\n"]}),"\n",(0,r.jsxs)(s.p,{children:["\ud638\ud658\ub418\uc9c0 \uc54a\ub294 \ubc84\uc804\uc758 \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \ub85c\ub529\ud558\ub824\uace0 \ud558\ub294 \uacbd\uc6b0 \ub7f0\ud0c0\uc784\uc5d0 ",(0,r.jsx)(s.code,{children:"UnsupportedClassVersionError"})," \uc608\uc678\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"class\xa0file format major versions"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Java SE"}),(0,r.jsx)(s.th,{children:"Released"}),(0,r.jsx)(s.th,{children:"Major"}),(0,r.jsx)(s.th,{children:"Supported majors"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"8"}),(0,r.jsx)(s.td,{children:"March 2014"}),(0,r.jsx)(s.td,{children:"52"}),(0,r.jsx)(s.td,{children:"45 .. 52"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"9"}),(0,r.jsx)(s.td,{children:"September 2017"}),(0,r.jsx)(s.td,{children:"53"}),(0,r.jsx)(s.td,{children:"45 .. 53"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"10"}),(0,r.jsx)(s.td,{children:"March 2018"}),(0,r.jsx)(s.td,{children:"54"}),(0,r.jsx)(s.td,{children:"45 .. 54"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"11"}),(0,r.jsx)(s.td,{children:"September 2018"}),(0,r.jsx)(s.td,{children:"55"}),(0,r.jsx)(s.td,{children:"45 .. 55"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"12"}),(0,r.jsx)(s.td,{children:"March 2019"}),(0,r.jsx)(s.td,{children:"56"}),(0,r.jsx)(s.td,{children:"45 .. 56"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"13"}),(0,r.jsx)(s.td,{children:"September 2019"}),(0,r.jsx)(s.td,{children:"57"}),(0,r.jsx)(s.td,{children:"45 .. 57"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"14"}),(0,r.jsx)(s.td,{children:"March 2020"}),(0,r.jsx)(s.td,{children:"58"}),(0,r.jsx)(s.td,{children:"45 .. 58"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"15"}),(0,r.jsx)(s.td,{children:"September 2020"}),(0,r.jsx)(s.td,{children:"59"}),(0,r.jsx)(s.td,{children:"45 .. 59"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"16"}),(0,r.jsx)(s.td,{children:"March 2021"}),(0,r.jsx)(s.td,{children:"60"}),(0,r.jsx)(s.td,{children:"45 .. 60"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"17"}),(0,r.jsx)(s.td,{children:"September 2021"}),(0,r.jsx)(s.td,{children:"61"}),(0,r.jsx)(s.td,{children:"45 .. 61"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"\uc0c1\uc218-\ud480",children:"\uc0c1\uc218 \ud480"}),"\n",(0,r.jsxs)(s.p,{children:["2\ubc14\uc774\ud2b8\uc758 \uc0c1\uc218\uc758 \uac1c\uc218\uac12\uc774 \uba3c\uc800\uc624\uace0 \uadf8 \ub4a4\ub85c \ucf54\ub4dc\uc5d0 \ub4f1\uc7a5\ud558\ub294 \uc0c1\uc218\uac12\uc774 \ubaa8\uc5ec\uc788\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ud074\ub798\uc2a4\uba85, \uc0c1\uc218\uba85, \uc0c1\uc218 \uac12, \ud544\ub4dc\uba85, \uba54\uc11c\ub4dc\uba85\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","JVM\uc740 \ucf54\ub4dc \uc2e4\ud589 \uc2dc \ub7f0\ud0c0\uc784\uc5d0 \ubc30\uce58\ub41c \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c, \ud574\ub2f9 \uc0c1\uc218 \ud480 \ud14c\uc774\ube14\uc744 \ucc3e\uc544\ubcf4\uace0 \ud544\uc694\ud55c \uac12\uc744 \ucc38\uc870\ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\uc561\uc138\uc2a4-\ud50c\ub798\uadf8",children:"\uc561\uc138\uc2a4 \ud50c\ub798\uadf8"}),"\n",(0,r.jsxs)(s.p,{children:["\ud074\ub798\uc2a4, \uc778\ud130\ud398\uc774\uc2a4\uc640 \uac19\uc740 \ud30c\uc77c\uc758 \uc18d\uc131\uc744 \ud45c\uc2dc\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 public interface\ub85c \uc815\uc758\ub41c \uc778\ud130\ud398\uc774\uc2a4\uc758 \ud50c\ub798\uadf8\ub294 0x0601\uc774\ub2e4."]}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["\uacc4\uc0b0\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. ",(0,r.jsx)(s.code,{children:"ACC_PUBLIC"})," xor ",(0,r.jsx)(s.code,{children:"ACC_INTERFACE"})," xor ",(0,r.jsx)(s.code,{children:"ACC_ABSTRACT"})]}),"\n"]}),"\n",(0,r.jsx)(s.p,{children:"\uacf5\uc2dd\ubb38\uc11c\uc5d0 \ub4e4\uc5b4\uac00\uba74 \uac01 \ud50c\ub798\uadf8\uc5d0 \ub300\ud55c \uc124\uba85 + \ud50c\ub798\uadf8 \uc124\uc815\uc2dc \ub3d9\uc2dc\uc5d0 \uc124\uc815\ub418\uba74 \uc548\ub418\ub294 \ud50c\ub798\uadf8\uc640 \uac19\uc740 \uc124\uba85\uc774 \uc790\uc138\ud558\uac8c \ub098\uc640\uc788\ub2e4."}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Class access and property modifiers"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Flag Name"}),(0,r.jsx)(s.th,{children:"Value"}),(0,r.jsx)(s.th,{children:"Interpretation"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_PUBLIC"}),(0,r.jsx)(s.td,{children:"0x0001"}),(0,r.jsx)(s.td,{children:"Declared\xa0public; may be accessed from outside its package."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_FINAL"}),(0,r.jsx)(s.td,{children:"0x0010"}),(0,r.jsx)(s.td,{children:"Declared\xa0final; no subclasses allowed."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_SUPER"}),(0,r.jsx)(s.td,{children:"0x0020"}),(0,r.jsx)(s.td,{children:"Treat superclass methods specially when invoked by the\xa0invokespecial\xa0instruction."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_INTERFACE"}),(0,r.jsx)(s.td,{children:"0x0200"}),(0,r.jsx)(s.td,{children:"Is an interface, not a class."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ABSTRACT"}),(0,r.jsx)(s.td,{children:"0x0400"}),(0,r.jsx)(s.td,{children:"Declared\xa0abstract; must not be instantiated."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_SYNTHETIC"}),(0,r.jsx)(s.td,{children:"0x1000"}),(0,r.jsx)(s.td,{children:"Declared synthetic; not present in the source code."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ANNOTATION"}),(0,r.jsx)(s.td,{children:"0x2000"}),(0,r.jsx)(s.td,{children:"Declared as an annotation type."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ENUM"}),(0,r.jsx)(s.td,{children:"0x4000"}),(0,r.jsx)(s.td,{children:"Declared as an\xa0enum\xa0type."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_MODULE"}),(0,r.jsx)(s.td,{children:"0x8000"}),(0,r.jsx)(s.td,{children:"Is a module, not a class or interface."})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"this_class",children:"this_class"}),"\n",(0,r.jsxs)(s.p,{children:["\ud074\ub798\uc2a4\uba85\uacfc \uac19\uc740 \uc774\ub984\uc744 \ud45c\ud604\ud558\ub294 \uac12\uc73c\ub85c, \uc0c1\uc218 \ud480\uc5d0\uc11c \ud074\ub798\uc2a4\uba85\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ud574\ub2f9 \uc778\ub371\uc2a4\uc758 \ud56d\ubaa9\uc740 ",(0,r.jsx)(s.code,{children:"CONSTANT_Class_infoclass"})," \ud615\uc2dd\uc758 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"super_class",children:"super_class"}),"\n",(0,r.jsxs)(s.p,{children:["\uc0c1\uc218 \ud480\uc5d0\uc11c \uc288\ud37c \ud074\ub798\uc2a4\uc758 \uc774\ub984\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uc544\ubb34\uac83\ub3c4 \uc0c1\uc18d\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\uc758 \uacbd\uc6b0 ",(0,r.jsx)(s.code,{children:"java.lang.Object"}),"\uc758 \uc778\ub371\uc2a4 \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"interface-field-method",children:"interface, field, method"}),"\n",(0,r.jsxs)(s.p,{children:["\uac01\uac01\uc758 \uac1c\uc218\uc640, \uc815\ubcf4\uc5d0 \ub300\ud55c \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4.",(0,r.jsx)(s.br,{}),"\n","interface, field, method\ub97c \ud45c\uc2dc\ud558\ub294 \ubc29\ubc95\uc774 \uac01\uac01 \ub2e4\ub974\uace0, \uc811\uadfc\uc790\uc5d0 \ub300\ud55c \ud50c\ub798\uadf8\ub3c4 \uac01\uac01 \ub2e4\ub974\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"attributes",children:"attributes"}),"\n",(0,r.jsxs)(s.p,{children:["\ud574\ub2f9 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucd94\uac00 \uc815\ubcf4\uc758 \ubaa8\uc74c\uc774\ub2e4. \uc608) \uc18c\uc2a4\ud30c\uc77c\uba85",(0,r.jsx)(s.br,{}),"\n","\uc815\ud574\uc9c4 \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \uad6c\uc870\ub97c \ud655\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud655\uc778\ud558\uba74\uc11c-\uc0ac\uc6a9\ud55c-\ud234",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234"}),"\n",(0,r.jsxs)(s.p,{children:["IntelliJ plugin - BinEd",(0,r.jsx)(s.br,{}),"\n","IntelliJ plugin - jclasslib Bytecode Viewer"]}),"\n",(0,r.jsx)(s.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(s.p,{children:["2\uc7a5 JVM \uc774\uc57c\uae30, \uc790\ubc14 \ucd5c\uc801\ud654",(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.fileformat.com/ko/programming/class/",children:"Class file in Java, File Format"}),(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html",children:"java se11 Class \ud30c\uc77c \ud615\uc2dd, Oracle"}),(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html",children:"java se17 Class \ud30c\uc77c \ud615\uc2dd, Oracle"})]})]})}function j(e={}){const{wrapper:s}={...(0,t.ah)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,s,n)=>{n.d(s,{ah:()=>a});var r=n(67294);function t(e,s,n){return s in e?Object.defineProperty(e,s,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[s]=n,e}function l(e,s){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);s&&(r=r.filter((function(s){return Object.getOwnPropertyDescriptor(e,s).enumerable}))),n.push.apply(n,r)}return n}function d(e){for(var s=1;s=0||(t[n]=e[n]);return t}(e,s);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(t[n]=e[n])}return t}var c=r.createContext({}),a=function(e){var s=r.useContext(c),n=s;return e&&(n="function"==typeof e?e(s):d(d({},s),e)),n},h={inlineCode:"code",wrapper:function(e){var s=e.children;return r.createElement(r.Fragment,{},s)}},j=r.forwardRef((function(e,s){var n=e.components,t=e.mdxType,l=e.originalType,c=e.parentName,j=i(e,["components","mdxType","originalType","parentName"]),x=a(n),o=t,u=x["".concat(c,".").concat(o)]||x[o]||h[o]||l;return n?r.createElement(u,d(d({ref:s},j),{},{components:n})):r.createElement(u,d({ref:s},j))}));j.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[470],{75712:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>c,contentTitle:()=>d,default:()=>j,frontMatter:()=>l,metadata:()=>i,toc:()=>a});var r=n(85893),t=n(3905);const l={title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",slug:"java-class-file",tags:["Java","Class"]},d=void 0,i={permalink:"/java-class-file",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",source:"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",description:"\ud074\ub798\uc2a4 \ud30c\uc77c",date:"2023-04-03T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 3\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Class",permalink:"/tags/class"}],readingTime:5.63,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",slug:"java-class-file",tags:["Java","Class"]},unlisted:!1,prevItem:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",permalink:"/custom-jdbc-template"},nextItem:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",permalink:"/test-double"}},c={authorsImageUrls:[]},a=[{value:"\ud074\ub798\uc2a4 \ud30c\uc77c",id:"\ud074\ub798\uc2a4-\ud30c\uc77c",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd",id:"\ud074\ub798\uc2a4-\ud30c\uc77c\uc758-\ub370\uc774\ud130-\ud615\uc2dd",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\uad6c\uc870",level:3},{value:"\ub9e4\uc9c1\ub118\ubc84",id:"\ub9e4\uc9c1\ub118\ubc84",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud3ec\ub9f7-\ubc84\uc804",level:3},{value:"\uc0c1\uc218 \ud480",id:"\uc0c1\uc218-\ud480",level:3},{value:"\uc561\uc138\uc2a4 \ud50c\ub798\uadf8",id:"\uc561\uc138\uc2a4-\ud50c\ub798\uadf8",level:3},{value:"this_class",id:"this_class",level:3},{value:"super_class",id:"super_class",level:3},{value:"interface, field, method",id:"interface-field-method",level:3},{value:"attributes",id:"attributes",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud655\uc778\ud558\uba74\uc11c-\uc0ac\uc6a9\ud55c-\ud234",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function h(e){const s={a:"a",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c",children:"\ud074\ub798\uc2a4 \ud30c\uc77c"}),"\n",(0,r.jsxs)(s.p,{children:["\uc790\ubc14 \uc18c\uc2a4\ucf54\ub4dc\uac00 \uc2e4\ud589\uc774 \ub418\ub824\uba74 \uc790\ubc14 \ucef4\ud30c\uc77c\ub7ec(javac)\ub97c \ud1b5\ud574 \uc18c\uc2a4\ucf54\ub4dc\ub97c \ud074\ub798\uc2a4\ud30c\uc77c\ub85c \ubcc0\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ucef4\ud30c\uc77c\ub41c \ud074\ub798\uc2a4\ud30c\uc77c\uc740 \uc5b4\ub5a4 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744\uae4c?"]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c\uc758-\ub370\uc774\ud130-\ud615\uc2dd",children:"\ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd"}),"\n",(0,r.jsxs)(s.p,{children:["8\ube44\ud2b8 \ubc14\uc774\ud2b8\uc758 \uc2a4\ud2b8\ub9bc\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","16\ube44\ud2b8 \ubc0f 32\ube44\ud2b8\uc758 \ub370\uc774\ud130\ub294 \uac01\uac01 2\uac1c, 4\uac1c\uc758 \uc5f0\uc18d\ub41c 8\ube44\ud2b8\ub97c \uc77d\uc5b4\uc11c \uad6c\uc131\ub41c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uba40\ud2f0\ubc14\uc774\ud2b8\uc758 \uacbd\uc6b0 \ud56d\uc0c1 big endian \uc21c\uc11c\ub85c \uc800\uc7a5\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(s.p,{children:["u1 \u2192 unsigned 1byte",(0,r.jsx)(s.br,{}),"\n","u2 \u2192 unsigned 2byte",(0,r.jsx)(s.br,{}),"\n","u4 \u2192 unsigned 4byte"]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\uad6c\uc870",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{children:"ClassFile {\n u4 magic;\n u2 minor_version;\n u2 major_version;\n u2 constant_pool_count;\n cp_info constant_pool[constant_pool_count-1];\n u2 access_flags;\n u2 this_class;\n u2 super_class;\n u2 interfaces_count;\n u2 interfaces[interfaces_count];\n u2 fields_count;\n field_info fields[fields_count];\n u2 methods_count;\n method_info methods[methods_count];\n u2 attributes_count;\n attribute_info attributes[attributes_count];\n}\n"})}),"\n",(0,r.jsx)(s.h3,{id:"\ub9e4\uc9c1\ub118\ubc84",children:"\ub9e4\uc9c1\ub118\ubc84"}),"\n",(0,r.jsxs)(s.p,{children:["\ubaa8\ub4e0 \ud074\ub798\uc2a4 \ud30c\uc77c\uc740 0xCAFEBABE\ub77c\ub294 \ub9e4\uc9c1\ub118\ubc84\ub85c \uc2dc\uc791\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ubcf4\ud1b5 \ub9e4\uc9c1\ub118\ubc84\ub294 \ud30c\uc77c \uc885\ub958\ub97c \uc2dd\ubcc4\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud3ec\ub9f7-\ubc84\uc804",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804"}),"\n",(0,r.jsx)(s.p,{children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ubc84\uc804 \uac12\uc740 \ud074\ub798\uc2a4\ub85c\ub354\uc758 \ud638\ud658\uc131 \ubcf4\uc7a5\uc744 \uc704\ud574 \uaf2d \ud544\uc694\ud55c \uac12\uc774\ub2e4."}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Java 17 \ubc84\uc804\uc73c\ub85c \ube4c\ub4dc\ud55c\ub2e4\uba74 class version 61 ex) 00 00 00 3D"}),"\n"]}),"\n",(0,r.jsxs)(s.p,{children:["\ud638\ud658\ub418\uc9c0 \uc54a\ub294 \ubc84\uc804\uc758 \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \ub85c\ub529\ud558\ub824\uace0 \ud558\ub294 \uacbd\uc6b0 \ub7f0\ud0c0\uc784\uc5d0 ",(0,r.jsx)(s.code,{children:"UnsupportedClassVersionError"})," \uc608\uc678\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"class\xa0file format major versions"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Java SE"}),(0,r.jsx)(s.th,{children:"Released"}),(0,r.jsx)(s.th,{children:"Major"}),(0,r.jsx)(s.th,{children:"Supported majors"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"8"}),(0,r.jsx)(s.td,{children:"March 2014"}),(0,r.jsx)(s.td,{children:"52"}),(0,r.jsx)(s.td,{children:"45 .. 52"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"9"}),(0,r.jsx)(s.td,{children:"September 2017"}),(0,r.jsx)(s.td,{children:"53"}),(0,r.jsx)(s.td,{children:"45 .. 53"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"10"}),(0,r.jsx)(s.td,{children:"March 2018"}),(0,r.jsx)(s.td,{children:"54"}),(0,r.jsx)(s.td,{children:"45 .. 54"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"11"}),(0,r.jsx)(s.td,{children:"September 2018"}),(0,r.jsx)(s.td,{children:"55"}),(0,r.jsx)(s.td,{children:"45 .. 55"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"12"}),(0,r.jsx)(s.td,{children:"March 2019"}),(0,r.jsx)(s.td,{children:"56"}),(0,r.jsx)(s.td,{children:"45 .. 56"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"13"}),(0,r.jsx)(s.td,{children:"September 2019"}),(0,r.jsx)(s.td,{children:"57"}),(0,r.jsx)(s.td,{children:"45 .. 57"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"14"}),(0,r.jsx)(s.td,{children:"March 2020"}),(0,r.jsx)(s.td,{children:"58"}),(0,r.jsx)(s.td,{children:"45 .. 58"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"15"}),(0,r.jsx)(s.td,{children:"September 2020"}),(0,r.jsx)(s.td,{children:"59"}),(0,r.jsx)(s.td,{children:"45 .. 59"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"16"}),(0,r.jsx)(s.td,{children:"March 2021"}),(0,r.jsx)(s.td,{children:"60"}),(0,r.jsx)(s.td,{children:"45 .. 60"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"17"}),(0,r.jsx)(s.td,{children:"September 2021"}),(0,r.jsx)(s.td,{children:"61"}),(0,r.jsx)(s.td,{children:"45 .. 61"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"\uc0c1\uc218-\ud480",children:"\uc0c1\uc218 \ud480"}),"\n",(0,r.jsxs)(s.p,{children:["2\ubc14\uc774\ud2b8\uc758 \uc0c1\uc218\uc758 \uac1c\uc218\uac12\uc774 \uba3c\uc800\uc624\uace0 \uadf8 \ub4a4\ub85c \ucf54\ub4dc\uc5d0 \ub4f1\uc7a5\ud558\ub294 \uc0c1\uc218\uac12\uc774 \ubaa8\uc5ec\uc788\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ud074\ub798\uc2a4\uba85, \uc0c1\uc218\uba85, \uc0c1\uc218 \uac12, \ud544\ub4dc\uba85, \uba54\uc11c\ub4dc\uba85\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","JVM\uc740 \ucf54\ub4dc \uc2e4\ud589 \uc2dc \ub7f0\ud0c0\uc784\uc5d0 \ubc30\uce58\ub41c \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c, \ud574\ub2f9 \uc0c1\uc218 \ud480 \ud14c\uc774\ube14\uc744 \ucc3e\uc544\ubcf4\uace0 \ud544\uc694\ud55c \uac12\uc744 \ucc38\uc870\ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\uc561\uc138\uc2a4-\ud50c\ub798\uadf8",children:"\uc561\uc138\uc2a4 \ud50c\ub798\uadf8"}),"\n",(0,r.jsxs)(s.p,{children:["\ud074\ub798\uc2a4, \uc778\ud130\ud398\uc774\uc2a4\uc640 \uac19\uc740 \ud30c\uc77c\uc758 \uc18d\uc131\uc744 \ud45c\uc2dc\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 public interface\ub85c \uc815\uc758\ub41c \uc778\ud130\ud398\uc774\uc2a4\uc758 \ud50c\ub798\uadf8\ub294 0x0601\uc774\ub2e4."]}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["\uacc4\uc0b0\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. ",(0,r.jsx)(s.code,{children:"ACC_PUBLIC"})," xor ",(0,r.jsx)(s.code,{children:"ACC_INTERFACE"})," xor ",(0,r.jsx)(s.code,{children:"ACC_ABSTRACT"})]}),"\n"]}),"\n",(0,r.jsx)(s.p,{children:"\uacf5\uc2dd\ubb38\uc11c\uc5d0 \ub4e4\uc5b4\uac00\uba74 \uac01 \ud50c\ub798\uadf8\uc5d0 \ub300\ud55c \uc124\uba85 + \ud50c\ub798\uadf8 \uc124\uc815\uc2dc \ub3d9\uc2dc\uc5d0 \uc124\uc815\ub418\uba74 \uc548\ub418\ub294 \ud50c\ub798\uadf8\uc640 \uac19\uc740 \uc124\uba85\uc774 \uc790\uc138\ud558\uac8c \ub098\uc640\uc788\ub2e4."}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Class access and property modifiers"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Flag Name"}),(0,r.jsx)(s.th,{children:"Value"}),(0,r.jsx)(s.th,{children:"Interpretation"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_PUBLIC"}),(0,r.jsx)(s.td,{children:"0x0001"}),(0,r.jsx)(s.td,{children:"Declared\xa0public; may be accessed from outside its package."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_FINAL"}),(0,r.jsx)(s.td,{children:"0x0010"}),(0,r.jsx)(s.td,{children:"Declared\xa0final; no subclasses allowed."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_SUPER"}),(0,r.jsx)(s.td,{children:"0x0020"}),(0,r.jsx)(s.td,{children:"Treat superclass methods specially when invoked by the\xa0invokespecial\xa0instruction."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_INTERFACE"}),(0,r.jsx)(s.td,{children:"0x0200"}),(0,r.jsx)(s.td,{children:"Is an interface, not a class."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ABSTRACT"}),(0,r.jsx)(s.td,{children:"0x0400"}),(0,r.jsx)(s.td,{children:"Declared\xa0abstract; must not be instantiated."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_SYNTHETIC"}),(0,r.jsx)(s.td,{children:"0x1000"}),(0,r.jsx)(s.td,{children:"Declared synthetic; not present in the source code."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ANNOTATION"}),(0,r.jsx)(s.td,{children:"0x2000"}),(0,r.jsx)(s.td,{children:"Declared as an annotation type."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ENUM"}),(0,r.jsx)(s.td,{children:"0x4000"}),(0,r.jsx)(s.td,{children:"Declared as an\xa0enum\xa0type."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_MODULE"}),(0,r.jsx)(s.td,{children:"0x8000"}),(0,r.jsx)(s.td,{children:"Is a module, not a class or interface."})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"this_class",children:"this_class"}),"\n",(0,r.jsxs)(s.p,{children:["\ud074\ub798\uc2a4\uba85\uacfc \uac19\uc740 \uc774\ub984\uc744 \ud45c\ud604\ud558\ub294 \uac12\uc73c\ub85c, \uc0c1\uc218 \ud480\uc5d0\uc11c \ud074\ub798\uc2a4\uba85\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ud574\ub2f9 \uc778\ub371\uc2a4\uc758 \ud56d\ubaa9\uc740 ",(0,r.jsx)(s.code,{children:"CONSTANT_Class_infoclass"})," \ud615\uc2dd\uc758 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"super_class",children:"super_class"}),"\n",(0,r.jsxs)(s.p,{children:["\uc0c1\uc218 \ud480\uc5d0\uc11c \uc288\ud37c \ud074\ub798\uc2a4\uc758 \uc774\ub984\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uc544\ubb34\uac83\ub3c4 \uc0c1\uc18d\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\uc758 \uacbd\uc6b0 ",(0,r.jsx)(s.code,{children:"java.lang.Object"}),"\uc758 \uc778\ub371\uc2a4 \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"interface-field-method",children:"interface, field, method"}),"\n",(0,r.jsxs)(s.p,{children:["\uac01\uac01\uc758 \uac1c\uc218\uc640, \uc815\ubcf4\uc5d0 \ub300\ud55c \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4.",(0,r.jsx)(s.br,{}),"\n","interface, field, method\ub97c \ud45c\uc2dc\ud558\ub294 \ubc29\ubc95\uc774 \uac01\uac01 \ub2e4\ub974\uace0, \uc811\uadfc\uc790\uc5d0 \ub300\ud55c \ud50c\ub798\uadf8\ub3c4 \uac01\uac01 \ub2e4\ub974\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"attributes",children:"attributes"}),"\n",(0,r.jsxs)(s.p,{children:["\ud574\ub2f9 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucd94\uac00 \uc815\ubcf4\uc758 \ubaa8\uc74c\uc774\ub2e4. \uc608) \uc18c\uc2a4\ud30c\uc77c\uba85",(0,r.jsx)(s.br,{}),"\n","\uc815\ud574\uc9c4 \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \uad6c\uc870\ub97c \ud655\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud655\uc778\ud558\uba74\uc11c-\uc0ac\uc6a9\ud55c-\ud234",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234"}),"\n",(0,r.jsxs)(s.p,{children:["IntelliJ plugin - BinEd",(0,r.jsx)(s.br,{}),"\n","IntelliJ plugin - jclasslib Bytecode Viewer"]}),"\n",(0,r.jsx)(s.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(s.p,{children:["2\uc7a5 JVM \uc774\uc57c\uae30, \uc790\ubc14 \ucd5c\uc801\ud654",(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.fileformat.com/ko/programming/class/",children:"Class file in Java, File Format"}),(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html",children:"java se11 Class \ud30c\uc77c \ud615\uc2dd, Oracle"}),(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html",children:"java se17 Class \ud30c\uc77c \ud615\uc2dd, Oracle"})]})]})}function j(e={}){const{wrapper:s}={...(0,t.ah)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,s,n)=>{n.d(s,{ah:()=>a});var r=n(67294);function t(e,s,n){return s in e?Object.defineProperty(e,s,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[s]=n,e}function l(e,s){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);s&&(r=r.filter((function(s){return Object.getOwnPropertyDescriptor(e,s).enumerable}))),n.push.apply(n,r)}return n}function d(e){for(var s=1;s=0||(t[n]=e[n]);return t}(e,s);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(t[n]=e[n])}return t}var c=r.createContext({}),a=function(e){var s=r.useContext(c),n=s;return e&&(n="function"==typeof e?e(s):d(d({},s),e)),n},h={inlineCode:"code",wrapper:function(e){var s=e.children;return r.createElement(r.Fragment,{},s)}},j=r.forwardRef((function(e,s){var n=e.components,t=e.mdxType,l=e.originalType,c=e.parentName,j=i(e,["components","mdxType","originalType","parentName"]),x=a(n),o=t,u=x["".concat(c,".").concat(o)]||x[o]||h[o]||l;return n?r.createElement(u,d(d({ref:s},j),{},{components:n})):r.createElement(u,d({ref:s},j))}));j.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/8a24850b.b479905c.js b/assets/js/8a24850b.059ab89a.js similarity index 98% rename from assets/js/8a24850b.b479905c.js rename to assets/js/8a24850b.059ab89a.js index 3748d5a8f..58b8559f7 100644 --- a/assets/js/8a24850b.b479905c.js +++ b/assets/js/8a24850b.059ab89a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[741],{86331:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>j,frontMatter:()=>c,metadata:()=>l,toc:()=>a});var s=r(85893),t=r(3905);const c={title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",slug:"chess-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,l={permalink:"/chess-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",description:"1, 2\ub2e8\uacc4//github.com/woowacourse/java-chess/pull/441",date:"2023-03-31T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 31\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.705,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",slug:"chess-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",permalink:"/woowacourse-level1-retrospective"},nextItem:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",permalink:"/grasp"}},o={authorsImageUrls:[]},a=[{value:"\uccb4\uc2a4",id:"\uccb4\uc2a4",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function h(e){const n={a:"a",admonition:"admonition",br:"br",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.ah)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,s.jsxs)(n.p,{children:["1, 2\ub2e8\uacc4: ",(0,s.jsx)(n.a,{href:"https://github.com/woowacourse/java-chess/pull/441",children:"https://github.com/woowacourse/java-chess/pull/441"}),(0,s.jsx)(n.br,{}),"\n","3, 4\ub2e8\uacc4: ",(0,s.jsx)(n.a,{href:"https://github.com/woowacourse/java-chess/pull/529",children:"https://github.com/woowacourse/java-chess/pull/529"})]})}),"\n",(0,s.jsx)(n.h3,{id:"\uccb4\uc2a4",children:"\uccb4\uc2a4"}),"\n",(0,s.jsxs)(n.p,{children:["\uccb4\uc2a4 \ubbf8\uc158\uc5d0\ub294 \uac00\ube44\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4!",(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4\ub294 \uc774\uc804 \ubbf8\uc158\ub4e4\ubcf4\ub2e4 \ud6e8\uc52c \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778\uc774\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \uac00\ube44\uc640 \ub098\ub294 \uccb4\uc2a4 \ub3c4\uba54\uc778\uc774 \uc775\uc219\ud574\uc11c \ub354 \ud3b8\ud55c \ub9c8\uc74c\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc5b4\ub824\uc6e0\ub358 \ubd80\ubd84\uc740 \uae30\ubb3c\uc758 \uc774\ub3d9, \uc774\ub3d9\uc2dc \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:["\uac00\ube44\uac00 \uc9d1\uc5d0\uac00\uc11c\ub3c4 \uae30\ubb3c\uc758 \uc774\ub3d9 \uad00\ub828\ud574 \uc0dd\uac01 \uc815\ub9ac\ud55c \uae00\uc744 \ubcf4\ub0b4\uc918\uc11c \ub354\uc6b1 \ube68\ub9ac \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ucd5c\uc885\uc801\uc73c\ub85c \uacb0\uc815\ud55c \ubd80\ubd84\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5\uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","Rank\uc640 File\uc740 \uac01\uac01 \uc704\uce58\uac12\uc744 \uac00\uc9c0\uace0 \uc788\uace0, \uac12\uc758 \ucc28\uc774\ub97c \uc774\uc6a9\ud574\uc11c \uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uacc4\uc0b0\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc9c1\uc120 \u2192 Rank\uc640 File \ucc28\uc774 \uc911 \ud558\ub098\uac00 0\uc774\uc5b4\uc57c \ud55c\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub300\uac01\uc120 \u2192 Rank\uc640 File \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \uac19\uc544\uc57c \ud55c\ub2e4. ex) abs(-2) == abs(2)",(0,s.jsx)(n.br,{}),"\n","\ub098\uc774\ud2b8 \u2192 \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \ud558\ub098\ub294 2 \ub098\uba38\uc9c0 \ud558\ub098\ub294 1\uc774\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ub3c4\ucc29 \uce78\uc758 \uae30\ubb3c \uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","\uc544\uad70 \u2192 \uc774\ub3d9\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc801\uad70 \u2192 \uc774\ub3d9\uc774 \uac00\ub2a5\ud558\ub2e4. \uc801\uad70\uc744 \uc7a1\ub294\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc911\uac04\uc5d0 \uae30\ubb3c \uc874\uc7ac \uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","\uc774\ub3d9 \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\uba74 \uc548\ub41c\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9"}),(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4 \ubbf8\uc158\uc740 \ud2b9\ubcc4\ud558\uac8c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc5f0\uacb0\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4 \uac8c\uc784\uc758 \uc0c1\ud0dc\ub97c \ub2e4\uc74c\uc758 \ub450\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uc815\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95"}),"\n",(0,s.jsx)(n.li,{children:"\uae30\ubcf4\ub97c \uc800\uc7a5\ud558\uace0 \uac8c\uc784\uc744 \ubd88\ub7ec\uc640 \uae30\ubcf4\ub300\ub85c \uc774\ub3d9\uc2dc\ud0a4\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\uae30\ubb3c\uc774 \uc774\ub3d9\ud560 \ub54c\ub9c8\ub2e4 \uac12\uc744 \uc800\uc7a5\ud558\uace0 \uc2f6\uc5c8\uace0, \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc774\uc720\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\ud134\uacfc \uac19\uc740 \ubd80\uac00\uc801\uc778 \uc694\uc18c\ub97c \uc800\uc7a5\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,s.jsx)(n.li,{children:"\uc774\ub3d9\uc744 \ud560 \ub54c \uae30\ubb3c\uc774 \uc7a1\ud788\ub294 \uacbd\uc6b0 update \ucffc\ub9ac(\uc774\ub3d9 \uae30\ubb3c)\uc640 delete(\uc7a1\ud78c \uae30\ubb3c) 2\uac1c\uc758 \ucffc\ub9ac\ub97c \ub0a0\ub824\uc57c \ud55c\ub2e4."}),"\n",(0,s.jsx)(n.li,{children:"\ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ub3c4\uba54\uc778\uc758 \ubcc0\uacbd\uc774 \ud06c\uac8c(\ucd08\uae30 \uc0c1\ud0dc\ub97c \uad6c\uc131\ud558\ub294 \ubd80\ubd84) \uc77c\uc5b4\ub098\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\uc815\ub9ac\ud558\uc790\uba74 \uae30\ubb3c \uc804\uccb4 \uc800\uc7a5\uacfc \uae30\ubcf4 \uc800\uc7a5\uc740 \ub2e4\uc74c\uacfc \ucc28\uc774\uac00 \uc788\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ubcf4\ub4dc\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc\uc5d0\uc11c 32\uac1c\uc758 Insert \ucffc\ub9ac(\uae30\ubb3c\uc758 \uc704\uce58) + \uae30\ubb3c \uc774\ub3d9 \uc2dc \uc6c0\uc9c1\uc784 \ubcc0\uacbd(\uc7a1\ud788\ub294 \uacbd\uc6b0 2\uac1c\uc758 \ucffc\ub9ac)",(0,s.jsx)(n.br,{}),"\n","\uae30\ubcf4\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uad6c\uc131 + \uc800\uc7a5\ub41c \uae30\ubcf4\ub97c select \ucffc\ub9ac\ub85c \uc870\ud68c\ud574\uc11c \uc0ac\uc6a9(1\ud68c) + insert \ucffc\ub9ac(\uc774\ub3d9 \ub2f9 1\ud68c)"]}),"\n",(0,s.jsx)(n.p,{children:"\ucd94\uac00\ub85c \uae30\ubcf4\uc800\uc7a5\uc774 \uad6c\ud604\ub3c4 \ub354\uc6b1 \uac04\ub2e8\ud558\ub2e4. \ud83d\udc4d"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"\ubd80\uac00\uc801\uc778 \ubd80\ubd84"})}),"\n",(0,s.jsx)(n.p,{children:"\ub9ac\ubdf0\uc5b4\uc778 \ucc30\ub9ac\ud83c\udf6b\uac00 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uac8c\uc784\uc774 \uc9c4\ud589\ub41c\ub2e4\uba74 \uc5b4\ub5a8\uc9c0? \uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ub2e4\uc591\ud55c \uc2dc\ub3c4\ub97c \ud574\ubd24\ub2e4."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\ub204\ub204\uc758 \ub3c4\uc6c0\uc73c\ub85c ConnectionPool \uad6c\ud604"}),"\n",(0,s.jsx)(n.li,{children:"ThreadLocal \uc0ac\uc6a9\ud574\uc11c \uc4f0\ub808\ub4dc \ubcc4 \uc138\uc158 \uad00\ub9ac"}),"\n",(0,s.jsx)(n.li,{children:"\uc2e4\uc81c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub0b4\uc5d0\uc11c \uccb4\uc2a4 \uac8c\uc784\uc774 \uc9c4\ud589\ub418\ub294 Board\ub97c ConcurrentHashMap\uc73c\ub85c \uc800\uc7a5(\uc0ac\uc2e4 \uc774 \ubd80\ubd84\uc740 \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ud544\uc694\uc5c6\uc9c0\ub9cc 2\uba85\uc774 \uc11c\ub85c \uac8c\uc784\ud558\ub294 \uacbd\uc6b0\ub97c \uc0dd\uac01\ud574\uc11c \ub123\uc5b4\ubcf4\uc558\ub2e4.)"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"\ub450 \uba85\uc774 \uc11c\ub85c \uac19\uc740 \ubc29\uc5d0 \uc785\uc7a5\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4\uba74 \ucd9c\ub825\ud558\ub294 \ubd80\ubd84\uc774 \uae4c\ub2e4\ub85c\uc6cc\uc9c8 \uac83 \uac19\ub2e4\uace0 \uc608\uc0c1\ub418\uc5b4(Board\uc5d0 \uc635\uc800\ubc84 \ud328\ud134\uc744 \uc0ac\uc6a9\ud574\uc57c\ub418\ub098?) \ud574\ubcfc \uc5c4\ub450\uac00 \ub098\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,s.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc9c0 \ubabb\ud55c \ubd80\ubd84"}),(0,s.jsx)(n.br,{}),"\n","DB \uad00\ub828 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0\ub9cc \uc9d1\uc911\ud558\ub2e4\ubcf4\ub2c8 \uc815\uc801 \uc911\uc694\ud55c DB\uc758 \ucf54\ub4dc\uc758 \uc608\uc678\ucc98\ub9ac, \ube48 \uac12\uc744 \ubc18\ud658 \ud558\ub294 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucc98\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ucc30\ub9ac\uc758 \uaf3c\uaf3c\ud55c \ub9ac\ubdf0\ub85c DB\ubd80\ubd84\uacfc \ub098\ub9cc\uc758 JdbcTemplate\uc744 \uae54\ub054\ud558\uac8c \uad6c\ud604\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ub2f4\uac10"}),(0,s.jsx)(n.br,{}),"\n","\ucd08\ubc18\uc5d0\ub294 \uc5ec\uc720\ub86d\uc9c0\ub9cc \uc81c\ucd9c \ub9c8\uac10\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \uc218\ub85d \uc0ac\ub78c\uc774 \uae09\ud574\uc9c0\ub294 \uac83 \uac19\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\ud560 \ub550 \uc18d\ub3c4\ub97c \uc870\uc808\ud558\uace0, \ub9c8\uc74c\uc5d0 \uc5ec\uc720\ub97c \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,s.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"DAO \uc911\ubcf5 \uc81c\uac70"})}),"\n",(0,s.jsxs)(n.p,{children:["\ud504\ub864\ub85c\uadf8\uc5d0 ",(0,s.jsx)(n.a,{href:"https://prolog.techcourse.co.kr/studylogs/2947",children:"\uae00"}),"\uc744 \uc791\uc131\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","DAO\ub97c \uc791\uc131\ud558\ub294\ub370 try-catch-resources\uc640 \uc5ec\ub7ec \ucf54\ub4dc\uac00 \uc911\ubcf5\ub418\uc11c \uc81c\uac70\ud558\uace0\uc2f6\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc73c\ub85c \uae54\ub054\ud558\uac8c \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\udc4d"]}),"\n",(0,s.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ud398\uc5b4 \uc0dd\uac01\ud558\uae30"}),(0,s.jsx)(n.br,{}),"\n","\uac00\ube44\ub294 \ub204\uad6c\ubcf4\ub2e4 \ud398\uc5b4\ub97c \uc0dd\uac01\ud558\uace0, \ubc30\ub824\ud574\uc8fc\ub294 \ud398\uc5b4\uc600\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ub2f9 \ub5a8\uc5b4\uc9c8\uae4c\ubd10 \uac71\uc815\ub3c4 \ud574\uc8fc\uace0, \ub098\uc758 \ucee8\ub514\uc158\ub3c4 \ud655\uc778\ud574\uc92c\ub2e4!"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ubbf8\uc158 \ubab0\uc785\ud558\uae30"}),(0,s.jsx)(n.br,{}),"\n","\ucd5c\uadfc\uc5d0 \ubbf8\uc158\uc5d0 \uc798 \ubab0\uc785\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uac00\ube44\ub294 \ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \ubbf8\uc158\uc5d0 \ub300\ud55c \ubab0\uc785\ub3c4\uac00 \ub9e4\uc6b0 \uc88b\uc558\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc9d1\uc5d0\uac00\uc11c\ub3c4 \uccb4\uc2a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ub85c\uc9c1\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560 \uc9c0 \uc0dd\uac01\ud55c \ub4a4 \uaf3c\uaf3c\ud574\uc11c \uc815\ub9ac\ud574\uc11c \ub098\uc5d0\uac8c \ubcf4\ub0b4\uc8fc\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub355\ubd84\uc5d0 \ub098\ub3c4 \uac00\ube44\uc758 \uc0dd\uac01\uc744 \uc54c \uc218 \uc788\uc5b4\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294\ub370 \uac00\uc18d\ub3c4\uac00 \ubd99\uc740 \uac83 \uac19\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub610\ud55c \ubbf8\uc158\uc744 \uc798 \ub9c8\ubb34\ub9ac\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\uc774 \uc804\ub2ec\ub418\uc11c \uadf8\ub7f0\uc9c0 \ub098\ub3c4 \ub369\ub2ec\uc544 \uc5f4\uc2ec\ud788 \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\ude04"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc194\uc9c1\ud568"}),(0,s.jsx)(n.br,{}),"\n","\uba3c\uc800 \ud68c\uace0\ud558\uc790\uace0 \ub9d0 \uac78\uc5b4\uc918\uc11c \uc815\ub9d0 \uace0\ub9c8\uc6e0\ub2e4\uace0 \ud45c\ud604\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\ubaa8\ub974\ub294\uac8c \uc788\uc73c\uba74 \uc194\uc9c1\ud558\uac8c \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\ub098\uc758 \uc758\uacac\uc744 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud55c \uc0c1\ud0dc\ub85c \uc804\ub2ec\ud560 \ub54c \uc774\ud574\uac00 \uc548\ub418\uc5c8\ub2e4\uace0 \uc815\ud655\ud788 \uc804\ub2ec\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\uc194\uc9c1\ud568\uc740 \ud398\uc5b4\ud560 \ub54c \uc911\uc694\ud55c \ubd80\ubd84\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,s.jsx)(n.p,{children:"\ub9c8\uc9c0\ub9c9\uc73c\ub85c \ucc30\ub9ac\ud83c\udf6b \uccb4\uc2a4 \ubbf8\uc158\ub54c \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0 \ub0a8\uaca8\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4!"})]})}function j(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var s=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function c(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);n&&(s=s.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,s)}return r}function i(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var o=s.createContext({}),a=function(e){var n=s.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},h={inlineCode:"code",wrapper:function(e){var n=e.children;return s.createElement(s.Fragment,{},n)}},j=s.forwardRef((function(e,n){var r=e.components,t=e.mdxType,c=e.originalType,o=e.parentName,j=l(e,["components","mdxType","originalType","parentName"]),x=a(r),p=t,d=x["".concat(o,".").concat(p)]||x[p]||h[p]||c;return r?s.createElement(d,i(i({ref:n},j),{},{components:r})):s.createElement(d,i({ref:n},j))}));j.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[741],{86331:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>j,frontMatter:()=>c,metadata:()=>l,toc:()=>a});var s=r(85893),t=r(3905);const c={title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",slug:"chess-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,l={permalink:"/chess-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",description:"1, 2\ub2e8\uacc4//github.com/woowacourse/java-chess/pull/441",date:"2023-03-31T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 31\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.705,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",slug:"chess-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",permalink:"/grasp"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",permalink:"/woowacourse-level1-retrospective"}},o={authorsImageUrls:[]},a=[{value:"\uccb4\uc2a4",id:"\uccb4\uc2a4",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function h(e){const n={a:"a",admonition:"admonition",br:"br",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.ah)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,s.jsxs)(n.p,{children:["1, 2\ub2e8\uacc4: ",(0,s.jsx)(n.a,{href:"https://github.com/woowacourse/java-chess/pull/441",children:"https://github.com/woowacourse/java-chess/pull/441"}),(0,s.jsx)(n.br,{}),"\n","3, 4\ub2e8\uacc4: ",(0,s.jsx)(n.a,{href:"https://github.com/woowacourse/java-chess/pull/529",children:"https://github.com/woowacourse/java-chess/pull/529"})]})}),"\n",(0,s.jsx)(n.h3,{id:"\uccb4\uc2a4",children:"\uccb4\uc2a4"}),"\n",(0,s.jsxs)(n.p,{children:["\uccb4\uc2a4 \ubbf8\uc158\uc5d0\ub294 \uac00\ube44\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4!",(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4\ub294 \uc774\uc804 \ubbf8\uc158\ub4e4\ubcf4\ub2e4 \ud6e8\uc52c \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778\uc774\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \uac00\ube44\uc640 \ub098\ub294 \uccb4\uc2a4 \ub3c4\uba54\uc778\uc774 \uc775\uc219\ud574\uc11c \ub354 \ud3b8\ud55c \ub9c8\uc74c\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc5b4\ub824\uc6e0\ub358 \ubd80\ubd84\uc740 \uae30\ubb3c\uc758 \uc774\ub3d9, \uc774\ub3d9\uc2dc \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:["\uac00\ube44\uac00 \uc9d1\uc5d0\uac00\uc11c\ub3c4 \uae30\ubb3c\uc758 \uc774\ub3d9 \uad00\ub828\ud574 \uc0dd\uac01 \uc815\ub9ac\ud55c \uae00\uc744 \ubcf4\ub0b4\uc918\uc11c \ub354\uc6b1 \ube68\ub9ac \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ucd5c\uc885\uc801\uc73c\ub85c \uacb0\uc815\ud55c \ubd80\ubd84\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5\uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","Rank\uc640 File\uc740 \uac01\uac01 \uc704\uce58\uac12\uc744 \uac00\uc9c0\uace0 \uc788\uace0, \uac12\uc758 \ucc28\uc774\ub97c \uc774\uc6a9\ud574\uc11c \uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uacc4\uc0b0\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc9c1\uc120 \u2192 Rank\uc640 File \ucc28\uc774 \uc911 \ud558\ub098\uac00 0\uc774\uc5b4\uc57c \ud55c\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub300\uac01\uc120 \u2192 Rank\uc640 File \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \uac19\uc544\uc57c \ud55c\ub2e4. ex) abs(-2) == abs(2)",(0,s.jsx)(n.br,{}),"\n","\ub098\uc774\ud2b8 \u2192 \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \ud558\ub098\ub294 2 \ub098\uba38\uc9c0 \ud558\ub098\ub294 1\uc774\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ub3c4\ucc29 \uce78\uc758 \uae30\ubb3c \uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","\uc544\uad70 \u2192 \uc774\ub3d9\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc801\uad70 \u2192 \uc774\ub3d9\uc774 \uac00\ub2a5\ud558\ub2e4. \uc801\uad70\uc744 \uc7a1\ub294\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc911\uac04\uc5d0 \uae30\ubb3c \uc874\uc7ac \uc5ec\ubd80"}),(0,s.jsx)(n.br,{}),"\n","\uc774\ub3d9 \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\uba74 \uc548\ub41c\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9"}),(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4 \ubbf8\uc158\uc740 \ud2b9\ubcc4\ud558\uac8c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc5f0\uacb0\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uccb4\uc2a4 \uac8c\uc784\uc758 \uc0c1\ud0dc\ub97c \ub2e4\uc74c\uc758 \ub450\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uc815\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95"}),"\n",(0,s.jsx)(n.li,{children:"\uae30\ubcf4\ub97c \uc800\uc7a5\ud558\uace0 \uac8c\uc784\uc744 \ubd88\ub7ec\uc640 \uae30\ubcf4\ub300\ub85c \uc774\ub3d9\uc2dc\ud0a4\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\uae30\ubb3c\uc774 \uc774\ub3d9\ud560 \ub54c\ub9c8\ub2e4 \uac12\uc744 \uc800\uc7a5\ud558\uace0 \uc2f6\uc5c8\uace0, \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc774\uc720\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\ud134\uacfc \uac19\uc740 \ubd80\uac00\uc801\uc778 \uc694\uc18c\ub97c \uc800\uc7a5\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,s.jsx)(n.li,{children:"\uc774\ub3d9\uc744 \ud560 \ub54c \uae30\ubb3c\uc774 \uc7a1\ud788\ub294 \uacbd\uc6b0 update \ucffc\ub9ac(\uc774\ub3d9 \uae30\ubb3c)\uc640 delete(\uc7a1\ud78c \uae30\ubb3c) 2\uac1c\uc758 \ucffc\ub9ac\ub97c \ub0a0\ub824\uc57c \ud55c\ub2e4."}),"\n",(0,s.jsx)(n.li,{children:"\ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ub3c4\uba54\uc778\uc758 \ubcc0\uacbd\uc774 \ud06c\uac8c(\ucd08\uae30 \uc0c1\ud0dc\ub97c \uad6c\uc131\ud558\ub294 \ubd80\ubd84) \uc77c\uc5b4\ub098\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\uc815\ub9ac\ud558\uc790\uba74 \uae30\ubb3c \uc804\uccb4 \uc800\uc7a5\uacfc \uae30\ubcf4 \uc800\uc7a5\uc740 \ub2e4\uc74c\uacfc \ucc28\uc774\uac00 \uc788\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ubcf4\ub4dc\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc\uc5d0\uc11c 32\uac1c\uc758 Insert \ucffc\ub9ac(\uae30\ubb3c\uc758 \uc704\uce58) + \uae30\ubb3c \uc774\ub3d9 \uc2dc \uc6c0\uc9c1\uc784 \ubcc0\uacbd(\uc7a1\ud788\ub294 \uacbd\uc6b0 2\uac1c\uc758 \ucffc\ub9ac)",(0,s.jsx)(n.br,{}),"\n","\uae30\ubcf4\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uad6c\uc131 + \uc800\uc7a5\ub41c \uae30\ubcf4\ub97c select \ucffc\ub9ac\ub85c \uc870\ud68c\ud574\uc11c \uc0ac\uc6a9(1\ud68c) + insert \ucffc\ub9ac(\uc774\ub3d9 \ub2f9 1\ud68c)"]}),"\n",(0,s.jsx)(n.p,{children:"\ucd94\uac00\ub85c \uae30\ubcf4\uc800\uc7a5\uc774 \uad6c\ud604\ub3c4 \ub354\uc6b1 \uac04\ub2e8\ud558\ub2e4. \ud83d\udc4d"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"\ubd80\uac00\uc801\uc778 \ubd80\ubd84"})}),"\n",(0,s.jsx)(n.p,{children:"\ub9ac\ubdf0\uc5b4\uc778 \ucc30\ub9ac\ud83c\udf6b\uac00 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uac8c\uc784\uc774 \uc9c4\ud589\ub41c\ub2e4\uba74 \uc5b4\ub5a8\uc9c0? \uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ub2e4\uc591\ud55c \uc2dc\ub3c4\ub97c \ud574\ubd24\ub2e4."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\ub204\ub204\uc758 \ub3c4\uc6c0\uc73c\ub85c ConnectionPool \uad6c\ud604"}),"\n",(0,s.jsx)(n.li,{children:"ThreadLocal \uc0ac\uc6a9\ud574\uc11c \uc4f0\ub808\ub4dc \ubcc4 \uc138\uc158 \uad00\ub9ac"}),"\n",(0,s.jsx)(n.li,{children:"\uc2e4\uc81c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub0b4\uc5d0\uc11c \uccb4\uc2a4 \uac8c\uc784\uc774 \uc9c4\ud589\ub418\ub294 Board\ub97c ConcurrentHashMap\uc73c\ub85c \uc800\uc7a5(\uc0ac\uc2e4 \uc774 \ubd80\ubd84\uc740 \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ud544\uc694\uc5c6\uc9c0\ub9cc 2\uba85\uc774 \uc11c\ub85c \uac8c\uc784\ud558\ub294 \uacbd\uc6b0\ub97c \uc0dd\uac01\ud574\uc11c \ub123\uc5b4\ubcf4\uc558\ub2e4.)"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"\ub450 \uba85\uc774 \uc11c\ub85c \uac19\uc740 \ubc29\uc5d0 \uc785\uc7a5\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4\uba74 \ucd9c\ub825\ud558\ub294 \ubd80\ubd84\uc774 \uae4c\ub2e4\ub85c\uc6cc\uc9c8 \uac83 \uac19\ub2e4\uace0 \uc608\uc0c1\ub418\uc5b4(Board\uc5d0 \uc635\uc800\ubc84 \ud328\ud134\uc744 \uc0ac\uc6a9\ud574\uc57c\ub418\ub098?) \ud574\ubcfc \uc5c4\ub450\uac00 \ub098\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,s.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc9c0 \ubabb\ud55c \ubd80\ubd84"}),(0,s.jsx)(n.br,{}),"\n","DB \uad00\ub828 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0\ub9cc \uc9d1\uc911\ud558\ub2e4\ubcf4\ub2c8 \uc815\uc801 \uc911\uc694\ud55c DB\uc758 \ucf54\ub4dc\uc758 \uc608\uc678\ucc98\ub9ac, \ube48 \uac12\uc744 \ubc18\ud658 \ud558\ub294 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucc98\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ucc30\ub9ac\uc758 \uaf3c\uaf3c\ud55c \ub9ac\ubdf0\ub85c DB\ubd80\ubd84\uacfc \ub098\ub9cc\uc758 JdbcTemplate\uc744 \uae54\ub054\ud558\uac8c \uad6c\ud604\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ub2f4\uac10"}),(0,s.jsx)(n.br,{}),"\n","\ucd08\ubc18\uc5d0\ub294 \uc5ec\uc720\ub86d\uc9c0\ub9cc \uc81c\ucd9c \ub9c8\uac10\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \uc218\ub85d \uc0ac\ub78c\uc774 \uae09\ud574\uc9c0\ub294 \uac83 \uac19\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\ud560 \ub550 \uc18d\ub3c4\ub97c \uc870\uc808\ud558\uace0, \ub9c8\uc74c\uc5d0 \uc5ec\uc720\ub97c \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,s.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"DAO \uc911\ubcf5 \uc81c\uac70"})}),"\n",(0,s.jsxs)(n.p,{children:["\ud504\ub864\ub85c\uadf8\uc5d0 ",(0,s.jsx)(n.a,{href:"https://prolog.techcourse.co.kr/studylogs/2947",children:"\uae00"}),"\uc744 \uc791\uc131\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","DAO\ub97c \uc791\uc131\ud558\ub294\ub370 try-catch-resources\uc640 \uc5ec\ub7ec \ucf54\ub4dc\uac00 \uc911\ubcf5\ub418\uc11c \uc81c\uac70\ud558\uace0\uc2f6\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc73c\ub85c \uae54\ub054\ud558\uac8c \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\udc4d"]}),"\n",(0,s.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ud398\uc5b4 \uc0dd\uac01\ud558\uae30"}),(0,s.jsx)(n.br,{}),"\n","\uac00\ube44\ub294 \ub204\uad6c\ubcf4\ub2e4 \ud398\uc5b4\ub97c \uc0dd\uac01\ud558\uace0, \ubc30\ub824\ud574\uc8fc\ub294 \ud398\uc5b4\uc600\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc911\uac04 \uc911\uac04 \ub2f9 \ub5a8\uc5b4\uc9c8\uae4c\ubd10 \uac71\uc815\ub3c4 \ud574\uc8fc\uace0, \ub098\uc758 \ucee8\ub514\uc158\ub3c4 \ud655\uc778\ud574\uc92c\ub2e4!"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\ubbf8\uc158 \ubab0\uc785\ud558\uae30"}),(0,s.jsx)(n.br,{}),"\n","\ucd5c\uadfc\uc5d0 \ubbf8\uc158\uc5d0 \uc798 \ubab0\uc785\ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uac00\ube44\ub294 \ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \ubbf8\uc158\uc5d0 \ub300\ud55c \ubab0\uc785\ub3c4\uac00 \ub9e4\uc6b0 \uc88b\uc558\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\uc9d1\uc5d0\uac00\uc11c\ub3c4 \uccb4\uc2a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ub85c\uc9c1\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560 \uc9c0 \uc0dd\uac01\ud55c \ub4a4 \uaf3c\uaf3c\ud574\uc11c \uc815\ub9ac\ud574\uc11c \ub098\uc5d0\uac8c \ubcf4\ub0b4\uc8fc\uc5c8\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub355\ubd84\uc5d0 \ub098\ub3c4 \uac00\ube44\uc758 \uc0dd\uac01\uc744 \uc54c \uc218 \uc788\uc5b4\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294\ub370 \uac00\uc18d\ub3c4\uac00 \ubd99\uc740 \uac83 \uac19\ub2e4.",(0,s.jsx)(n.br,{}),"\n","\ub610\ud55c \ubbf8\uc158\uc744 \uc798 \ub9c8\ubb34\ub9ac\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\uc774 \uc804\ub2ec\ub418\uc11c \uadf8\ub7f0\uc9c0 \ub098\ub3c4 \ub369\ub2ec\uc544 \uc5f4\uc2ec\ud788 \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\ude04"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"\uc194\uc9c1\ud568"}),(0,s.jsx)(n.br,{}),"\n","\uba3c\uc800 \ud68c\uace0\ud558\uc790\uace0 \ub9d0 \uac78\uc5b4\uc918\uc11c \uc815\ub9d0 \uace0\ub9c8\uc6e0\ub2e4\uace0 \ud45c\ud604\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\ubaa8\ub974\ub294\uac8c \uc788\uc73c\uba74 \uc194\uc9c1\ud558\uac8c \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\ub098\uc758 \uc758\uacac\uc744 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud55c \uc0c1\ud0dc\ub85c \uc804\ub2ec\ud560 \ub54c \uc774\ud574\uac00 \uc548\ub418\uc5c8\ub2e4\uace0 \uc815\ud655\ud788 \uc804\ub2ec\ud574\uc8fc\ub294 \ubd80\ubd84",(0,s.jsx)(n.br,{}),"\n","\uc194\uc9c1\ud568\uc740 \ud398\uc5b4\ud560 \ub54c \uc911\uc694\ud55c \ubd80\ubd84\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,s.jsx)(n.p,{children:"\ub9c8\uc9c0\ub9c9\uc73c\ub85c \ucc30\ub9ac\ud83c\udf6b \uccb4\uc2a4 \ubbf8\uc158\ub54c \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0 \ub0a8\uaca8\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4!"})]})}function j(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var s=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function c(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);n&&(s=s.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,s)}return r}function i(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var o=s.createContext({}),a=function(e){var n=s.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},h={inlineCode:"code",wrapper:function(e){var n=e.children;return s.createElement(s.Fragment,{},n)}},j=s.forwardRef((function(e,n){var r=e.components,t=e.mdxType,c=e.originalType,o=e.parentName,j=l(e,["components","mdxType","originalType","parentName"]),x=a(r),p=t,d=x["".concat(o,".").concat(p)]||x[p]||h[p]||c;return r?s.createElement(d,i(i({ref:n},j),{},{components:r})):s.createElement(d,i({ref:n},j))}));j.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/8a27aeff.2359b403.js b/assets/js/8a27aeff.557abf1c.js similarity index 96% rename from assets/js/8a27aeff.2359b403.js rename to assets/js/8a27aeff.557abf1c.js index 818a419a5..88031b2d2 100644 --- a/assets/js/8a27aeff.2359b403.js +++ b/assets/js/8a27aeff.557abf1c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[71],{57041:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var n=t(85893),s=t(3905);const i={title:"2022\ub144 \ud68c\uace0",slug:"2022-retrospective",tags:["Retrospective"]},o=void 0,c={permalink:"/2022-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",title:"2022\ub144 \ud68c\uace0",description:"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70",date:"2023-01-02T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 2\uc77c",tags:[{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.705,hasTruncateMarker:!1,authors:[],frontMatter:{title:"2022\ub144 \ud68c\uace0",slug:"2022-retrospective",tags:["Retrospective"]},unlisted:!1,prevItem:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",permalink:"/the-essence-of-object-orientation"},nextItem:{title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",permalink:"/book-writer"}},l={authorsImageUrls:[]},a=[{value:"\uc804\uc5ed",id:"\uc804\uc5ed",level:3},{value:"\uc790\ubc14",id:"\uc790\ubc14",level:3},{value:"\uc2a4\ud130\ub514",id:"\uc2a4\ud130\ub514",level:3},{value:"\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4",id:"\uc6b0\uc544\ud55c-\ud14c\ud06c\ucf54\uc2a4",level:3},{value:"2023\ub144\uc5d0\ub294",id:"2023\ub144\uc5d0\ub294",level:3}];function p(e){const r={a:"a",br:"br",h3:"h3",p:"p",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.p,{children:"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70"}),"\n",(0,n.jsx)(r.h3,{id:"\uc804\uc5ed",children:"\uc804\uc5ed"}),"\n",(0,n.jsxs)(r.p,{children:["\uc57d 1\ub144 6\uac1c\uc6d4\uac04\uc758 \uacf5\uad70 \uc815\ubcf4\ubcf4\ud638\ubcd1 \uc0dd\ud65c\uc744 \ub9c8\uce58\uace0 \uc804\uc5ed\uc744 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc870\uae30 \uc804\uc5ed \ub54c\ubb38\uc5d0 2021\ub144 12\uc6d4\uc5d0 \ub098\uc654\uc9c0\ub9cc, \uc2e4\uc81c \uc804\uc5ed \ub0a0\uc9dc\ub294 2022\ub144\uc774\ub2c8 \ud68c\uace0\uc5d0 \uc801\uc5b4\ub3c4 \uc0c1\uad00\uc5c6\uaca0\uc9c0."]}),"\n",(0,n.jsxs)(r.p,{children:["\uc870\uae08 \ub354 \ubbf8\ub798\uc5d0 \ub300\ud55c \uc0dd\uac01\uc744 \ud574\ubcfc\uac78 \uadf8\ub7ac\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc804\uc5ed\uc744 \ud588\uc9c0\ub9cc \ubb50 \ud558\ub098 \uc81c\ub300\ub85c \ud560 \uc904 \uc544\ub294 \uac83\ub3c4 \uc5c6\uc73c\ub2c8 \ub113\uc740 \ubc14\ub2f7\uc18d\uc5d0 \ub369\uadf8\ub7ec\ub2c8 \ub193\uc544\uc9c4 \uae30\ubd84\uc774 \uad1c\ud788 \ub4e4\uc5c8\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc77c\ucc0d \uc0dd\uac01\uc744 \uc815\ub9ac\ud558\uc5ec \ubc29\ud5a5\uc744 \uc7a1\uc9c0 \ubabb\ud588\uae30\uc5d0 \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub0a8\uc558\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc790\ubc14",children:"\uc790\ubc14"}),"\n",(0,n.jsxs)(r.p,{children:["\uc804\uc5ed\uc744 \ud558\uace0 \uc9c4\ub85c\ub97c \uace0\ubbfc\ud558\ub2e4 \ud5a5\ub85c\ub2d8\uc758 ",(0,n.jsx)(r.a,{href:"https://jojoldu.tistory.com/609",children:"\uc790\ubc14 \uacf5\ud654\uad6d"})," \ud3ec\uc2a4\ud305\uc744 \uc77d\uace0 \ub098\uc11c \uc790\ubc14 \uacf5\ubd80\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc720\uba85\ud55c \uc778\ud504\ub7f0\uc758 \uae40\uc601\ud55c\ub2d8\uc758 \uc2a4\ud504\ub9c1 \uac15\uc758\ub3c4 \uc788\uace0, \uc88b\uc740 \uc790\ubc14 \uac1c\ubc1c \uc11c\uc801\uc774 \ub9ce\uc544\uc11c \ub3c5\ud559\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud558\ub2e4 \ubcf4\ub2c8 \uc790\ubc14\uc640 \uc2a4\ud504\ub9c1\uc744 \uacf5\ubd80\ud558\uba74\uc11c \u201c\uc65c \uc9c4\uc791\ud558\uc9c0 \uc54a\uc558\uc9c0\u201d\ub77c\ub294 \uc0dd\uac01\ub3c4 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc591\uc9c8\uc758 \uc790\ub8cc\ub3c4 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0, \uc608\uc804\uc5d0 \ub178\ub4dc\ub85c \uac1c\ubc1c\ud588\uc744 \ub54c \ud480\uc9c0 \ubabb\ud588\ub358 \ub2f5\ub2f5\ud568\uc744 \ub9ce\uc774 \ud574\uc18c\ud588\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["23\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae4a\uac8c \uc790\ubc14\ub97c \uacf5\ubd80\ud574\ubcfc \uc0dd\uac01\uc774\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc5b8\uc5b4\ub97c \ud558\ub098 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ub9ce\uc740 \ub3c4\uc6c0\uc774 \ub418\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc2a4\ud130\ub514",children:"\uc2a4\ud130\ub514"}),"\n",(0,n.jsxs)(r.p,{children:["\uae40\uc601\ud55c\ub2d8\uc758 \uac15\uc758\ub97c \uac70\uc758 \ub2e4 \ub4e4\uc5c8\uc744 \ub54c\ucbe4, \ud56d\uc0c1 \uac15\uc758\uc5d0\uc11c \uc5b8\uae09\ub418\ub294 \ud1a0\ube44\uc758 \uc2a4\ud504\ub9c1\uc744 \uc77d\uc5b4\ubcf4\uace0 \uc2f6\uc5b4\uc84c\uace0",(0,n.jsx)(r.br,{}),"\n","\ud63c\uc790 \uacf5\ubd80\ud558\uae30\uc5d0\ub294 \ub3d9\uae30\ubd80\uc5ec\ub3c4 \ubd80\uc871\ud588\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud130\ub514\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\uc744 \ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uacf5\ubd80\ub97c \ud560 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\uc9c0\ub9cc \ub098\uc5d0\uac8c\ub294 \ub0b4\uc6a9\uc774 \uaf64\ub098 \uc5b4\ub824\uc6cc\uc11c \uc2dc\uac04\uc744 \ub9ce\uc774 \uc18c\ube44\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uac19\uc774 \uc2a4\ud130\ub514\ud558\uc2dc\ub294 \ubd84\uacfc 7\uac1c\uc6d4 \ub3d9\uc548 \uc2a4\ud130\ub514\ub97c \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00 \ucd1d 3\uad8c\uc758 \ucc45\uc744 \uc77d\uc744 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc6b0\uc544\ud55c-\ud14c\ud06c\ucf54\uc2a4",children:"\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4"}),"\n",(0,n.jsxs)(r.p,{children:["\uad70 \ubcf5\ubb34 \uc911\uc77c \ub54c \uc9c0\uc6d0\ud588\ub2e4 \ub5a8\uc5b4\uc9c4 \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ub2e4\uc2dc \uc9c0\uc6d0\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88 \uc5f0\ub3c4\uc5d0 \ucde8\uc5c5\uc744 \ud558\ub294 \uac8c \ubaa9\ud45c\uc600\uc9c0\ub9cc \ub0b4\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud2b9\ubcc4\ud55c \ubb34\uae30\uac00 \uc5c6\ub2e4\ub294 \uac78 \uae68\ub2ec\uc558\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc801\uc9c0 \uc54a\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574 \uc900\ube44\ub97c \ud588\uace0, \uac10\uc0ac\ud558\uac8c\ub3c4 \uc774\ubc88\uc5d0\ub294 \ucd5c\uc885 \ud569\uaca9\uc744 \ud588\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub09c \uc0ac\ub78c\ub4e4\uacfc \uc18c\ud1b5\ud558\uace0, \ud611\uc5c5\ud558\ub294 \ub2a5\ub825\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ud1b5\ud574 \uadf8 \ube48 \ubd80\ubd84\uc744 \ucc44\uc6b0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"2023\ub144\uc5d0\ub294",children:"2023\ub144\uc5d0\ub294"}),"\n",(0,n.jsxs)(r.p,{children:["\ub9c8\uc74c\uc758 \uc5ec\uc720\uac00 \uc5c6\uc5c8\ub358 2022\ub144\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud558\uace0 \uc2f6\uc740 \uac74 \ub9ce\uc9c0\ub9cc, \uc774\ubc88\uc5d0\ub294 \uc5ec\uc720\ub97c \uac00\uc9c0\uace0 \ud560 \uc218 \uc788\ub294 \uac83\uc5d0 \ucd5c\uc120\uc744 \ub2e4\ud574\uc57c\uaca0\ub2e4."]})]})}function u(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>a});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function o(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=n.createContext({}),a=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):o(o({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=a(t),b=s,j=d["".concat(l,".").concat(b)]||d[b]||p[b]||i;return t?n.createElement(j,o(o({ref:r},u),{},{components:t})):n.createElement(j,o({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[71],{57041:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var n=t(85893),s=t(3905);const i={title:"2022\ub144 \ud68c\uace0",slug:"2022-retrospective",tags:["Retrospective"]},o=void 0,c={permalink:"/2022-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",title:"2022\ub144 \ud68c\uace0",description:"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70",date:"2023-01-02T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 2\uc77c",tags:[{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.705,hasTruncateMarker:!1,authors:[],frontMatter:{title:"2022\ub144 \ud68c\uace0",slug:"2022-retrospective",tags:["Retrospective"]},unlisted:!1,prevItem:{title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",permalink:"/book-writer"},nextItem:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",permalink:"/the-essence-of-object-orientation"}},l={authorsImageUrls:[]},a=[{value:"\uc804\uc5ed",id:"\uc804\uc5ed",level:3},{value:"\uc790\ubc14",id:"\uc790\ubc14",level:3},{value:"\uc2a4\ud130\ub514",id:"\uc2a4\ud130\ub514",level:3},{value:"\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4",id:"\uc6b0\uc544\ud55c-\ud14c\ud06c\ucf54\uc2a4",level:3},{value:"2023\ub144\uc5d0\ub294",id:"2023\ub144\uc5d0\ub294",level:3}];function p(e){const r={a:"a",br:"br",h3:"h3",p:"p",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.p,{children:"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70"}),"\n",(0,n.jsx)(r.h3,{id:"\uc804\uc5ed",children:"\uc804\uc5ed"}),"\n",(0,n.jsxs)(r.p,{children:["\uc57d 1\ub144 6\uac1c\uc6d4\uac04\uc758 \uacf5\uad70 \uc815\ubcf4\ubcf4\ud638\ubcd1 \uc0dd\ud65c\uc744 \ub9c8\uce58\uace0 \uc804\uc5ed\uc744 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc870\uae30 \uc804\uc5ed \ub54c\ubb38\uc5d0 2021\ub144 12\uc6d4\uc5d0 \ub098\uc654\uc9c0\ub9cc, \uc2e4\uc81c \uc804\uc5ed \ub0a0\uc9dc\ub294 2022\ub144\uc774\ub2c8 \ud68c\uace0\uc5d0 \uc801\uc5b4\ub3c4 \uc0c1\uad00\uc5c6\uaca0\uc9c0."]}),"\n",(0,n.jsxs)(r.p,{children:["\uc870\uae08 \ub354 \ubbf8\ub798\uc5d0 \ub300\ud55c \uc0dd\uac01\uc744 \ud574\ubcfc\uac78 \uadf8\ub7ac\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc804\uc5ed\uc744 \ud588\uc9c0\ub9cc \ubb50 \ud558\ub098 \uc81c\ub300\ub85c \ud560 \uc904 \uc544\ub294 \uac83\ub3c4 \uc5c6\uc73c\ub2c8 \ub113\uc740 \ubc14\ub2f7\uc18d\uc5d0 \ub369\uadf8\ub7ec\ub2c8 \ub193\uc544\uc9c4 \uae30\ubd84\uc774 \uad1c\ud788 \ub4e4\uc5c8\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc77c\ucc0d \uc0dd\uac01\uc744 \uc815\ub9ac\ud558\uc5ec \ubc29\ud5a5\uc744 \uc7a1\uc9c0 \ubabb\ud588\uae30\uc5d0 \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub0a8\uc558\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc790\ubc14",children:"\uc790\ubc14"}),"\n",(0,n.jsxs)(r.p,{children:["\uc804\uc5ed\uc744 \ud558\uace0 \uc9c4\ub85c\ub97c \uace0\ubbfc\ud558\ub2e4 \ud5a5\ub85c\ub2d8\uc758 ",(0,n.jsx)(r.a,{href:"https://jojoldu.tistory.com/609",children:"\uc790\ubc14 \uacf5\ud654\uad6d"})," \ud3ec\uc2a4\ud305\uc744 \uc77d\uace0 \ub098\uc11c \uc790\ubc14 \uacf5\ubd80\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc720\uba85\ud55c \uc778\ud504\ub7f0\uc758 \uae40\uc601\ud55c\ub2d8\uc758 \uc2a4\ud504\ub9c1 \uac15\uc758\ub3c4 \uc788\uace0, \uc88b\uc740 \uc790\ubc14 \uac1c\ubc1c \uc11c\uc801\uc774 \ub9ce\uc544\uc11c \ub3c5\ud559\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud558\ub2e4 \ubcf4\ub2c8 \uc790\ubc14\uc640 \uc2a4\ud504\ub9c1\uc744 \uacf5\ubd80\ud558\uba74\uc11c \u201c\uc65c \uc9c4\uc791\ud558\uc9c0 \uc54a\uc558\uc9c0\u201d\ub77c\ub294 \uc0dd\uac01\ub3c4 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc591\uc9c8\uc758 \uc790\ub8cc\ub3c4 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0, \uc608\uc804\uc5d0 \ub178\ub4dc\ub85c \uac1c\ubc1c\ud588\uc744 \ub54c \ud480\uc9c0 \ubabb\ud588\ub358 \ub2f5\ub2f5\ud568\uc744 \ub9ce\uc774 \ud574\uc18c\ud588\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["23\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae4a\uac8c \uc790\ubc14\ub97c \uacf5\ubd80\ud574\ubcfc \uc0dd\uac01\uc774\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc5b8\uc5b4\ub97c \ud558\ub098 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ub9ce\uc740 \ub3c4\uc6c0\uc774 \ub418\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc2a4\ud130\ub514",children:"\uc2a4\ud130\ub514"}),"\n",(0,n.jsxs)(r.p,{children:["\uae40\uc601\ud55c\ub2d8\uc758 \uac15\uc758\ub97c \uac70\uc758 \ub2e4 \ub4e4\uc5c8\uc744 \ub54c\ucbe4, \ud56d\uc0c1 \uac15\uc758\uc5d0\uc11c \uc5b8\uae09\ub418\ub294 \ud1a0\ube44\uc758 \uc2a4\ud504\ub9c1\uc744 \uc77d\uc5b4\ubcf4\uace0 \uc2f6\uc5b4\uc84c\uace0",(0,n.jsx)(r.br,{}),"\n","\ud63c\uc790 \uacf5\ubd80\ud558\uae30\uc5d0\ub294 \ub3d9\uae30\ubd80\uc5ec\ub3c4 \ubd80\uc871\ud588\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud130\ub514\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\uc744 \ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uacf5\ubd80\ub97c \ud560 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\uc9c0\ub9cc \ub098\uc5d0\uac8c\ub294 \ub0b4\uc6a9\uc774 \uaf64\ub098 \uc5b4\ub824\uc6cc\uc11c \uc2dc\uac04\uc744 \ub9ce\uc774 \uc18c\ube44\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uac19\uc774 \uc2a4\ud130\ub514\ud558\uc2dc\ub294 \ubd84\uacfc 7\uac1c\uc6d4 \ub3d9\uc548 \uc2a4\ud130\ub514\ub97c \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00 \ucd1d 3\uad8c\uc758 \ucc45\uc744 \uc77d\uc744 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc6b0\uc544\ud55c-\ud14c\ud06c\ucf54\uc2a4",children:"\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4"}),"\n",(0,n.jsxs)(r.p,{children:["\uad70 \ubcf5\ubb34 \uc911\uc77c \ub54c \uc9c0\uc6d0\ud588\ub2e4 \ub5a8\uc5b4\uc9c4 \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ub2e4\uc2dc \uc9c0\uc6d0\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88 \uc5f0\ub3c4\uc5d0 \ucde8\uc5c5\uc744 \ud558\ub294 \uac8c \ubaa9\ud45c\uc600\uc9c0\ub9cc \ub0b4\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud2b9\ubcc4\ud55c \ubb34\uae30\uac00 \uc5c6\ub2e4\ub294 \uac78 \uae68\ub2ec\uc558\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc801\uc9c0 \uc54a\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574 \uc900\ube44\ub97c \ud588\uace0, \uac10\uc0ac\ud558\uac8c\ub3c4 \uc774\ubc88\uc5d0\ub294 \ucd5c\uc885 \ud569\uaca9\uc744 \ud588\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub09c \uc0ac\ub78c\ub4e4\uacfc \uc18c\ud1b5\ud558\uace0, \ud611\uc5c5\ud558\ub294 \ub2a5\ub825\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ud1b5\ud574 \uadf8 \ube48 \ubd80\ubd84\uc744 \ucc44\uc6b0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"2023\ub144\uc5d0\ub294",children:"2023\ub144\uc5d0\ub294"}),"\n",(0,n.jsxs)(r.p,{children:["\ub9c8\uc74c\uc758 \uc5ec\uc720\uac00 \uc5c6\uc5c8\ub358 2022\ub144\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud558\uace0 \uc2f6\uc740 \uac74 \ub9ce\uc9c0\ub9cc, \uc774\ubc88\uc5d0\ub294 \uc5ec\uc720\ub97c \uac00\uc9c0\uace0 \ud560 \uc218 \uc788\ub294 \uac83\uc5d0 \ucd5c\uc120\uc744 \ub2e4\ud574\uc57c\uaca0\ub2e4."]})]})}function u(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>a});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function o(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=n.createContext({}),a=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):o(o({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=a(t),b=s,j=d["".concat(l,".").concat(b)]||d[b]||p[b]||i;return t?n.createElement(j,o(o({ref:r},u),{},{components:t})):n.createElement(j,o({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/8ad2f007.9b356e06.js b/assets/js/8ad2f007.05e7e42b.js similarity index 97% rename from assets/js/8ad2f007.9b356e06.js rename to assets/js/8ad2f007.05e7e42b.js index 6bae46b4b..d2708e489 100644 --- a/assets/js/8ad2f007.9b356e06.js +++ b/assets/js/8ad2f007.05e7e42b.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8360],{6073:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var n=r(85893),o=r(3905);const c={title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",slug:"mock-static-method",tags:["Mockito","static"]},i=void 0,a={permalink:"/mock-static-method",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",source:"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",description:"\uac1c\uc694",date:"2023-07-30T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 30\uc77c",tags:[{label:"Mockito",permalink:"/tags/mockito"},{label:"static",permalink:"/tags/static"}],readingTime:2.635,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",slug:"mock-static-method",tags:["Mockito","static"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",permalink:"/route-image-python"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",permalink:"/route-image-intro"}},s={authorsImageUrls:[]},l=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"Mocking static methods",id:"mocking-static-methods",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function m(e){const t={a:"a",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,n.jsxs)(t.p,{children:["\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud55c\ub2e4\ub294 \uac83\uc740 \uac1d\uccb4\uc9c0\ud5a5\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ubcfc \ub54c \uc548\ud2f0\ud328\ud134\uc774\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ud2b9\uc218\ud55c \uacbd\uc6b0\uc5d0\ub294 \uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc774 \ud544\uc694\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:"\uc608\ub97c \ub4e4\uc5b4 \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud55c\ub2e4\ub358\uc9c0, IO \uad00\ub828\ud55c \ubd80\ubd84\uc744 \ud14c\uc2a4\ud2b8 \ud560 \ub54c \uc815\ub9d0 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\ub9cc \uc801\uc6a9\ud560 \uc218 \uc788\uc744 \uac83\uc774\ub2e4."}),"\n",(0,n.jsxs)(t.p,{children:["\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba70 ImageIo.write \uba54\uc11c\ub4dc\uac00 \ud638\ucd9c\ub418\ub294 \uc9c0 \uac80\uc99d\uc774 \ud544\uc694\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud574\ub2f9 static \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294 \ubd80\ubd84\uc744 \ub530\ub85c RouteImageUploader \ud074\ub798\uc2a4\ub85c \ucd5c\ub300\ud55c \ubd84\ub9ac\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc800\uc7a5 \uae30\ub2a5 \uc790\uccb4\uac00 \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc774\uace0, \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294\ub370\ub294 mock\uc744 \uc0ac\uc6a9\ud558\ub294\uac8c \uc801\uc808\ud558\ub2e4\uace0 \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",children:"public void upload(BufferedImage bufferedImage) {\n File file = new File(\ud30c\uc77c\uacbd\ub85c);\n try {\n ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);\n } catch (IOException e) {\n throw new DrawException(IMAGE_SAVE_FAIL);\n }\n}\n"})}),"\n",(0,n.jsx)(t.h3,{id:"mocking-static-methods",children:"Mocking static methods"}),"\n",(0,n.jsxs)(t.p,{children:["Mockito 3.4.0 \uc774\ud6c4\uc5d0\ub294 static method\ub97c \ubaa8\ud0b9\ud560 \uc218 \uc788\ub294 Mockito.mockStatic \uba54\uc11c\ub4dc\ub97c \uc9c0\uc6d0\ud55c\ub2e4.",(0,n.jsx)(t.br,{}),"\n","mockStatic\uc744 \uc0ac\uc6a9\ud558\uba74 ",(0,n.jsx)(t.code,{children:"MockedStatic"}),"\uc774 \ubc18\ud658\ub418\ub294\ub370 \uc0ac\uc6a9 \ud6c4 \uaf2d close\ub97c \ud574\uc918\uc57c \ud55c\ub2e4."]}),"\n",(0,n.jsxs)(t.p,{children:["JUnit\uc758 @BeforeAll\ub85c \uc124\uc815\ud558\uace0 @AfterAll \uba54\uc11c\ub4dc\ub85c \uc885\ub8cc\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\uc9c0\ub9cc ",(0,n.jsx)(t.code,{children:"MockedStatic"}),"\uc758 \uc0c1\uc704 \uc778\ud130\ud398\uc774\uc2a4\uc778 ScopedMock\uc774 AutoCloseable\uc744 \uad6c\ud604\ud558\uace0 \uc788\uae30\uc5d0 try-with-resources\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \ub354\uc6b1 \uc88b\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",children:"// given\nBufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);\nRouteImageUploader routeImageUploader = new RouteImageUploader();\n\n// expect\ntry (MockedStatic imageIO = Mockito.mockStatic(ImageIO.class)) {\n routeImageUploader.upload(bufferedImage);\n imageIO.verify(\n () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),\n times(1)\n );\n}\n"})}),"\n",(0,n.jsx)(t.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,n.jsxs)(t.p,{children:["\uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc740 \uc548\ud2f0\ud328\ud134\uc774\uc73c\ub85c \uc801\uc808\ud55c \ucd94\uc0c1\ud654\ub97c \uc774\uc6a9\ud574 \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc88b\uc740 \ucf54\ub4dc\ub97c \ub9cc\ub4dc\ub294 \uc5f0\uc2b5\uc744 \ud558\uc790.",(0,n.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ucd94\uc0c1\ud654\ub97c \ud558\uba74 \ud560 \uc218\ub85d \ucf54\ub4dc\uc758 \ubcf5\uc7a1\ub3c4\ub294 \uc99d\uac00\ud55c\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud56d\uc0c1 \uc0c1\ud669\uc744 \uace0\ub824\ud558\uace0 \uac04\uacb0\ud568\uc744 \ud3ec\uae30\ud560 \ub9cc\ud07c \uc911\uc694\ud55c \ubd80\ubd84\uc778\uc9c0 \uc801\uc808\ud55c \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uace0\ub824\ud558\uc790."]}),"\n",(0,n.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks",children:"Mocking static methods"}),(0,n.jsx)(t.br,{}),"\n",(0,n.jsx)(t.a,{href:"https://www.baeldung.com/mockito-mock-static-methods",children:"Mockito mock static methods"}),(0,n.jsx)(t.br,{}),"\n",(0,n.jsx)(t.a,{href:"https://github.com/mockito/mockito/issues/1013",children:"Enable mocking static methods in Mockito"})]})]})}function d(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(m,{...e})}):m(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,d=a(e,["components","mdxType","originalType","parentName"]),u=l(r),p=o,g=u["".concat(s,".").concat(p)]||u[p]||m[p]||c;return r?n.createElement(g,i(i({ref:t},d),{},{components:r})):n.createElement(g,i({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8360],{6073:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var n=r(85893),o=r(3905);const c={title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",slug:"mock-static-method",tags:["Mockito","static"]},i=void 0,a={permalink:"/mock-static-method",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",source:"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",description:"\uac1c\uc694",date:"2023-07-30T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 30\uc77c",tags:[{label:"Mockito",permalink:"/tags/mockito"},{label:"static",permalink:"/tags/static"}],readingTime:2.635,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",slug:"mock-static-method",tags:["Mockito","static"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",permalink:"/route-image-intro"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",permalink:"/route-image-python"}},s={authorsImageUrls:[]},l=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"Mocking static methods",id:"mocking-static-methods",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function m(e){const t={a:"a",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,n.jsxs)(t.p,{children:["\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud55c\ub2e4\ub294 \uac83\uc740 \uac1d\uccb4\uc9c0\ud5a5\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ubcfc \ub54c \uc548\ud2f0\ud328\ud134\uc774\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ud2b9\uc218\ud55c \uacbd\uc6b0\uc5d0\ub294 \uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc774 \ud544\uc694\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:"\uc608\ub97c \ub4e4\uc5b4 \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud55c\ub2e4\ub358\uc9c0, IO \uad00\ub828\ud55c \ubd80\ubd84\uc744 \ud14c\uc2a4\ud2b8 \ud560 \ub54c \uc815\ub9d0 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\ub9cc \uc801\uc6a9\ud560 \uc218 \uc788\uc744 \uac83\uc774\ub2e4."}),"\n",(0,n.jsxs)(t.p,{children:["\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba70 ImageIo.write \uba54\uc11c\ub4dc\uac00 \ud638\ucd9c\ub418\ub294 \uc9c0 \uac80\uc99d\uc774 \ud544\uc694\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud574\ub2f9 static \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294 \ubd80\ubd84\uc744 \ub530\ub85c RouteImageUploader \ud074\ub798\uc2a4\ub85c \ucd5c\ub300\ud55c \ubd84\ub9ac\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc800\uc7a5 \uae30\ub2a5 \uc790\uccb4\uac00 \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc774\uace0, \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294\ub370\ub294 mock\uc744 \uc0ac\uc6a9\ud558\ub294\uac8c \uc801\uc808\ud558\ub2e4\uace0 \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",children:"public void upload(BufferedImage bufferedImage) {\n File file = new File(\ud30c\uc77c\uacbd\ub85c);\n try {\n ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);\n } catch (IOException e) {\n throw new DrawException(IMAGE_SAVE_FAIL);\n }\n}\n"})}),"\n",(0,n.jsx)(t.h3,{id:"mocking-static-methods",children:"Mocking static methods"}),"\n",(0,n.jsxs)(t.p,{children:["Mockito 3.4.0 \uc774\ud6c4\uc5d0\ub294 static method\ub97c \ubaa8\ud0b9\ud560 \uc218 \uc788\ub294 Mockito.mockStatic \uba54\uc11c\ub4dc\ub97c \uc9c0\uc6d0\ud55c\ub2e4.",(0,n.jsx)(t.br,{}),"\n","mockStatic\uc744 \uc0ac\uc6a9\ud558\uba74 ",(0,n.jsx)(t.code,{children:"MockedStatic"}),"\uc774 \ubc18\ud658\ub418\ub294\ub370 \uc0ac\uc6a9 \ud6c4 \uaf2d close\ub97c \ud574\uc918\uc57c \ud55c\ub2e4."]}),"\n",(0,n.jsxs)(t.p,{children:["JUnit\uc758 @BeforeAll\ub85c \uc124\uc815\ud558\uace0 @AfterAll \uba54\uc11c\ub4dc\ub85c \uc885\ub8cc\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\uc9c0\ub9cc ",(0,n.jsx)(t.code,{children:"MockedStatic"}),"\uc758 \uc0c1\uc704 \uc778\ud130\ud398\uc774\uc2a4\uc778 ScopedMock\uc774 AutoCloseable\uc744 \uad6c\ud604\ud558\uace0 \uc788\uae30\uc5d0 try-with-resources\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \ub354\uc6b1 \uc88b\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",children:"// given\nBufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);\nRouteImageUploader routeImageUploader = new RouteImageUploader();\n\n// expect\ntry (MockedStatic imageIO = Mockito.mockStatic(ImageIO.class)) {\n routeImageUploader.upload(bufferedImage);\n imageIO.verify(\n () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),\n times(1)\n );\n}\n"})}),"\n",(0,n.jsx)(t.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,n.jsxs)(t.p,{children:["\uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc740 \uc548\ud2f0\ud328\ud134\uc774\uc73c\ub85c \uc801\uc808\ud55c \ucd94\uc0c1\ud654\ub97c \uc774\uc6a9\ud574 \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc88b\uc740 \ucf54\ub4dc\ub97c \ub9cc\ub4dc\ub294 \uc5f0\uc2b5\uc744 \ud558\uc790.",(0,n.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ucd94\uc0c1\ud654\ub97c \ud558\uba74 \ud560 \uc218\ub85d \ucf54\ub4dc\uc758 \ubcf5\uc7a1\ub3c4\ub294 \uc99d\uac00\ud55c\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud56d\uc0c1 \uc0c1\ud669\uc744 \uace0\ub824\ud558\uace0 \uac04\uacb0\ud568\uc744 \ud3ec\uae30\ud560 \ub9cc\ud07c \uc911\uc694\ud55c \ubd80\ubd84\uc778\uc9c0 \uc801\uc808\ud55c \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uace0\ub824\ud558\uc790."]}),"\n",(0,n.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks",children:"Mocking static methods"}),(0,n.jsx)(t.br,{}),"\n",(0,n.jsx)(t.a,{href:"https://www.baeldung.com/mockito-mock-static-methods",children:"Mockito mock static methods"}),(0,n.jsx)(t.br,{}),"\n",(0,n.jsx)(t.a,{href:"https://github.com/mockito/mockito/issues/1013",children:"Enable mocking static methods in Mockito"})]})]})}function d(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(m,{...e})}):m(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,d=a(e,["components","mdxType","originalType","parentName"]),u=l(r),p=o,g=u["".concat(s,".").concat(p)]||u[p]||m[p]||c;return r?n.createElement(g,i(i({ref:t},d),{},{components:r})):n.createElement(g,i({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/905ecccc.aeeb3c76.js b/assets/js/905ecccc.63be6be2.js similarity index 99% rename from assets/js/905ecccc.aeeb3c76.js rename to assets/js/905ecccc.63be6be2.js index a2494ff90..8a6ed7a86 100644 --- a/assets/js/905ecccc.aeeb3c76.js +++ b/assets/js/905ecccc.63be6be2.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2939],{76306:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var r=t(85893),o=t(3905),a=t(74866),i=t(85162);const s={title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},l=void 0,c={permalink:"/tomcat-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1, 2\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-http/pull/302",date:"2023-09-11T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:12.345,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"},nextItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"}},u={authorsImageUrls:[]},d=[{value:"\ud1b0\ucea3 \uad6c\ud604",id:"\ud1b0\ucea3-\uad6c\ud604",level:3},{value:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",level:3},{value:"\ucf54\ub4dc \ub9ac\ubdf0",id:"\ucf54\ub4dc-\ub9ac\ubdf0",level:3},{value:"SessionConfig",id:"sessionconfig",level:3},{value:"HTTP \uc218\uc5c5",id:"http-\uc218\uc5c5",level:3},{value:"Thread \uc218\uc5c5",id:"thread-\uc218\uc5c5",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",pre:"pre",...(0,o.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,r.jsxs)(n.p,{children:["1, 2\ub2e8\uacc4: ",(0,r.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-http/pull/302",children:"https://github.com/woowacourse/jwp-dashboard-http/pull/302"}),(0,r.jsx)(n.br,{}),"\n","3, 4\ub2e8\uacc4: ",(0,r.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-http/pull/431",children:"https://github.com/woowacourse/jwp-dashboard-http/pull/431"})]})}),"\n",(0,r.jsx)(n.h3,{id:"\ud1b0\ucea3-\uad6c\ud604",children:"\ud1b0\ucea3 \uad6c\ud604"}),"\n",(0,r.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2616/",children:"RFC 2616"}),"\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",children:"\ub2e4\uc774\uc5b4\uadf8\ub7a8"}),"\n",(0,r.jsxs)(n.p,{children:["Catalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph coyote\n\t\tHP[Http11Processor] --\x3e A\n\t\tHP --\x3e HttpRequestParser\n\t\tHP --\x3e HttpResponseGenerator\n\t\tA[Adapter]\n end\n\n subgraph catalina\n\t\tRA[RequestAdapter] -.-> A\n\t\tAC[AbstractController] -.-> C[Controller]\n\t\tStaticController -.-> AC\n\t\tSM[SessionManger] -.-> Manager\n\t\tTC[Tomcat] --\x3e RA\n\t\tRA --\x3e C\n\t\tRA --\x3e Manager\n\t\tRA --\x3e RM\n\t\tRM[RequestMapper] --\x3e C\n end\n\n subgraph jwp\n\t\tLC[LoginController] -.-> AC\n\t\tApplication --\x3e TC\n end\n"}),"\n",(0,r.jsx)(n.h3,{id:"\ucf54\ub4dc-\ub9ac\ubdf0",children:"\ucf54\ub4dc \ub9ac\ubdf0"}),"\n",(0,r.jsxs)(n.p,{children:["\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"sessionconfig",children:"SessionConfig"}),"\n",(0,r.jsxs)(n.p,{children:["\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 ",(0,r.jsx)(n.a,{href:"https://github.com/apache/tomcat/pull/660",children:"\ucee8\ud2b8\ub9ac\ubdf0\ud2b8"}),"\ub97c \uc2dc\ub3c4\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n","\n","\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(i.Z,{value:"\uae30\uc874",label:"\uae30\uc874",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_COOKIE_NAME;\n }\n\n return result;\n}\n\npublic static String getSessionUriParamName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_PARAMETER_NAME;\n }\n\n return result;\n}\n\nprivate static String getConfiguredSessionCookieName(Context context) {\n\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc =\n context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n\n return null;\n}\n"})})}),(0,r.jsx)(i.Z,{value:"PR \uc694\uccad",label:"PR \uc694\uccad",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_COOKIE_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_PARAMETER_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n return defaultName;\n}\n"})})}),(0,r.jsx)(i.Z,{value:"\ucd5c\uc885",label:"\ucd5c\uc885",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n return defaultName;\n}\n"})})})]}),"\n",(0,r.jsx)(n.h3,{id:"http-\uc218\uc5c5",children:"HTTP \uc218\uc5c5"}),"\n",(0,r.jsxs)(n.p,{children:["\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","HTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yml",children:"server:\n compression:\n enabled: true\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 ",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/issues/21369",children:"issue"}),"\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network."}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Phil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4."}),"\n",(0,r.jsx)(n.admonition,{title:"ETag",type:"note",children:(0,r.jsxs)(n.p,{children:["ETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","MDN"]})}),"\n",(0,r.jsx)(n.h3,{id:"thread-\uc218\uc5c5",children:"Thread \uc218\uc5c5"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"threads.max"}),": Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"max-connections"}),": Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"accept-count"}),": \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:'graph LR\n C("Client") -- request --\x3e ACQ("\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \n size = accept-count") --\x3e TCQ("Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\n size = max-connections") --\x3e TP("Thread Pool\n size = threads.max")'}),"\n",(0,r.jsx)(n.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2616/",children:"RFC 2616"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag",children:"ETag, mdn"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://tomcat.apache.org/tomcat-8.5-doc/config/http.html",children:"Apache Tomcat 8 Configuration Reference"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://bcho.tistory.com/788",children:"Apache Tomcat Tuning, Terry Cho"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev-ws.tistory.com/96",children:"maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30"})]})]})}function h(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),c=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=c(t),h=o,m=p["".concat(l,".").concat(h)]||p[h]||u[h]||a;return t?r.createElement(m,i(i({ref:n},d),{},{components:t})):r.createElement(m,i({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>i});t(67294);var r=t(86010);const o={tabItem:"tabItem_Ymn6"};var a=t(85893);function i(e){let{children:n,hidden:t,className:i}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.Z)(o.tabItem,i),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>S});var r=t(67294),o=t(86010),a=t(12466),i=t(16550),s=t(20469),l=t(91980),c=t(67392),u=t(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:o}}=e;return{value:n,label:t,attributes:r,default:o}}))}(t);return function(e){const n=(0,c.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const o=(0,i.k6)(),a=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(o.location.search);n.set(a,e),o.replace({...o.location,search:n.toString()})}),[a,o])]}function g(e){const{defaultValue:n,queryString:t=!1,groupId:o}=e,a=p(e),[i,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[c,d]=m({queryString:t,groupId:o}),[g,x]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[o,a]=(0,u.Nk)(t);return[o,(0,r.useCallback)((e=>{t&&a.set(e)}),[t,a])]}({groupId:o}),b=(()=>{const e=c??g;return h({value:e,tabValues:a})?e:null})();(0,s.Z)((()=>{b&&l(b)}),[b]);return{selectedValue:i,selectValue:(0,r.useCallback)((e=>{if(!h({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),x(e)}),[d,x,a]),tabValues:a}}var x=t(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var f=t(85893);function j(e){let{className:n,block:t,selectedValue:r,selectValue:i,tabValues:s}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,a.o5)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),o=s[t].value;o!==r&&(c(n),i(o))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,f.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":t},n),children:s.map((e=>{let{value:n,label:t,attributes:a}=e;return(0,f.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...a,className:(0,o.Z)("tabs__item",b.tabItem,a?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function v(e){let{lazy:n,children:t,selectedValue:o}=e;const a=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===o));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,f.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==o})))})}function C(e){const n=g(e);return(0,f.jsxs)("div",{className:(0,o.Z)("tabs-container",b.tabList),children:[(0,f.jsx)(j,{...e,...n}),(0,f.jsx)(v,{...e,...n})]})}function S(e){const n=(0,x.Z)();return(0,f.jsx)(C,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2939],{76306:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var r=t(85893),o=t(3905),a=t(74866),i=t(85162);const s={title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},l=void 0,c={permalink:"/tomcat-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1, 2\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-http/pull/302",date:"2023-09-11T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:12.345,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"},nextItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"}},u={authorsImageUrls:[]},d=[{value:"\ud1b0\ucea3 \uad6c\ud604",id:"\ud1b0\ucea3-\uad6c\ud604",level:3},{value:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",level:3},{value:"\ucf54\ub4dc \ub9ac\ubdf0",id:"\ucf54\ub4dc-\ub9ac\ubdf0",level:3},{value:"SessionConfig",id:"sessionconfig",level:3},{value:"HTTP \uc218\uc5c5",id:"http-\uc218\uc5c5",level:3},{value:"Thread \uc218\uc5c5",id:"thread-\uc218\uc5c5",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",pre:"pre",...(0,o.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,r.jsxs)(n.p,{children:["1, 2\ub2e8\uacc4: ",(0,r.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-http/pull/302",children:"https://github.com/woowacourse/jwp-dashboard-http/pull/302"}),(0,r.jsx)(n.br,{}),"\n","3, 4\ub2e8\uacc4: ",(0,r.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-http/pull/431",children:"https://github.com/woowacourse/jwp-dashboard-http/pull/431"})]})}),"\n",(0,r.jsx)(n.h3,{id:"\ud1b0\ucea3-\uad6c\ud604",children:"\ud1b0\ucea3 \uad6c\ud604"}),"\n",(0,r.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2616/",children:"RFC 2616"}),"\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",children:"\ub2e4\uc774\uc5b4\uadf8\ub7a8"}),"\n",(0,r.jsxs)(n.p,{children:["Catalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph coyote\n\t\tHP[Http11Processor] --\x3e A\n\t\tHP --\x3e HttpRequestParser\n\t\tHP --\x3e HttpResponseGenerator\n\t\tA[Adapter]\n end\n\n subgraph catalina\n\t\tRA[RequestAdapter] -.-> A\n\t\tAC[AbstractController] -.-> C[Controller]\n\t\tStaticController -.-> AC\n\t\tSM[SessionManger] -.-> Manager\n\t\tTC[Tomcat] --\x3e RA\n\t\tRA --\x3e C\n\t\tRA --\x3e Manager\n\t\tRA --\x3e RM\n\t\tRM[RequestMapper] --\x3e C\n end\n\n subgraph jwp\n\t\tLC[LoginController] -.-> AC\n\t\tApplication --\x3e TC\n end\n"}),"\n",(0,r.jsx)(n.h3,{id:"\ucf54\ub4dc-\ub9ac\ubdf0",children:"\ucf54\ub4dc \ub9ac\ubdf0"}),"\n",(0,r.jsxs)(n.p,{children:["\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"sessionconfig",children:"SessionConfig"}),"\n",(0,r.jsxs)(n.p,{children:["\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 ",(0,r.jsx)(n.a,{href:"https://github.com/apache/tomcat/pull/660",children:"\ucee8\ud2b8\ub9ac\ubdf0\ud2b8"}),"\ub97c \uc2dc\ub3c4\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n","\n","\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(i.Z,{value:"\uae30\uc874",label:"\uae30\uc874",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_COOKIE_NAME;\n }\n\n return result;\n}\n\npublic static String getSessionUriParamName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_PARAMETER_NAME;\n }\n\n return result;\n}\n\nprivate static String getConfiguredSessionCookieName(Context context) {\n\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc =\n context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n\n return null;\n}\n"})})}),(0,r.jsx)(i.Z,{value:"PR \uc694\uccad",label:"PR \uc694\uccad",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_COOKIE_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_PARAMETER_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n return defaultName;\n}\n"})})}),(0,r.jsx)(i.Z,{value:"\ucd5c\uc885",label:"\ucd5c\uc885",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n return defaultName;\n}\n"})})})]}),"\n",(0,r.jsx)(n.h3,{id:"http-\uc218\uc5c5",children:"HTTP \uc218\uc5c5"}),"\n",(0,r.jsxs)(n.p,{children:["\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","HTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yml",children:"server:\n compression:\n enabled: true\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 ",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/issues/21369",children:"issue"}),"\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network."}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Phil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4."}),"\n",(0,r.jsx)(n.admonition,{title:"ETag",type:"note",children:(0,r.jsxs)(n.p,{children:["ETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","MDN"]})}),"\n",(0,r.jsx)(n.h3,{id:"thread-\uc218\uc5c5",children:"Thread \uc218\uc5c5"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"threads.max"}),": Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"max-connections"}),": Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"accept-count"}),": \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:'graph LR\n C("Client") -- request --\x3e ACQ("\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \n size = accept-count") --\x3e TCQ("Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\n size = max-connections") --\x3e TP("Thread Pool\n size = threads.max")'}),"\n",(0,r.jsx)(n.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2616/",children:"RFC 2616"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag",children:"ETag, mdn"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://tomcat.apache.org/tomcat-8.5-doc/config/http.html",children:"Apache Tomcat 8 Configuration Reference"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://bcho.tistory.com/788",children:"Apache Tomcat Tuning, Terry Cho"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev-ws.tistory.com/96",children:"maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30"})]})]})}function h(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),c=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=c(t),h=o,m=p["".concat(l,".").concat(h)]||p[h]||u[h]||a;return t?r.createElement(m,i(i({ref:n},d),{},{components:t})):r.createElement(m,i({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>i});t(67294);var r=t(86010);const o={tabItem:"tabItem_Ymn6"};var a=t(85893);function i(e){let{children:n,hidden:t,className:i}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.Z)(o.tabItem,i),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>S});var r=t(67294),o=t(86010),a=t(12466),i=t(16550),s=t(20469),l=t(91980),c=t(67392),u=t(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:o}}=e;return{value:n,label:t,attributes:r,default:o}}))}(t);return function(e){const n=(0,c.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const o=(0,i.k6)(),a=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(o.location.search);n.set(a,e),o.replace({...o.location,search:n.toString()})}),[a,o])]}function g(e){const{defaultValue:n,queryString:t=!1,groupId:o}=e,a=p(e),[i,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[c,d]=m({queryString:t,groupId:o}),[g,x]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[o,a]=(0,u.Nk)(t);return[o,(0,r.useCallback)((e=>{t&&a.set(e)}),[t,a])]}({groupId:o}),b=(()=>{const e=c??g;return h({value:e,tabValues:a})?e:null})();(0,s.Z)((()=>{b&&l(b)}),[b]);return{selectedValue:i,selectValue:(0,r.useCallback)((e=>{if(!h({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),x(e)}),[d,x,a]),tabValues:a}}var x=t(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var f=t(85893);function j(e){let{className:n,block:t,selectedValue:r,selectValue:i,tabValues:s}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,a.o5)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),o=s[t].value;o!==r&&(c(n),i(o))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,f.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":t},n),children:s.map((e=>{let{value:n,label:t,attributes:a}=e;return(0,f.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...a,className:(0,o.Z)("tabs__item",b.tabItem,a?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function v(e){let{lazy:n,children:t,selectedValue:o}=e;const a=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===o));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,f.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==o})))})}function C(e){const n=g(e);return(0,f.jsxs)("div",{className:(0,o.Z)("tabs-container",b.tabList),children:[(0,f.jsx)(j,{...e,...n}),(0,f.jsx)(v,{...e,...n})]})}function S(e){const n=(0,x.Z)();return(0,f.jsx)(C,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file diff --git a/assets/js/92ade856.9c969003.js b/assets/js/92ade856.dd26f1be.js similarity index 99% rename from assets/js/92ade856.9c969003.js rename to assets/js/92ade856.dd26f1be.js index bf1f523e9..6f6ef1df8 100644 --- a/assets/js/92ade856.9c969003.js +++ b/assets/js/92ade856.dd26f1be.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1772],{31824:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>u,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>d});var a=r(85893),t=r(3905),i=r(74866),l=r(85162);const s={title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",slug:"db-replication",tags:["mysql","replication"]},c=void 0,o={permalink:"/db-replication",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",source:"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",description:"\ubcf5\uc81c(Replication)",date:"2023-08-22T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 22\uc77c",tags:[{label:"mysql",permalink:"/tags/mysql"},{label:"replication",permalink:"/tags/replication"}],readingTime:21,hasTruncateMarker:!1,authors:[],frontMatter:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",slug:"db-replication",tags:["mysql","replication"]},unlisted:!1,prevItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",permalink:"/woowacourse-level3-retrospective"}},u={authorsImageUrls:[]},d=[{value:"\ubcf5\uc81c(Replication)",id:"\ubcf5\uc81creplication",level:2},{value:"\ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720",id:"\ubcf5\uc81c\ub97c-\ud558\ub294-\uc774\uc720",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ud30c\uc77c-\uc704\uce58-\uae30\ubc18-\ubcf5\uc81c",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd\uc758-\ubb38\uc81c\uc810",level:3},{value:"\uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c",id:"\uae00\ub85c\ubc8c-\ud2b8\ub79c\uc7ad\uc158-\uc544\uc774\ub514gtid-\uae30\ubc18-\ubcf5\uc81c",level:3},{value:"\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0",id:"\ubcf5\uc81c-\ud1a0\ud3f4\ub85c\uc9c0",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd-replication-\uad6c\uc131\ud558\uae30",level:2},{value:"MySQL \ud658\uacbd \uad6c\uc131",id:"mysql-\ud658\uacbd-\uad6c\uc131",level:3},{value:"\ub3c4\ucee4 \uc2e4\ud589",id:"\ub3c4\ucee4-\uc2e4\ud589",level:3},{value:"replication slave \uad8c\ud55c \uc124\uc815",id:"replication-slave-\uad8c\ud55c-\uc124\uc815",level:3},{value:"SOURCE DB \uc815\ubcf4 \ud655\uc778",id:"source-db-\uc815\ubcf4-\ud655\uc778",level:3},{value:"SOURCE ip \uc8fc\uc18c \ud655\uc778",id:"source-ip-\uc8fc\uc18c-\ud655\uc778",level:3},{value:"replica mysql \uc811\uc18d",id:"replica-mysql-\uc811\uc18d",level:3},{value:"replica \uc124\uc815",id:"replica-\uc124\uc815",level:3},{value:"\uc124\uc815 \ud655\uc778",id:"\uc124\uc815-\ud655\uc778",level:3},{value:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30",id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8\ub85c-db-\uc811\uadfc\ud558\uae30",level:2},{value:"Environment \uc124\uc815",id:"environment-\uc124\uc815",level:3},{value:"DataSourceType \uc124\uc815",id:"datasourcetype-\uc124\uc815",level:3},{value:"AbstractRoutingDataSource \uc124\uc815",id:"abstractroutingdatasource-\uc124\uc815",level:3},{value:"DataSource \uc124\uc815",id:"datasource-\uc124\uc815",level:3},{value:"\ub3d9\uc791 \ud655\uc778",id:"\ub3d9\uc791-\ud655\uc778",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"\ubcf5\uc81creplication",children:"\ubcf5\uc81c(Replication)"}),"\n",(0,a.jsxs)(n.p,{children:["\ud55c \uc11c\ubc84\uc5d0\uc11c \ub2e4\ub978 \uc11c\ubc84\ub85c \ub370\uc774\ud130\ub97c \ub3d9\uae30\ud654\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc6d0\ubcf8 \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Primary \ub610\ub294 Source \ub77c\uace0 \ubd80\ub974\uace0, \ubcf5\uc81c\ub41c \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Secondary \ub610\ub294 Replica \ub77c\uace0 \ubd80\ub978\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ubcf5\uc81c\ub97c-\ud558\ub294-\uc774\uc720",children:"\ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"1. \uc2a4\ucf00\uc77c \uc544\uc6c3"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc0ac\uc6a9\uc790\uc758 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uac00\ud574\uc9c0\ub294 \ubd80\ud558\ub3c4 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc99d\uac00\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub97c \ucc98\ub9ac\ud558\uae30 \uc704\ud574 \ubcf5\uc81c\ub97c \ud1b5\ud55c \uc2a4\ucf00\uc77c \uc544\uc6c3\uc744 \uc801\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucffc\ub9ac\ub4e4\uc744 \uac01\uac01\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c \ubd84\uc0b0 \uc2dc\ud0ac \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"2. \ub370\uc774\ud130 \ubc31\uc5c5"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc2e4\uc81c \uc6b4\uc601\ub418\ub294 \uc11c\ube44\uc2a4\uac00 \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 DB\uc5d0\uc11c \ubc31\uc5c5\uc744 \uc9c4\ud589\ud558\ub294 \uacbd\uc6b0, \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc774 \uac00\uc9c0 \uc54a\ub3c4\ub85d \ubcf5\uc81c\ub97c \ud1b5\ud574 Replica \uc11c\ubc84\ub97c \uad6c\ucd95\ud558\uc5ec, Replica \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ub97c \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\uc73c\ub85c \uc601\ud5a5\uc744 \ucd5c\uc18c\ud654 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"3. \ub370\uc774\ud130 \ubd84\uc11d"})}),"\n",(0,a.jsxs)(n.p,{children:["\ubc31\uc5c5\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc7a1\ud558\uace0 \ubb34\uac70\uc6b4 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\uc758 \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc81c\ub97c \uc0ac\uc6a9\ud574 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"4. \ub370\uc774\ud130\uc758 \uc9c0\ub9ac\uc801 \ubd84\uc0b0"})}),"\n",(0,a.jsx)(n.p,{children:"\ube60\ub978 \uc751\ub2f5\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc11c\ubc84\uc5d0 \uac00\uae5d\uac8c \uc11c\ubc84\ub97c \uad6c\uc131\ud558\uac70\ub098, \uace0\uac00\uc6a9\uc131(High Availability)\uc744 \uc704\ud574\uc11c\ub3c4 \uc0ac\uc6a9\ub41c\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ud30c\uc77c-\uc704\uce58-\uae30\ubc18-\ubcf5\uc81c",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c"}),"\n",(0,a.jsxs)(n.p,{children:["MySQL \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub85c\uadf8 \ud30c\uc77c\uc744 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub77c\uace0 \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ud1b5\ud574 \ub370\uc774\ud130 \ubcc0\uacbd, \ud14c\uc774\ube14 \uad6c\uc870 \ubcc0\uacbd, \uacc4\uc815\uc774\ub098 \uad8c\ud55c \ubcc0\uacbd\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc800\uc7a5\ub41c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","MySQL\uc758 \ubcf5\uc81c\ub294 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. \uc774\ub97c Replica \uc11c\ubc84\ub85c \uc804\ub2ec\ud558\uace0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph Replica\n\t\tdirection TB\n\t\tIO[Replication I/O thread] -- save --\x3e RL[Relay Log]\n\t\tSQL[Replication SQL Thread] -- read --\x3e RL\n\tend\n\n\tsubgraph Source\n\t\tdirection TB\n\t\tBLD[Binary Log Dump Thread] -- Send Binary Log Dump--\x3e IO\n\tend\n"}),"\n",(0,a.jsx)(n.admonition,{title:"\uc2a4\ub808\ub4dc\ubcc4 \uc5ed\ud560",type:"note",children:(0,a.jsxs)(n.p,{children:["Binary Log Dump Thread: \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc758 \ub0b4\uc6a9\uc744 Replica \uc11c\ubc84\ub85c \uc804\ub2ec",(0,a.jsx)(n.br,{}),"\n","Replication I/O Thread: Binary \ub85c\uadf8 \uc774\ubca4\ud2b8\ub97c \uac00\uc838\uc640 \ub85c\uceec \uc11c\ubc84\uc758 \ud30c\uc77c(Relay Log)\ub85c \uc800\uc7a5",(0,a.jsx)(n.br,{}),"\n","Replication SQL Thread: \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc774\ubca4\ud2b8\ub97c \uc77d\uace0 \uc2e4\ud589"]})}),"\n",(0,a.jsx)(n.h3,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd\uc758-\ubb38\uc81c\uc810",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810"}),"\n",(0,a.jsxs)(n.p,{children:["\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc740 \uc11c\ubc84\uc5d0 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0 \ubcc0\uacbd\uc774 \uae4c\ub2e4\ub86d\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud1a0\ud3f4\ub85c\uc9c0\ub780 \ub124\ud2b8\uc6cc\ud06c\uc758 \uc694\uc18c\ub4e4\uc744 \ubb3c\ub9ac\uc801\uc73c\ub85c \uc5f0\uacb0\ud574 \ub193\uc740 \uac83, \ub610\ub294 \uadf8 \uc5f0\uacb0 \ubc29\uc2dd\uc744 \ub9d0\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph TD\n\tA[A binary-log:300] --\x3e B[B Binary-log:300]\n\tA[A binary-log:300] --\x3e C[C Binary-log:200]"}),"\n",(0,a.jsx)(n.p,{children:"\uc704\uc640 \uac19\uc774 Source \uc11c\ubc84, Replica 2\ub300\uac00 \uc874\uc7ac\ud558\uace0, C \uc11c\ubc84\uc5d0 \ubcf5\uc81c \uc9c0\uc5f0\uc774 \ub418\uc5c8\uc744 \ub54c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph TD\n\tA[A binary-log:300]\n\tB[B Binary-log:300] --\x3e C[C Binary-log:200 \ubb38\uc81c \ubc1c\uc0dd]"}),"\n",(0,a.jsxs)(n.p,{children:["A \uc11c\ubc84\uc5d0\uc11c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 B \uc11c\ubc84\ub97c Source \uc11c\ubc84\ub85c \uc2b9\uaca9\ud558\uace0, C\uc5d0\uac8c \uc870\ud68c \ucffc\ub9ac\ub97c \ubd84\uc0b0\uc2dc\ud0a8\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \uc5ec\uae30\uc11c C \uc11c\ubc84\uc5d0\ub294 A \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\uac00 \uc548\ub418\uc5c8\uc73c\ub2c8 \uc870\ud68c \uc2dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub4a4\ub2a6\uac8c B \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\ub97c \ud558\ub824\uace0 \ud574\ub3c4, \uc5b4\ub5a4 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8, \uc5b4\ub5a4 \uc704\uce58\uc640 \ub3d9\uae30\ud654\ud574\uc57c\ud558\ub294\uc9c0 \uc54c\uae30 \uc5b4\ub835\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\uae00\ub85c\ubc8c-\ud2b8\ub79c\uc7ad\uc158-\uc544\uc774\ub514gtid-\uae30\ubc18-\ubcf5\uc81c",children:"\uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c"}),"\n",(0,a.jsxs)(n.p,{children:["GTID \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ubc1c\uc0dd\ud55c \uc774\ubca4\ud2b8\uc5d0 \uace0\uc720\ud55c \uc2dd\ubcc4\uac12\uc744 \ubd80\uc5ec\ud55c\ub2e4\uba74, \ub3d9\uae30\ud654\uc5d0 \ub300\ud55c \ubb38\uc81c\ub97c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc704\uc758 \uc608\uc2dc\uc640 \uac19\uc774 \ubcf5\uc81c \uc9c0\uc5f0\uacfc \ud568\uaed8 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ud574\ub3c4 \ud2b9\uc815 GTID \ubd80\ud130 \ubcf5\uc81c\ub97c \uc7ac\uac1c\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,a.jsx)(n.admonition,{title:"GTID",type:"note",children:(0,a.jsxs)(n.p,{children:["\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\uc5d0 \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \uc11c\ubc84\uc5d0\uc11c \uace0\uc720\ud558\ub3c4\ub85d \uac01 \uc774\ubca4\ud2b8\uc5d0 \ubd80\uc5ec\ub41c \uc2dd\ubcc4\uac12",(0,a.jsx)(n.br,{}),"\n","[source_id]:[transaction_id]\ub85c \uad6c\uc131\ub418\uba70, source_id\ub294 \uc11c\ubc84\ub97c \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc774\uace0 transaction_id\ub294 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc73c\ub85c 1\uc529 \uc99d\uac00\ud558\ub294 \ud615\ud0dc\ub85c \ubc1c\uae09\ub41c\ub2e4."]})}),"\n",(0,a.jsx)(n.h3,{id:"\ubcf5\uc81c-\ud1a0\ud3f4\ub85c\uc9c0",children:"\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["\uac00\uc7a5 \uac04\ub2e8\ud55c \uad6c\uc131\uc73c\ub85c \uc81c\uc77c \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","replica \uc11c\ubc84\ub97c \uc77d\uae30 \uc804\uc6a9, \uc608\ube44 \uc11c\ubc84, \ubc31\uc5c5 \uc6a9\ub3c4\ub85c \ub9ce\uc774 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R\n S[Source] --\x3e R[Replica]"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uba40\ud2f0 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["2\uac1c\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\ub098\uc758 replica\ub294 \uc608\ube44 \uc6a9\ub3c4\ub85c \ub0a8\uaca8\ub450\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucd94\ud6c4\uc5d0 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 \uc608\ube44 \uc6a9\ub3c4\uc758 replica\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c \uc77d\uae30 \uc694\uccad\uc758 \ubd80\ud558 \ubd84\uc0b0\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R1\n S[Source] --\x3e R1[Replica1]\n S --\x3e R2[Replica2]"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uccb4\uc778 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["replica \uc11c\ubc84\uac00 \ub9ce\uc740 \uacbd\uc6b0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \uc804\ub2ec\ud558\ub294 \uc791\uc5c5 \uc790\uccb4\uac00 \ubd80\ud558\uac00 \ub420 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c 1:M",":M"," \uad6c\uc870\ub85c \uccb4\uc778 \ubcf5\uc81c \uad6c\uc131\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R1\n S[Source] --\x3e R1[Replica1]\n S --\x3e R2[Replica2]\n S --\x3e R3[Replica3]\n\n R3 --\x3e R3-1[Replica 3-1]\n R3 --\x3e R3-2[Replica 3-2]\n\n B[Batch Server] --\x3e R3-2"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\ub4c0\uc5bc \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["2\uac1c\uc758 MySQL \uc11c\ubc84 \ubaa8\ub450 \uc77d\uae30\uc640 \uc4f0\uae30\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d \ud558\ub294 \uad6c\uc131\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uac01 \uc11c\ubc84\uc5d0\uc11c \ubcc0\uacbd\ub41c \ub370\uc774\ud130\ub294 \ub2e4\ub978 \uc11c\ubc84\uc5d0 \ubc18\uc601\ub41c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ubaa9\uc801\uc5d0 \ub530\ub77c ACTIVE-ACTIVE \ud615\ud0dc \ub610\ub294 ACTIVE-PASSIVE \ud615\ud0dc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","ACTIVE-PASSIVE \ud615\ud0dc\uc778 \uacbd\uc6b0 \uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131\uacfc \ub3d9\uc77c\ud574\ubcf4\uc774\uc9c0\ub9cc, ACTIVE \uc11c\ubc84\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uba74 \uc124\uc815\uc758 \ubcc0\uacbd\uc5c6\uc774 PASSIVE \uc11c\ubc84\ub85c \uc4f0\uae30 \uc791\uc5c5\uc744 \uc804\ud658\ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc774 \uc7a5\uc810\uc774\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR1\n W -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR2\n SR1[Source/Replica 1] --\x3e SR2[Source/Replica 2]"}),"\n",(0,a.jsx)(n.admonition,{title:"ACTIVE-ACTIVE, ACTIVE-PASSIVE",type:"note",children:(0,a.jsxs)(n.p,{children:["ACTIVE-ACTIVE: 2\uac1c\uc758 \uc11c\ubc84 \ubaa8\ub450 \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc",(0,a.jsx)(n.br,{}),"\n","ACTIVE-PASSIVE: \ud558\ub098\uc758 \uc11c\ubc84\uc5d0\uc11c\ub9cc \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc"]})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uba40\ud2f0 \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc5ec\ub7ec\uac1c\uc758 source \uc11c\ubc84\uc640 \ud558\ub098\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \uad6c\uc131\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub294 source \uc11c\ubc84\uc758 \ub370\uc774\ud130\ub97c \ud55c \uacf3\uc5d0 \ubc31\uc5c5\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9, \uc5ec\ub7ec \uc11c\ubc84\uc5d0 \uc874\uc7ac\ud558\ub294 \ub370\uc774\ud130\ub97c \ud1b5\ud569, \uc0e4\ub529\ub418\uc5b4\uc788\ub294 \ud14c\uc774\ube14 \ub370\uc774\ud130\ub97c \ud1b5\ud569\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n S1[Source 1] --\x3e R[Replica]\n S2[Source 2] --\x3e R"}),"\n",(0,a.jsx)(n.h2,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd-replication-\uad6c\uc131\ud558\uae30",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30"}),"\n",(0,a.jsxs)(n.p,{children:["mysql 2\ub300\ub97c \uc774\uc6a9\ud558\uc5ec replication\uc744 \uad6c\uc131\ud558\uace0, spring boot application\uc73c\ub85c source, replica \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\ubcf4\ub294 \uc608\uc81c\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://github.com/bbiac/db-replication",children:"https://github.com/bbiac/db-replication"})]}),"\n",(0,a.jsx)(n.h3,{id:"mysql-\ud658\uacbd-\uad6c\uc131",children:"MySQL \ud658\uacbd \uad6c\uc131"}),"\n",(0,a.jsxs)(n.p,{children:["MySQL \ubc84\uc804\uc740 8.1\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","13306, 13307 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud574\uc11c MySQL \uc11c\ubc84 2\ub300\ub97c \ub744\uc6e0\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub610\ud55c \uc0ac\uc2e4 IP \ub300\uc5ed\uc73c\ub85c \ud1b5\uc2e0\ud560 \uc218 \uc788\ub3c4\ub85d \ucee4\uc2a4\ud140 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yml",children:"version: '3.8'\n\nservices:\n source:\n platform: linux/x86_64\n image: mysql:latest\n restart: always\n container_name: mysql-source\n environment:\n TZ: 'Asia/Seoul'\n MYSQL_DATABASE: 'db'\n MYSQL_USER: 'user'\n MYSQL_PASSWORD: 'password'\n MYSQL_ROOT_PASSWORD: 'password'\n ports:\n - \"13306:3306\"\n volumes:\n - db-source:/var/lib/mysql\n - db-source:/var/lib/mysql-files\n - ./docker/source.cnf:/etc/mysql/my.cnf\n networks:\n - mysql_network\n\n replica:\n platform: linux/x86_64\n image: mysql:latest\n restart: always\n container_name: mysql-replica\n environment:\n TZ: 'Asia/Seoul'\n MYSQL_DATABASE: 'db'\n MYSQL_USER: 'user'\n MYSQL_PASSWORD: 'password'\n MYSQL_ROOT_PASSWORD: 'password'\n ports:\n - \"13307:3306\"\n volumes:\n - db-replica:/var/lib/mysql\n - db-replica:/var/lib/mysql-files\n - ./docker/replica.cnf:/etc/mysql/my.cnf\n networks:\n - mysql_network\n\nvolumes:\n db-source:\n db-replica:\n\nnetworks:\n mysql_network:\n driver: bridge\n"})}),"\n",(0,a.jsx)(n.p,{children:"\ub610\ud55c source, replica \uac01\uac01 \ub2e4\uc74c\uacfc \uac19\uc774 db \uc124\uc815\uc744 \ud588\ub2e4."}),"\n",(0,a.jsxs)(n.table,{children:[(0,a.jsx)(n.thead,{children:(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.th,{children:"\uc124\uc815"}),(0,a.jsx)(n.th,{children:"\uc124\uba85"})]})}),(0,a.jsxs)(n.tbody,{children:[(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"server_id"}),(0,a.jsx)(n.td,{children:"\uac01\uac01\uc758 mysql \ub9c8\ub2e4 \uace0\uc720\ud55c \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"log_bin"}),(0,a.jsx)(n.td,{children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815\uc73c\ub85c \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 /var/lib/mysql \uc544\ub798 \ud574\ub2f9 log_bin\uc5d0 \uc124\uc815\ub41c \uac12\uc73c\ub85c \ub85c\uadf8\uac00 \uc0dd\uc131\ub41c\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"sync_binlog"}),(0,a.jsx)(n.td,{children:"N\uac1c\uc758 \ud2b8\ub79c\uc7ad\uc158 \ub2f9 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ub514\uc2a4\ud06c\uc640 \ub3d9\uae30\ud654 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d \ud55c\ub2e4.\xa01\uc740 \uae30\ubcf8\uac12\uc73c\ub85c \uc548\uc815\uc801\uc774\uc9c0\ub9cc, \uac00\uc7a5 \ub290\ub9ac\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"relay_log"}),(0,a.jsx)(n.td,{children:"\ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"relay_log_purge"}),(0,a.jsx)(n.td,{children:"\ud544\uc694 \uc5c6\ub294 \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \uc0ad\uc81c\ud558\ub294 \uc635\uc158"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"read_only"}),(0,a.jsx)(n.td,{children:"\uc77d\uae30 \uc804\uc6a9 \uc124\uc815"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"log_replica_updates"}),(0,a.jsx)(n.td,{children:"Replication SQL Thread\ub85c \uc778\ud574 \uc2e4\ud589\ub418\ub294 \uc815\ubcf4\ub97c \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc5d0 \uae30\ub85d \ucd94\ud6c4\uc5d0 \uc18c\uc2a4 \uc11c\ubc84\ub85c \uc2b9\uaca9\ub418\ub294 \uacbd\uc6b0\ub97c \uace0\ub824\ud558\uba74 \uc124\uc815\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."})]})]})]}),"\n","\n","\n",(0,a.jsxs)(i.Z,{children:[(0,a.jsx)(l.Z,{value:"Source",label:"Source",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-cnf",metastring:'title="/docker/source.cnf"',children:"[mysqld]\nserver_id=1\nlog_bin=mysql-bin\nsync_binlog=1\n"})})}),(0,a.jsx)(l.Z,{value:"Replica",label:"Replica",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-cnf",metastring:'title="/docker/replica.cnf"',children:"[mysqld]\nserver_id=2\nrelay_log=mysql-relay-bin\nrelay_log_purge=ON\nread_only\nlog_replica_updates\n"})})})]}),"\n",(0,a.jsx)(n.h3,{id:"\ub3c4\ucee4-\uc2e4\ud589",children:"\ub3c4\ucee4 \uc2e4\ud589"}),"\n",(0,a.jsxs)(n.p,{children:["docker-compose up \uba85\ub839\uc5b4\ub85c docker-compose \uc124\uc815\uc73c\ub85c docker\ub97c \ub744\uc6b4\ub2e4.",(0,a.jsx)(n.br,{}),"\n","-d \uc635\uc158\uc744 \ubd99\uc774\uba74 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ubaa8\ub4dc\ub85c \uc2e4\ud589\ub41c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"docker-compose up -d\n"})}),"\n",(0,a.jsx)(n.h3,{id:"replication-slave-\uad8c\ud55c-\uc124\uc815",children:"replication slave \uad8c\ud55c \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["REPLICATION SLAVE \uad8c\ud55c\uc774 \uc124\uc815\ub418\uc5b4 \uc788\uc5b4\uc57c replica \uc11c\ubc84\uc5d0\uc11c source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec \ub85c\uadf8\ub97c \uc77d\uc5b4\uc62c \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec user \uacc4\uc815\uc5d0 \ud574\ub2f9 \uad8c\ud55c\uc744 \uc124\uc815\ud574\uc900\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:"SOURCE \uc811\uc18d"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker exec -it mysql-source mysql -u root -p\n"})}),"\n",(0,a.jsx)(n.p,{children:"user \uacc4\uc815\uc5d0 REPLICATION SLAVE \uad8c\ud55c \ucd94\uac00"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"GRANT REPLICATION SLAVE ON *.* TO 'user'@'%';\nFLUSH PRIVILEGES;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"source-db-\uc815\ubcf4-\ud655\uc778",children:"SOURCE DB \uc815\ubcf4 \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["replica \uc124\uc815\uc5d0 \ud544\uc694\ud55c source db\uc758 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c\uba85\uacfc Position\uc744 \ud655\uc778\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","Position \uac12\uc740 \uc2e4\uc81c \ud30c\uc77c\uc758 \ubc14\uc774\ud2b8 \uc218\ub97c \uc758\ubbf8\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud655\uc778\ud55c File(SOURCE_LOG_FILE)\uacfc Position(SOURCE_LOG_POS) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"SHOW MASTER STATUS;\n\n+------------------+----------+--------------+------------------+-------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |\n+------------------+----------+--------------+------------------+-------------------+\n| mysql-bin.000003 | 1082 | | | |\n+------------------+----------+--------------+------------------+-------------------+\n"})}),"\n",(0,a.jsx)(n.h3,{id:"source-ip-\uc8fc\uc18c-\ud655\uc778",children:"SOURCE ip \uc8fc\uc18c \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["docker inspect -f \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ud574\ub2f9 \ucee8\ud14c\uc774\ub108\uc758 \uc138\ubd80 \uc815\ubcf4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud574 docker-compose \ud30c\uc77c\uc5d0 \uc124\uc815\ud574\ub454 mysql_network\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc124 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'docker inspect -f "{{with index .NetworkSettings.Networks \\"db-replication_mysql_network\\"}}{{.IPAddress}}{{end}}" mysql-source\n'})}),"\n",(0,a.jsxs)(n.p,{children:["ip \uc8fc\uc18c\uac00 \ub098\uc624\uc9c0 \uc54a\ub294 \uacbd\uc6b0 docker inspect mysql-source\ub85c \ud655\uc778\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud655\uc778\ud55c IP\uc8fc\uc18c(SOURCE_HOST) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"replica-mysql-\uc811\uc18d",children:"replica mysql \uc811\uc18d"}),"\n",(0,a.jsx)(n.p,{children:"source db\uc5d0 \uc811\uc18d\ud588\ub358 \ubc29\ubc95\uacfc \ub3d9\uc77c\ud558\uac8c replica db\uc5d0 \uc811\uc18d\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker exec -it mysql-replica mysql -u root -p\n"})}),"\n",(0,a.jsx)(n.h3,{id:"replica-\uc124\uc815",children:"replica \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\uc774\uc804\uc5d0 source db\uc5d0\uc11c \uc5bb\uc5c8\ub358 \uc815\ubcf4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc5ec replica \uc124\uc815\uc744 \uc9c4\ud589\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc2e4\uc81c DB \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc73c\ub85c source DB\uc758 \ud30c\uc77c\uc744 \ubcf5\uc81c\ud574\uc57c\ud558\uc9c0\ub9cc \ud604\uc7ac \ubcf5\uc81c\ud560 \ub370\uc774\ud130\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ubd80\ubd84\uc740 \uc0dd\ub7b5\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","SOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS \ub97c \uc801\uc808\ud788 \ubcc0\uacbd\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"STOP REPLICA;\n\nCHANGE REPLICATION SOURCE TO \nSOURCE_HOST='172.29.0.2', \nSOURCE_USER='user', \nSOURCE_PASSWORD='password', \nSOURCE_LOG_FILE='mysql-bin.000001', \nSOURCE_LOG_POS=0, \nGET_SOURCE_PUBLIC_KEY=1;\n\nSTART REPLICA;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"\uc124\uc815-\ud655\uc778",children:"\uc124\uc815 \ud655\uc778"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"SHOW REPLICA STATUS;\n\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n| Waiting for source to send event | 172.25.0.3 | user | 3306 | 60 | mysql-bin.000003 | 1082 | mysql-relay-bin.000002 | 868 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 1082 | 1078 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | | | 1 | |\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n"})}),"\n",(0,a.jsx)(n.p,{children:"Replica_IO_Running, Replica_SQL_Running \uac12\uc774 YES\ub77c\uba74 \uc815\uc0c1\uc801\uc73c\ub85c replication \uad6c\uc131\uc774 \uc644\ub8cc\ub41c \uac83\uc774\ub2e4."}),"\n",(0,a.jsxs)(n.p,{children:["\uc124\uc815\uc744 \ub9c8\uce5c \ud6c4 source db\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 create table \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","replica db\uc5d0 \ub3d9\uc77c\ud55c member table\uc774 \uc0dd\uc131\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE member\n(\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\n name VARCHAR(255)\n);\n"})}),"\n",(0,a.jsx)(n.h2,{id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8\ub85c-db-\uc811\uadfc\ud558\uae30",children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30"}),"\n",(0,a.jsx)(n.p,{children:"\uc77c\ubc18\uc801\uc778 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 source, \uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158\uc778 \uacbd\uc6b0 replica\ub85c \uc694\uccad\uc774 \uac00\ub3c4\ub85d \uad6c\uc131\ud574\ubcf4\uc790."}),"\n",(0,a.jsx)(n.h3,{id:"environment-\uc124\uc815",children:"Environment \uc124\uc815"}),"\n",(0,a.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 source, replica\ub85c \uad6c\ubd84\ud558\uc5ec \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yml",metastring:'title="application.yml"',children:"spring:\n datasource:\n source:\n username: user\n password: password\n driver-class-name: com.mysql.cj.jdbc.Driver\n jdbc-url: jdbc:mysql://localhost:13306/db\n replica:\n username: user\n password: password\n driver-class-name: com.mysql.cj.jdbc.Driver\n jdbc-url: jdbc:mysql://localhost:13307/db\n"})}),"\n",(0,a.jsx)(n.h3,{id:"datasourcetype-\uc124\uc815",children:"DataSourceType \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\ub2e8\uc21c \ubb38\uc790\uc5f4\ub85c\ub3c4 \uad6c\ubd84\ud560 \uc218 \uc788\uc9c0\ub9cc, enum\uc744 \uc774\uc6a9\ud574\uc11c \ud2b8\ub79c\uc7ad\uc158\uc744 \uad6c\ubd84\ud558\ub3c4\ub85d \uc0dd\uc131\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","Key\ub294 \ucd94\ud6c4\uc5d0 \ube48 \uc124\uc815\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="DataSourceType"',children:'public enum DataSourceType {\n SOURCE(SOURCE_NAME),\n REPLICA(REPLICA_NAME),\n ;\n\n private final String key;\n\n DataSourceType(String key) {\n this.key = key;\n }\n\n public static class Key {\n public static final String ROUTING_NAME = "ROUTING";\n public static final String SOURCE_NAME = "SOURCE";\n public static final String REPLICA_NAME = "REPLICA";\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"abstractroutingdatasource-\uc124\uc815",children:"AbstractRoutingDataSource \uc124\uc815"}),"\n",(0,a.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1\uc774 \uc9c0\uc6d0\ud574\uc8fc\ub294 AbstractRoutingDataSource\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSource\ub97c \ud5a5\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsxs)(n.p,{children:["\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub294 ",(0,a.jsx)(n.code,{children:"Map"}),"\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\uc744 \ubc1b\uc544 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"setDefaultTargetDataSource: \uae30\ubcf8 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"setTargetDataSources: \ub9f5 \ud615\ud0dc\ub85c \ubc1b\uc740 \ub370\uc774\ud130 \uc18c\uc2a4 \uac12\ub4e4\uc744 \uc124\uc815\ud55c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"determineCurrentLookupKey\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \ud2b8\ub79c\uc7ad\uc158\uc774 \uc77d\uae30 \uc804\uc6a9\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uace0, \ubc18\ud658\ud55c \uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ub370\uc774\ud130 \uc18c\uc2a4\uac00 \uc0ac\uc6a9\ub41c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="RoutingDataSource"',children:'public class RoutingDataSource extends AbstractRoutingDataSource {\n\n private final Logger log = LoggerFactory.getLogger(getClass());\n\n public static RoutingDataSource from(Map dataSources) {\n RoutingDataSource routingDataSource = new RoutingDataSource();\n routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));\n routingDataSource.setTargetDataSources(dataSources);\n return routingDataSource;\n }\n\n @Override\n protected Object determineCurrentLookupKey() {\n boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();\n\n if (readOnly) {\n log.info("readOnly = true, request to replica");\n return DataSourceType.REPLICA;\n }\n log.info("readOnly = false, request to source");\n return DataSourceType.SOURCE;\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"datasource-\uc124\uc815",children:"DataSource \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c\ubd80\ud130 \uc21c\uc11c\ub300\ub85c Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy \uc124\uc815\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc2a4\ud504\ub9c1\uc740 \ud2b8\ub79c\uc7ad\uc158 \uc2dc\uc791\uc2dc\uc5d0 \ucee4\ub125\uc158\uc758 \uc0ac\uc6a9\uc5ec\ubd80\uc640 \uc0c1\uad00\uc5c6\uc774 \ucee4\ub125\uc158\uc744 \ud655\ubcf4\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c readOnly \ud2b8\ub79c\uc7ad\uc158\uc774 \uc124\uc815\ub41c \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ubbf8\ub9ac \ud655\ubcf4\ub41c \ucee4\ub125\uc158\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 replica db\ub85c \uc694\uccad\uc744 \ud558\uc9c0 \uc54a\uace0 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4."]}),"\n",(0,a.jsxs)(n.p,{children:["TransactionSynchronizationManager.isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc \ud638\ucd9c \uc2dc currentTransactionReadOnly\ub77c\ub294 ",(0,a.jsx)(n.code,{children:"ThreadLocal"}),"\uc5d0 \uc124\uc815\ub41c \uac12\uc744 \ubc18\ud658\ud558\ub294\ub370 readOnly \uc124\uc815\uc774 \ub418\uba74 \uc774 \uac12\uc744 true\ub85c \uc124\uc815\ud55c\ub2e4. \ud558\uc9c0\ub9cc determineCurrentLookupKey\ub97c \ud638\ucd9c\ud558\uc5ec key \uac12\uc744 \uac00\uc838\uc624\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc774\ud6c4\uc5d0 \uc124\uc815\ub418\uae30 \ub54c\ubb38\uc5d0 determineCurrentLookupKey \uba54\uc11c\ub4dc\uc5d0\uc11c \ud56d\uc0c1 DataSourceType.SOURCE\uac00 \ubc18\ud658\ub418\uc5b4 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:"LazyConnectionDataSourceProxy\ub97c \uc124\uc815\ud558\ub294 \uacbd\uc6b0 \uc2e4\uc81c DataSource\ub97c \uc0ac\uc6a9\ud558\ub294 \uc2dc\uc810\uc5d0 \ucee4\ub125\uc158\uc744 \ud68d\ub4dd\ud574\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc124\uc815\ud55c\ub300\ub85c replica db\ub85c \uc870\ud68c \uc694\uccad\uc744 \ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="DataSourceConfiguration"',children:'@Configuration\npublic class DataSourceConfiguration {\n\n @Bean\n @Qualifier(SOURCE_NAME)\n @ConfigurationProperties(prefix = "spring.datasource.source")\n public DataSource sourceDataSource() {\n return DataSourceBuilder.create().build();\n }\n\n @Bean\n @Qualifier(REPLICA_NAME)\n @ConfigurationProperties(prefix = "spring.datasource.replica")\n public DataSource replicaDataSource() {\n return DataSourceBuilder.create().build();\n }\n\n @Bean\n @Qualifier(ROUTING_NAME)\n public DataSource routingDataSource(\n @Qualifier(SOURCE_NAME) DataSource sourceDataSource,\n @Qualifier(REPLICA_NAME) DataSource replicaDataSource\n ) {\n return RoutingDataSource.from(Map.of(\n DataSourceType.SOURCE, sourceDataSource,\n DataSourceType.REPLICA, replicaDataSource\n ));\n }\n\n @Bean\n @Primary\n public DataSource dataSource(\n @Qualifier(ROUTING_NAME) DataSource routingDataSource\n ) {\n return new LazyConnectionDataSourceProxy(routingDataSource);\n }\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"\ucd5c\uc885\uc801\uc73c\ub85c DataSource \ube48\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ud615\ud0dc\uac00 \ub41c\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n DSP[LazyConnectionDataSourceProxy] --\x3e RDS[RoutingDataSource]\n\tRDS --\x3e S[SourceDataSource]\n\tRDS --\x3e R[ReplicaDataSource]"}),"\n",(0,a.jsx)(n.h3,{id:"\ub3d9\uc791-\ud655\uc778",children:"\ub3d9\uc791 \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["\uac04\ub2e8\ud558\uac8c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\uc11c \uc124\uc815\ud55c\ub300\ub85c \ub3d9\uc791\uc774 \ub418\ub294\uc9c0 \ud655\uc778\ud574\ubcf4\uc558\ub2e4.",(0,a.jsx)(n.br,{}),"\n","save \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 ",(0,a.jsx)(n.code,{children:"@Transactional"}),", findById \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 ",(0,a.jsx)(n.code,{children:"@Transactional(readOnly = true)"}),"\uac00 \uc124\uc815\ub418\uc5b4\uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub85c\uadf8\ub97c \ud1b5\ud574 save\uc758 \uacbd\uc6b0 source db\ub85c findById\uc758 \uacbd\uc6b0 replica db\ub85c \uc694\uccad\uc744 \ud558\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="MemberServiceTest"',children:'@SpringBootTest\nclass MemberServiceTest {\n\n @Autowired\n private MemberService memberService;\n\n @Test\n void \uc0ac\uc6a9\uc790\ub97c_\uc800\uc7a5\ud55c\ub2e4() {\n // RoutingDataSource log: readOnly = false\n memberService.save("bbiac");\n }\n\n @Test\n void \uc0ac\uc6a9\uc790\ub97c_\uc870\ud68c\ud55c\ub2e4() {\n // RoutingDataSource log: readOnly = true\n assertThatThrownBy(() -> memberService.findById(MAX_VALUE))\n .isInstanceOf(NoSuchElementException.class);\n }\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"DB\uc5d0\uc11c\ub294 \ud655\uc778\ud558\ub824\uba74 root \uacc4\uc815\uc73c\ub85c \uc811\uc18d\ud55c \ud6c4 general log\ub97c \ud65c\uc131\ud654 \uc2dc\ud0a8\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SET GLOBAL log_output = 'table';\nSET GLOBAL general_log = 1;\n"})}),"\n",(0,a.jsxs)(n.p,{children:["general log\ub97c \ud65c\uc131\ud654 \ud55c \ud6c4 \uc77d\uae30 \uc804\uc6a9 \uba54\uc11c\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","server_id, \uc2e4\ud589\ud55c \ucffc\ub9ac\ubb38\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like '%select%';\n\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n| user_host | thread_id | server_id | convert(argument using utf8) |\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n| user[user] @ [172.25.0.1] | 277 | 2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n"})}),"\n",(0,a.jsx)(n.p,{children:"\ud655\uc778 \ud6c4 general log\ub97c \ube44\ud65c\uc131\ud654 \ud55c \ud6c4 \ube44\ud65c\uc131\ud654 \ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SET GLOBAL general_log = 0;\nSHOW VARIABLES LIKE '%general%';\n\n+------------------+---------------------------------+\n| Variable_name | Value |\n+------------------+---------------------------------+\n| general_log | OFF |\n| general_log_file | /var/lib/mysql/4b6b9db98290.log |\n+------------------+---------------------------------+\n"})}),"\n",(0,a.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(n.p,{children:["16\uc7a5 \ubcf5\uc81c, Real MySQL 8.0 - \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.1/en/replication.html",children:"Replication, MySQL Docs"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://huisam.tistory.com/entry/mysql-replication",children:"MySql - Master Slave Replication \uad6c\uc870 \ub9cc\ub4e4\uc5b4\ubcf4\uae30"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://cheese10yun.github.io/spring-transaction/",children:"Spring \ub808\ud50c\ub9ac\ucf00\uc774\uc158 \ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac \ubc29\uc2dd"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://github.com/kwon37xi/replication-datasource",children:"replication-datasource"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/pulse/simplified-guide-mysql-replication-docker-compose-rakesh-shekhawat/",children:"Simplified Guide to MySQL Replication with Docker Compose"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://www.daleseo.com/dockerfile/",children:"Dockerfile\uc5d0\uc11c \uc790\uc8fc \uc4f0\uc774\ub294 \uba85\ub839\uc5b4"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.1/en/change-replication-source-to.html",children:"CHANGE REPLICATION SOURCE TO Statement"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://kwonnam.pe.kr/wiki/springframework/lazyconnectiondatasourceproxy",children:"LazyConnectionDataSourceProxy"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://hudi.blog/database-replication-with-springboot-and-mysql/",children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ub808\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ud1b5\ud55c \ucffc\ub9ac \uc131\ub2a5 \uac1c\uc120 (feat. Mysql, SpringBoot)"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://chagokx2.tistory.com/100",children:"\ubd80\ud558 \ubd84\uc0b0\uc744 \uc704\ud55c MySQL Replication \uad6c\uc131 \ubc0f \ucffc\ub9ac \uc694\uccad \ubd84\uae30"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.docker.com/get-started/08_using_compose/",children:"Use Docker Compose, Docker"})]})]})}function h(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var a=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,a)}return r}function l(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var c=a.createContext({}),o=function(e){var n=a.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):l(l({},n),e)),r},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var r=e.components,t=e.mdxType,i=e.originalType,c=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=o(r),h=t,S=p["".concat(c,".").concat(h)]||p[h]||u[h]||i;return r?a.createElement(S,l(l({ref:n},d),{},{components:r})):a.createElement(S,l({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,r)=>{r.d(n,{Z:()=>l});r(67294);var a=r(86010);const t={tabItem:"tabItem_Ymn6"};var i=r(85893);function l(e){let{children:n,hidden:r,className:l}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,a.Z)(t.tabItem,l),hidden:r,children:n})}},74866:(e,n,r)=>{r.d(n,{Z:()=>R});var a=r(67294),t=r(86010),i=r(12466),l=r(16550),s=r(20469),c=r(91980),o=r(67392),u=r(50012);function d(e){return a.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:r}=e;return(0,a.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:r,attributes:a,default:t}}=e;return{value:n,label:r,attributes:a,default:t}}))}(r);return function(e){const n=(0,o.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,r])}function h(e){let{value:n,tabValues:r}=e;return r.some((e=>e.value===n))}function S(e){let{queryString:n=!1,groupId:r}=e;const t=(0,l.k6)(),i=function(e){let{queryString:n=!1,groupId:r}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!r)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return r??null}({queryString:n,groupId:r});return[(0,c._X)(i),(0,a.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(t.location.search);n.set(i,e),t.replace({...t.location,search:n.toString()})}),[i,t])]}function x(e){const{defaultValue:n,queryString:r=!1,groupId:t}=e,i=p(e),[l,c]=(0,a.useState)((()=>function(e){let{defaultValue:n,tabValues:r}=e;if(0===r.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:r}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${r.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const a=r.find((e=>e.default))??r[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:n,tabValues:i}))),[o,d]=S({queryString:r,groupId:t}),[x,m]=function(e){let{groupId:n}=e;const r=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,i]=(0,u.Nk)(r);return[t,(0,a.useCallback)((e=>{r&&i.set(e)}),[r,i])]}({groupId:t}),b=(()=>{const e=o??x;return h({value:e,tabValues:i})?e:null})();(0,s.Z)((()=>{b&&c(b)}),[b]);return{selectedValue:l,selectValue:(0,a.useCallback)((e=>{if(!h({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),d(e),m(e)}),[d,m,i]),tabValues:i}}var m=r(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var j=r(85893);function g(e){let{className:n,block:r,selectedValue:a,selectValue:l,tabValues:s}=e;const c=[],{blockElementScrollPositionUntilNextRender:o}=(0,i.o5)(),u=e=>{const n=e.currentTarget,r=c.indexOf(n),t=s[r].value;t!==a&&(o(n),l(t))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const r=c.indexOf(e.currentTarget)+1;n=c[r]??c[0];break}case"ArrowLeft":{const r=c.indexOf(e.currentTarget)-1;n=c[r]??c[c.length-1];break}}n?.focus()};return(0,j.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.Z)("tabs",{"tabs--block":r},n),children:s.map((e=>{let{value:n,label:r,attributes:i}=e;return(0,j.jsx)("li",{role:"tab",tabIndex:a===n?0:-1,"aria-selected":a===n,ref:e=>c.push(e),onKeyDown:d,onClick:u,...i,className:(0,t.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":a===n}),children:r??n},n)}))})}function _(e){let{lazy:n,children:r,selectedValue:t}=e;const i=(Array.isArray(r)?r:[r]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===t));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return(0,j.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function y(e){const n=x(e);return(0,j.jsxs)("div",{className:(0,t.Z)("tabs-container",b.tabList),children:[(0,j.jsx)(g,{...e,...n}),(0,j.jsx)(_,{...e,...n})]})}function R(e){const n=(0,m.Z)();return(0,j.jsx)(y,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1772],{31824:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>u,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>d});var a=r(85893),t=r(3905),i=r(74866),l=r(85162);const s={title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",slug:"db-replication",tags:["mysql","replication"]},c=void 0,o={permalink:"/db-replication",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",source:"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",description:"\ubcf5\uc81c(Replication)",date:"2023-08-22T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 22\uc77c",tags:[{label:"mysql",permalink:"/tags/mysql"},{label:"replication",permalink:"/tags/replication"}],readingTime:21,hasTruncateMarker:!1,authors:[],frontMatter:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",slug:"db-replication",tags:["mysql","replication"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",permalink:"/woowacourse-level3-retrospective"},nextItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"}},u={authorsImageUrls:[]},d=[{value:"\ubcf5\uc81c(Replication)",id:"\ubcf5\uc81creplication",level:2},{value:"\ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720",id:"\ubcf5\uc81c\ub97c-\ud558\ub294-\uc774\uc720",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ud30c\uc77c-\uc704\uce58-\uae30\ubc18-\ubcf5\uc81c",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd\uc758-\ubb38\uc81c\uc810",level:3},{value:"\uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c",id:"\uae00\ub85c\ubc8c-\ud2b8\ub79c\uc7ad\uc158-\uc544\uc774\ub514gtid-\uae30\ubc18-\ubcf5\uc81c",level:3},{value:"\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0",id:"\ubcf5\uc81c-\ud1a0\ud3f4\ub85c\uc9c0",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd-replication-\uad6c\uc131\ud558\uae30",level:2},{value:"MySQL \ud658\uacbd \uad6c\uc131",id:"mysql-\ud658\uacbd-\uad6c\uc131",level:3},{value:"\ub3c4\ucee4 \uc2e4\ud589",id:"\ub3c4\ucee4-\uc2e4\ud589",level:3},{value:"replication slave \uad8c\ud55c \uc124\uc815",id:"replication-slave-\uad8c\ud55c-\uc124\uc815",level:3},{value:"SOURCE DB \uc815\ubcf4 \ud655\uc778",id:"source-db-\uc815\ubcf4-\ud655\uc778",level:3},{value:"SOURCE ip \uc8fc\uc18c \ud655\uc778",id:"source-ip-\uc8fc\uc18c-\ud655\uc778",level:3},{value:"replica mysql \uc811\uc18d",id:"replica-mysql-\uc811\uc18d",level:3},{value:"replica \uc124\uc815",id:"replica-\uc124\uc815",level:3},{value:"\uc124\uc815 \ud655\uc778",id:"\uc124\uc815-\ud655\uc778",level:3},{value:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30",id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8\ub85c-db-\uc811\uadfc\ud558\uae30",level:2},{value:"Environment \uc124\uc815",id:"environment-\uc124\uc815",level:3},{value:"DataSourceType \uc124\uc815",id:"datasourcetype-\uc124\uc815",level:3},{value:"AbstractRoutingDataSource \uc124\uc815",id:"abstractroutingdatasource-\uc124\uc815",level:3},{value:"DataSource \uc124\uc815",id:"datasource-\uc124\uc815",level:3},{value:"\ub3d9\uc791 \ud655\uc778",id:"\ub3d9\uc791-\ud655\uc778",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"\ubcf5\uc81creplication",children:"\ubcf5\uc81c(Replication)"}),"\n",(0,a.jsxs)(n.p,{children:["\ud55c \uc11c\ubc84\uc5d0\uc11c \ub2e4\ub978 \uc11c\ubc84\ub85c \ub370\uc774\ud130\ub97c \ub3d9\uae30\ud654\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc6d0\ubcf8 \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Primary \ub610\ub294 Source \ub77c\uace0 \ubd80\ub974\uace0, \ubcf5\uc81c\ub41c \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Secondary \ub610\ub294 Replica \ub77c\uace0 \ubd80\ub978\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ubcf5\uc81c\ub97c-\ud558\ub294-\uc774\uc720",children:"\ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"1. \uc2a4\ucf00\uc77c \uc544\uc6c3"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc0ac\uc6a9\uc790\uc758 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uac00\ud574\uc9c0\ub294 \ubd80\ud558\ub3c4 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc99d\uac00\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub97c \ucc98\ub9ac\ud558\uae30 \uc704\ud574 \ubcf5\uc81c\ub97c \ud1b5\ud55c \uc2a4\ucf00\uc77c \uc544\uc6c3\uc744 \uc801\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucffc\ub9ac\ub4e4\uc744 \uac01\uac01\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c \ubd84\uc0b0 \uc2dc\ud0ac \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"2. \ub370\uc774\ud130 \ubc31\uc5c5"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc2e4\uc81c \uc6b4\uc601\ub418\ub294 \uc11c\ube44\uc2a4\uac00 \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 DB\uc5d0\uc11c \ubc31\uc5c5\uc744 \uc9c4\ud589\ud558\ub294 \uacbd\uc6b0, \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc774 \uac00\uc9c0 \uc54a\ub3c4\ub85d \ubcf5\uc81c\ub97c \ud1b5\ud574 Replica \uc11c\ubc84\ub97c \uad6c\ucd95\ud558\uc5ec, Replica \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ub97c \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\uc73c\ub85c \uc601\ud5a5\uc744 \ucd5c\uc18c\ud654 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"3. \ub370\uc774\ud130 \ubd84\uc11d"})}),"\n",(0,a.jsxs)(n.p,{children:["\ubc31\uc5c5\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc7a1\ud558\uace0 \ubb34\uac70\uc6b4 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\uc758 \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc81c\ub97c \uc0ac\uc6a9\ud574 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"4. \ub370\uc774\ud130\uc758 \uc9c0\ub9ac\uc801 \ubd84\uc0b0"})}),"\n",(0,a.jsx)(n.p,{children:"\ube60\ub978 \uc751\ub2f5\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc11c\ubc84\uc5d0 \uac00\uae5d\uac8c \uc11c\ubc84\ub97c \uad6c\uc131\ud558\uac70\ub098, \uace0\uac00\uc6a9\uc131(High Availability)\uc744 \uc704\ud574\uc11c\ub3c4 \uc0ac\uc6a9\ub41c\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ud30c\uc77c-\uc704\uce58-\uae30\ubc18-\ubcf5\uc81c",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c"}),"\n",(0,a.jsxs)(n.p,{children:["MySQL \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub85c\uadf8 \ud30c\uc77c\uc744 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub77c\uace0 \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ud1b5\ud574 \ub370\uc774\ud130 \ubcc0\uacbd, \ud14c\uc774\ube14 \uad6c\uc870 \ubcc0\uacbd, \uacc4\uc815\uc774\ub098 \uad8c\ud55c \ubcc0\uacbd\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc800\uc7a5\ub41c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","MySQL\uc758 \ubcf5\uc81c\ub294 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. \uc774\ub97c Replica \uc11c\ubc84\ub85c \uc804\ub2ec\ud558\uace0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph Replica\n\t\tdirection TB\n\t\tIO[Replication I/O thread] -- save --\x3e RL[Relay Log]\n\t\tSQL[Replication SQL Thread] -- read --\x3e RL\n\tend\n\n\tsubgraph Source\n\t\tdirection TB\n\t\tBLD[Binary Log Dump Thread] -- Send Binary Log Dump--\x3e IO\n\tend\n"}),"\n",(0,a.jsx)(n.admonition,{title:"\uc2a4\ub808\ub4dc\ubcc4 \uc5ed\ud560",type:"note",children:(0,a.jsxs)(n.p,{children:["Binary Log Dump Thread: \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc758 \ub0b4\uc6a9\uc744 Replica \uc11c\ubc84\ub85c \uc804\ub2ec",(0,a.jsx)(n.br,{}),"\n","Replication I/O Thread: Binary \ub85c\uadf8 \uc774\ubca4\ud2b8\ub97c \uac00\uc838\uc640 \ub85c\uceec \uc11c\ubc84\uc758 \ud30c\uc77c(Relay Log)\ub85c \uc800\uc7a5",(0,a.jsx)(n.br,{}),"\n","Replication SQL Thread: \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc774\ubca4\ud2b8\ub97c \uc77d\uace0 \uc2e4\ud589"]})}),"\n",(0,a.jsx)(n.h3,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd\uc758-\ubb38\uc81c\uc810",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810"}),"\n",(0,a.jsxs)(n.p,{children:["\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc740 \uc11c\ubc84\uc5d0 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0 \ubcc0\uacbd\uc774 \uae4c\ub2e4\ub86d\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud1a0\ud3f4\ub85c\uc9c0\ub780 \ub124\ud2b8\uc6cc\ud06c\uc758 \uc694\uc18c\ub4e4\uc744 \ubb3c\ub9ac\uc801\uc73c\ub85c \uc5f0\uacb0\ud574 \ub193\uc740 \uac83, \ub610\ub294 \uadf8 \uc5f0\uacb0 \ubc29\uc2dd\uc744 \ub9d0\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph TD\n\tA[A binary-log:300] --\x3e B[B Binary-log:300]\n\tA[A binary-log:300] --\x3e C[C Binary-log:200]"}),"\n",(0,a.jsx)(n.p,{children:"\uc704\uc640 \uac19\uc774 Source \uc11c\ubc84, Replica 2\ub300\uac00 \uc874\uc7ac\ud558\uace0, C \uc11c\ubc84\uc5d0 \ubcf5\uc81c \uc9c0\uc5f0\uc774 \ub418\uc5c8\uc744 \ub54c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph TD\n\tA[A binary-log:300]\n\tB[B Binary-log:300] --\x3e C[C Binary-log:200 \ubb38\uc81c \ubc1c\uc0dd]"}),"\n",(0,a.jsxs)(n.p,{children:["A \uc11c\ubc84\uc5d0\uc11c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 B \uc11c\ubc84\ub97c Source \uc11c\ubc84\ub85c \uc2b9\uaca9\ud558\uace0, C\uc5d0\uac8c \uc870\ud68c \ucffc\ub9ac\ub97c \ubd84\uc0b0\uc2dc\ud0a8\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \uc5ec\uae30\uc11c C \uc11c\ubc84\uc5d0\ub294 A \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\uac00 \uc548\ub418\uc5c8\uc73c\ub2c8 \uc870\ud68c \uc2dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub4a4\ub2a6\uac8c B \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\ub97c \ud558\ub824\uace0 \ud574\ub3c4, \uc5b4\ub5a4 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8, \uc5b4\ub5a4 \uc704\uce58\uc640 \ub3d9\uae30\ud654\ud574\uc57c\ud558\ub294\uc9c0 \uc54c\uae30 \uc5b4\ub835\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\uae00\ub85c\ubc8c-\ud2b8\ub79c\uc7ad\uc158-\uc544\uc774\ub514gtid-\uae30\ubc18-\ubcf5\uc81c",children:"\uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c"}),"\n",(0,a.jsxs)(n.p,{children:["GTID \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ubc1c\uc0dd\ud55c \uc774\ubca4\ud2b8\uc5d0 \uace0\uc720\ud55c \uc2dd\ubcc4\uac12\uc744 \ubd80\uc5ec\ud55c\ub2e4\uba74, \ub3d9\uae30\ud654\uc5d0 \ub300\ud55c \ubb38\uc81c\ub97c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc704\uc758 \uc608\uc2dc\uc640 \uac19\uc774 \ubcf5\uc81c \uc9c0\uc5f0\uacfc \ud568\uaed8 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ud574\ub3c4 \ud2b9\uc815 GTID \ubd80\ud130 \ubcf5\uc81c\ub97c \uc7ac\uac1c\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,a.jsx)(n.admonition,{title:"GTID",type:"note",children:(0,a.jsxs)(n.p,{children:["\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\uc5d0 \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \uc11c\ubc84\uc5d0\uc11c \uace0\uc720\ud558\ub3c4\ub85d \uac01 \uc774\ubca4\ud2b8\uc5d0 \ubd80\uc5ec\ub41c \uc2dd\ubcc4\uac12",(0,a.jsx)(n.br,{}),"\n","[source_id]:[transaction_id]\ub85c \uad6c\uc131\ub418\uba70, source_id\ub294 \uc11c\ubc84\ub97c \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc774\uace0 transaction_id\ub294 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc73c\ub85c 1\uc529 \uc99d\uac00\ud558\ub294 \ud615\ud0dc\ub85c \ubc1c\uae09\ub41c\ub2e4."]})}),"\n",(0,a.jsx)(n.h3,{id:"\ubcf5\uc81c-\ud1a0\ud3f4\ub85c\uc9c0",children:"\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["\uac00\uc7a5 \uac04\ub2e8\ud55c \uad6c\uc131\uc73c\ub85c \uc81c\uc77c \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","replica \uc11c\ubc84\ub97c \uc77d\uae30 \uc804\uc6a9, \uc608\ube44 \uc11c\ubc84, \ubc31\uc5c5 \uc6a9\ub3c4\ub85c \ub9ce\uc774 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R\n S[Source] --\x3e R[Replica]"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uba40\ud2f0 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["2\uac1c\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\ub098\uc758 replica\ub294 \uc608\ube44 \uc6a9\ub3c4\ub85c \ub0a8\uaca8\ub450\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucd94\ud6c4\uc5d0 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 \uc608\ube44 \uc6a9\ub3c4\uc758 replica\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c \uc77d\uae30 \uc694\uccad\uc758 \ubd80\ud558 \ubd84\uc0b0\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R1\n S[Source] --\x3e R1[Replica1]\n S --\x3e R2[Replica2]"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uccb4\uc778 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["replica \uc11c\ubc84\uac00 \ub9ce\uc740 \uacbd\uc6b0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \uc804\ub2ec\ud558\ub294 \uc791\uc5c5 \uc790\uccb4\uac00 \ubd80\ud558\uac00 \ub420 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c 1:M",":M"," \uad6c\uc870\ub85c \uccb4\uc778 \ubcf5\uc81c \uad6c\uc131\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R1\n S[Source] --\x3e R1[Replica1]\n S --\x3e R2[Replica2]\n S --\x3e R3[Replica3]\n\n R3 --\x3e R3-1[Replica 3-1]\n R3 --\x3e R3-2[Replica 3-2]\n\n B[Batch Server] --\x3e R3-2"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\ub4c0\uc5bc \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["2\uac1c\uc758 MySQL \uc11c\ubc84 \ubaa8\ub450 \uc77d\uae30\uc640 \uc4f0\uae30\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d \ud558\ub294 \uad6c\uc131\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uac01 \uc11c\ubc84\uc5d0\uc11c \ubcc0\uacbd\ub41c \ub370\uc774\ud130\ub294 \ub2e4\ub978 \uc11c\ubc84\uc5d0 \ubc18\uc601\ub41c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ubaa9\uc801\uc5d0 \ub530\ub77c ACTIVE-ACTIVE \ud615\ud0dc \ub610\ub294 ACTIVE-PASSIVE \ud615\ud0dc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","ACTIVE-PASSIVE \ud615\ud0dc\uc778 \uacbd\uc6b0 \uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131\uacfc \ub3d9\uc77c\ud574\ubcf4\uc774\uc9c0\ub9cc, ACTIVE \uc11c\ubc84\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uba74 \uc124\uc815\uc758 \ubcc0\uacbd\uc5c6\uc774 PASSIVE \uc11c\ubc84\ub85c \uc4f0\uae30 \uc791\uc5c5\uc744 \uc804\ud658\ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc774 \uc7a5\uc810\uc774\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR1\n W -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR2\n SR1[Source/Replica 1] --\x3e SR2[Source/Replica 2]"}),"\n",(0,a.jsx)(n.admonition,{title:"ACTIVE-ACTIVE, ACTIVE-PASSIVE",type:"note",children:(0,a.jsxs)(n.p,{children:["ACTIVE-ACTIVE: 2\uac1c\uc758 \uc11c\ubc84 \ubaa8\ub450 \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc",(0,a.jsx)(n.br,{}),"\n","ACTIVE-PASSIVE: \ud558\ub098\uc758 \uc11c\ubc84\uc5d0\uc11c\ub9cc \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc"]})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uba40\ud2f0 \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc5ec\ub7ec\uac1c\uc758 source \uc11c\ubc84\uc640 \ud558\ub098\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \uad6c\uc131\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub294 source \uc11c\ubc84\uc758 \ub370\uc774\ud130\ub97c \ud55c \uacf3\uc5d0 \ubc31\uc5c5\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9, \uc5ec\ub7ec \uc11c\ubc84\uc5d0 \uc874\uc7ac\ud558\ub294 \ub370\uc774\ud130\ub97c \ud1b5\ud569, \uc0e4\ub529\ub418\uc5b4\uc788\ub294 \ud14c\uc774\ube14 \ub370\uc774\ud130\ub97c \ud1b5\ud569\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n S1[Source 1] --\x3e R[Replica]\n S2[Source 2] --\x3e R"}),"\n",(0,a.jsx)(n.h2,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd-replication-\uad6c\uc131\ud558\uae30",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30"}),"\n",(0,a.jsxs)(n.p,{children:["mysql 2\ub300\ub97c \uc774\uc6a9\ud558\uc5ec replication\uc744 \uad6c\uc131\ud558\uace0, spring boot application\uc73c\ub85c source, replica \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\ubcf4\ub294 \uc608\uc81c\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://github.com/bbiac/db-replication",children:"https://github.com/bbiac/db-replication"})]}),"\n",(0,a.jsx)(n.h3,{id:"mysql-\ud658\uacbd-\uad6c\uc131",children:"MySQL \ud658\uacbd \uad6c\uc131"}),"\n",(0,a.jsxs)(n.p,{children:["MySQL \ubc84\uc804\uc740 8.1\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","13306, 13307 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud574\uc11c MySQL \uc11c\ubc84 2\ub300\ub97c \ub744\uc6e0\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub610\ud55c \uc0ac\uc2e4 IP \ub300\uc5ed\uc73c\ub85c \ud1b5\uc2e0\ud560 \uc218 \uc788\ub3c4\ub85d \ucee4\uc2a4\ud140 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yml",children:"version: '3.8'\n\nservices:\n source:\n platform: linux/x86_64\n image: mysql:latest\n restart: always\n container_name: mysql-source\n environment:\n TZ: 'Asia/Seoul'\n MYSQL_DATABASE: 'db'\n MYSQL_USER: 'user'\n MYSQL_PASSWORD: 'password'\n MYSQL_ROOT_PASSWORD: 'password'\n ports:\n - \"13306:3306\"\n volumes:\n - db-source:/var/lib/mysql\n - db-source:/var/lib/mysql-files\n - ./docker/source.cnf:/etc/mysql/my.cnf\n networks:\n - mysql_network\n\n replica:\n platform: linux/x86_64\n image: mysql:latest\n restart: always\n container_name: mysql-replica\n environment:\n TZ: 'Asia/Seoul'\n MYSQL_DATABASE: 'db'\n MYSQL_USER: 'user'\n MYSQL_PASSWORD: 'password'\n MYSQL_ROOT_PASSWORD: 'password'\n ports:\n - \"13307:3306\"\n volumes:\n - db-replica:/var/lib/mysql\n - db-replica:/var/lib/mysql-files\n - ./docker/replica.cnf:/etc/mysql/my.cnf\n networks:\n - mysql_network\n\nvolumes:\n db-source:\n db-replica:\n\nnetworks:\n mysql_network:\n driver: bridge\n"})}),"\n",(0,a.jsx)(n.p,{children:"\ub610\ud55c source, replica \uac01\uac01 \ub2e4\uc74c\uacfc \uac19\uc774 db \uc124\uc815\uc744 \ud588\ub2e4."}),"\n",(0,a.jsxs)(n.table,{children:[(0,a.jsx)(n.thead,{children:(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.th,{children:"\uc124\uc815"}),(0,a.jsx)(n.th,{children:"\uc124\uba85"})]})}),(0,a.jsxs)(n.tbody,{children:[(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"server_id"}),(0,a.jsx)(n.td,{children:"\uac01\uac01\uc758 mysql \ub9c8\ub2e4 \uace0\uc720\ud55c \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"log_bin"}),(0,a.jsx)(n.td,{children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815\uc73c\ub85c \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 /var/lib/mysql \uc544\ub798 \ud574\ub2f9 log_bin\uc5d0 \uc124\uc815\ub41c \uac12\uc73c\ub85c \ub85c\uadf8\uac00 \uc0dd\uc131\ub41c\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"sync_binlog"}),(0,a.jsx)(n.td,{children:"N\uac1c\uc758 \ud2b8\ub79c\uc7ad\uc158 \ub2f9 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ub514\uc2a4\ud06c\uc640 \ub3d9\uae30\ud654 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d \ud55c\ub2e4.\xa01\uc740 \uae30\ubcf8\uac12\uc73c\ub85c \uc548\uc815\uc801\uc774\uc9c0\ub9cc, \uac00\uc7a5 \ub290\ub9ac\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"relay_log"}),(0,a.jsx)(n.td,{children:"\ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"relay_log_purge"}),(0,a.jsx)(n.td,{children:"\ud544\uc694 \uc5c6\ub294 \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \uc0ad\uc81c\ud558\ub294 \uc635\uc158"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"read_only"}),(0,a.jsx)(n.td,{children:"\uc77d\uae30 \uc804\uc6a9 \uc124\uc815"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"log_replica_updates"}),(0,a.jsx)(n.td,{children:"Replication SQL Thread\ub85c \uc778\ud574 \uc2e4\ud589\ub418\ub294 \uc815\ubcf4\ub97c \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc5d0 \uae30\ub85d \ucd94\ud6c4\uc5d0 \uc18c\uc2a4 \uc11c\ubc84\ub85c \uc2b9\uaca9\ub418\ub294 \uacbd\uc6b0\ub97c \uace0\ub824\ud558\uba74 \uc124\uc815\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."})]})]})]}),"\n","\n","\n",(0,a.jsxs)(i.Z,{children:[(0,a.jsx)(l.Z,{value:"Source",label:"Source",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-cnf",metastring:'title="/docker/source.cnf"',children:"[mysqld]\nserver_id=1\nlog_bin=mysql-bin\nsync_binlog=1\n"})})}),(0,a.jsx)(l.Z,{value:"Replica",label:"Replica",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-cnf",metastring:'title="/docker/replica.cnf"',children:"[mysqld]\nserver_id=2\nrelay_log=mysql-relay-bin\nrelay_log_purge=ON\nread_only\nlog_replica_updates\n"})})})]}),"\n",(0,a.jsx)(n.h3,{id:"\ub3c4\ucee4-\uc2e4\ud589",children:"\ub3c4\ucee4 \uc2e4\ud589"}),"\n",(0,a.jsxs)(n.p,{children:["docker-compose up \uba85\ub839\uc5b4\ub85c docker-compose \uc124\uc815\uc73c\ub85c docker\ub97c \ub744\uc6b4\ub2e4.",(0,a.jsx)(n.br,{}),"\n","-d \uc635\uc158\uc744 \ubd99\uc774\uba74 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ubaa8\ub4dc\ub85c \uc2e4\ud589\ub41c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"docker-compose up -d\n"})}),"\n",(0,a.jsx)(n.h3,{id:"replication-slave-\uad8c\ud55c-\uc124\uc815",children:"replication slave \uad8c\ud55c \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["REPLICATION SLAVE \uad8c\ud55c\uc774 \uc124\uc815\ub418\uc5b4 \uc788\uc5b4\uc57c replica \uc11c\ubc84\uc5d0\uc11c source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec \ub85c\uadf8\ub97c \uc77d\uc5b4\uc62c \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec user \uacc4\uc815\uc5d0 \ud574\ub2f9 \uad8c\ud55c\uc744 \uc124\uc815\ud574\uc900\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:"SOURCE \uc811\uc18d"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker exec -it mysql-source mysql -u root -p\n"})}),"\n",(0,a.jsx)(n.p,{children:"user \uacc4\uc815\uc5d0 REPLICATION SLAVE \uad8c\ud55c \ucd94\uac00"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"GRANT REPLICATION SLAVE ON *.* TO 'user'@'%';\nFLUSH PRIVILEGES;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"source-db-\uc815\ubcf4-\ud655\uc778",children:"SOURCE DB \uc815\ubcf4 \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["replica \uc124\uc815\uc5d0 \ud544\uc694\ud55c source db\uc758 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c\uba85\uacfc Position\uc744 \ud655\uc778\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","Position \uac12\uc740 \uc2e4\uc81c \ud30c\uc77c\uc758 \ubc14\uc774\ud2b8 \uc218\ub97c \uc758\ubbf8\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud655\uc778\ud55c File(SOURCE_LOG_FILE)\uacfc Position(SOURCE_LOG_POS) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"SHOW MASTER STATUS;\n\n+------------------+----------+--------------+------------------+-------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |\n+------------------+----------+--------------+------------------+-------------------+\n| mysql-bin.000003 | 1082 | | | |\n+------------------+----------+--------------+------------------+-------------------+\n"})}),"\n",(0,a.jsx)(n.h3,{id:"source-ip-\uc8fc\uc18c-\ud655\uc778",children:"SOURCE ip \uc8fc\uc18c \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["docker inspect -f \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ud574\ub2f9 \ucee8\ud14c\uc774\ub108\uc758 \uc138\ubd80 \uc815\ubcf4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud574 docker-compose \ud30c\uc77c\uc5d0 \uc124\uc815\ud574\ub454 mysql_network\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc124 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'docker inspect -f "{{with index .NetworkSettings.Networks \\"db-replication_mysql_network\\"}}{{.IPAddress}}{{end}}" mysql-source\n'})}),"\n",(0,a.jsxs)(n.p,{children:["ip \uc8fc\uc18c\uac00 \ub098\uc624\uc9c0 \uc54a\ub294 \uacbd\uc6b0 docker inspect mysql-source\ub85c \ud655\uc778\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud655\uc778\ud55c IP\uc8fc\uc18c(SOURCE_HOST) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"replica-mysql-\uc811\uc18d",children:"replica mysql \uc811\uc18d"}),"\n",(0,a.jsx)(n.p,{children:"source db\uc5d0 \uc811\uc18d\ud588\ub358 \ubc29\ubc95\uacfc \ub3d9\uc77c\ud558\uac8c replica db\uc5d0 \uc811\uc18d\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker exec -it mysql-replica mysql -u root -p\n"})}),"\n",(0,a.jsx)(n.h3,{id:"replica-\uc124\uc815",children:"replica \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\uc774\uc804\uc5d0 source db\uc5d0\uc11c \uc5bb\uc5c8\ub358 \uc815\ubcf4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc5ec replica \uc124\uc815\uc744 \uc9c4\ud589\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc2e4\uc81c DB \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc73c\ub85c source DB\uc758 \ud30c\uc77c\uc744 \ubcf5\uc81c\ud574\uc57c\ud558\uc9c0\ub9cc \ud604\uc7ac \ubcf5\uc81c\ud560 \ub370\uc774\ud130\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ubd80\ubd84\uc740 \uc0dd\ub7b5\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","SOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS \ub97c \uc801\uc808\ud788 \ubcc0\uacbd\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"STOP REPLICA;\n\nCHANGE REPLICATION SOURCE TO \nSOURCE_HOST='172.29.0.2', \nSOURCE_USER='user', \nSOURCE_PASSWORD='password', \nSOURCE_LOG_FILE='mysql-bin.000001', \nSOURCE_LOG_POS=0, \nGET_SOURCE_PUBLIC_KEY=1;\n\nSTART REPLICA;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"\uc124\uc815-\ud655\uc778",children:"\uc124\uc815 \ud655\uc778"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"SHOW REPLICA STATUS;\n\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n| Waiting for source to send event | 172.25.0.3 | user | 3306 | 60 | mysql-bin.000003 | 1082 | mysql-relay-bin.000002 | 868 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 1082 | 1078 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | | | 1 | |\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n"})}),"\n",(0,a.jsx)(n.p,{children:"Replica_IO_Running, Replica_SQL_Running \uac12\uc774 YES\ub77c\uba74 \uc815\uc0c1\uc801\uc73c\ub85c replication \uad6c\uc131\uc774 \uc644\ub8cc\ub41c \uac83\uc774\ub2e4."}),"\n",(0,a.jsxs)(n.p,{children:["\uc124\uc815\uc744 \ub9c8\uce5c \ud6c4 source db\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 create table \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","replica db\uc5d0 \ub3d9\uc77c\ud55c member table\uc774 \uc0dd\uc131\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE member\n(\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\n name VARCHAR(255)\n);\n"})}),"\n",(0,a.jsx)(n.h2,{id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8\ub85c-db-\uc811\uadfc\ud558\uae30",children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30"}),"\n",(0,a.jsx)(n.p,{children:"\uc77c\ubc18\uc801\uc778 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 source, \uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158\uc778 \uacbd\uc6b0 replica\ub85c \uc694\uccad\uc774 \uac00\ub3c4\ub85d \uad6c\uc131\ud574\ubcf4\uc790."}),"\n",(0,a.jsx)(n.h3,{id:"environment-\uc124\uc815",children:"Environment \uc124\uc815"}),"\n",(0,a.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 source, replica\ub85c \uad6c\ubd84\ud558\uc5ec \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yml",metastring:'title="application.yml"',children:"spring:\n datasource:\n source:\n username: user\n password: password\n driver-class-name: com.mysql.cj.jdbc.Driver\n jdbc-url: jdbc:mysql://localhost:13306/db\n replica:\n username: user\n password: password\n driver-class-name: com.mysql.cj.jdbc.Driver\n jdbc-url: jdbc:mysql://localhost:13307/db\n"})}),"\n",(0,a.jsx)(n.h3,{id:"datasourcetype-\uc124\uc815",children:"DataSourceType \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\ub2e8\uc21c \ubb38\uc790\uc5f4\ub85c\ub3c4 \uad6c\ubd84\ud560 \uc218 \uc788\uc9c0\ub9cc, enum\uc744 \uc774\uc6a9\ud574\uc11c \ud2b8\ub79c\uc7ad\uc158\uc744 \uad6c\ubd84\ud558\ub3c4\ub85d \uc0dd\uc131\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","Key\ub294 \ucd94\ud6c4\uc5d0 \ube48 \uc124\uc815\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="DataSourceType"',children:'public enum DataSourceType {\n SOURCE(SOURCE_NAME),\n REPLICA(REPLICA_NAME),\n ;\n\n private final String key;\n\n DataSourceType(String key) {\n this.key = key;\n }\n\n public static class Key {\n public static final String ROUTING_NAME = "ROUTING";\n public static final String SOURCE_NAME = "SOURCE";\n public static final String REPLICA_NAME = "REPLICA";\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"abstractroutingdatasource-\uc124\uc815",children:"AbstractRoutingDataSource \uc124\uc815"}),"\n",(0,a.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1\uc774 \uc9c0\uc6d0\ud574\uc8fc\ub294 AbstractRoutingDataSource\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSource\ub97c \ud5a5\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsxs)(n.p,{children:["\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub294 ",(0,a.jsx)(n.code,{children:"Map"}),"\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\uc744 \ubc1b\uc544 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"setDefaultTargetDataSource: \uae30\ubcf8 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"setTargetDataSources: \ub9f5 \ud615\ud0dc\ub85c \ubc1b\uc740 \ub370\uc774\ud130 \uc18c\uc2a4 \uac12\ub4e4\uc744 \uc124\uc815\ud55c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"determineCurrentLookupKey\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \ud2b8\ub79c\uc7ad\uc158\uc774 \uc77d\uae30 \uc804\uc6a9\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uace0, \ubc18\ud658\ud55c \uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ub370\uc774\ud130 \uc18c\uc2a4\uac00 \uc0ac\uc6a9\ub41c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="RoutingDataSource"',children:'public class RoutingDataSource extends AbstractRoutingDataSource {\n\n private final Logger log = LoggerFactory.getLogger(getClass());\n\n public static RoutingDataSource from(Map dataSources) {\n RoutingDataSource routingDataSource = new RoutingDataSource();\n routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));\n routingDataSource.setTargetDataSources(dataSources);\n return routingDataSource;\n }\n\n @Override\n protected Object determineCurrentLookupKey() {\n boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();\n\n if (readOnly) {\n log.info("readOnly = true, request to replica");\n return DataSourceType.REPLICA;\n }\n log.info("readOnly = false, request to source");\n return DataSourceType.SOURCE;\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"datasource-\uc124\uc815",children:"DataSource \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c\ubd80\ud130 \uc21c\uc11c\ub300\ub85c Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy \uc124\uc815\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc2a4\ud504\ub9c1\uc740 \ud2b8\ub79c\uc7ad\uc158 \uc2dc\uc791\uc2dc\uc5d0 \ucee4\ub125\uc158\uc758 \uc0ac\uc6a9\uc5ec\ubd80\uc640 \uc0c1\uad00\uc5c6\uc774 \ucee4\ub125\uc158\uc744 \ud655\ubcf4\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c readOnly \ud2b8\ub79c\uc7ad\uc158\uc774 \uc124\uc815\ub41c \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ubbf8\ub9ac \ud655\ubcf4\ub41c \ucee4\ub125\uc158\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 replica db\ub85c \uc694\uccad\uc744 \ud558\uc9c0 \uc54a\uace0 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4."]}),"\n",(0,a.jsxs)(n.p,{children:["TransactionSynchronizationManager.isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc \ud638\ucd9c \uc2dc currentTransactionReadOnly\ub77c\ub294 ",(0,a.jsx)(n.code,{children:"ThreadLocal"}),"\uc5d0 \uc124\uc815\ub41c \uac12\uc744 \ubc18\ud658\ud558\ub294\ub370 readOnly \uc124\uc815\uc774 \ub418\uba74 \uc774 \uac12\uc744 true\ub85c \uc124\uc815\ud55c\ub2e4. \ud558\uc9c0\ub9cc determineCurrentLookupKey\ub97c \ud638\ucd9c\ud558\uc5ec key \uac12\uc744 \uac00\uc838\uc624\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc774\ud6c4\uc5d0 \uc124\uc815\ub418\uae30 \ub54c\ubb38\uc5d0 determineCurrentLookupKey \uba54\uc11c\ub4dc\uc5d0\uc11c \ud56d\uc0c1 DataSourceType.SOURCE\uac00 \ubc18\ud658\ub418\uc5b4 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:"LazyConnectionDataSourceProxy\ub97c \uc124\uc815\ud558\ub294 \uacbd\uc6b0 \uc2e4\uc81c DataSource\ub97c \uc0ac\uc6a9\ud558\ub294 \uc2dc\uc810\uc5d0 \ucee4\ub125\uc158\uc744 \ud68d\ub4dd\ud574\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc124\uc815\ud55c\ub300\ub85c replica db\ub85c \uc870\ud68c \uc694\uccad\uc744 \ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="DataSourceConfiguration"',children:'@Configuration\npublic class DataSourceConfiguration {\n\n @Bean\n @Qualifier(SOURCE_NAME)\n @ConfigurationProperties(prefix = "spring.datasource.source")\n public DataSource sourceDataSource() {\n return DataSourceBuilder.create().build();\n }\n\n @Bean\n @Qualifier(REPLICA_NAME)\n @ConfigurationProperties(prefix = "spring.datasource.replica")\n public DataSource replicaDataSource() {\n return DataSourceBuilder.create().build();\n }\n\n @Bean\n @Qualifier(ROUTING_NAME)\n public DataSource routingDataSource(\n @Qualifier(SOURCE_NAME) DataSource sourceDataSource,\n @Qualifier(REPLICA_NAME) DataSource replicaDataSource\n ) {\n return RoutingDataSource.from(Map.of(\n DataSourceType.SOURCE, sourceDataSource,\n DataSourceType.REPLICA, replicaDataSource\n ));\n }\n\n @Bean\n @Primary\n public DataSource dataSource(\n @Qualifier(ROUTING_NAME) DataSource routingDataSource\n ) {\n return new LazyConnectionDataSourceProxy(routingDataSource);\n }\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"\ucd5c\uc885\uc801\uc73c\ub85c DataSource \ube48\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ud615\ud0dc\uac00 \ub41c\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n DSP[LazyConnectionDataSourceProxy] --\x3e RDS[RoutingDataSource]\n\tRDS --\x3e S[SourceDataSource]\n\tRDS --\x3e R[ReplicaDataSource]"}),"\n",(0,a.jsx)(n.h3,{id:"\ub3d9\uc791-\ud655\uc778",children:"\ub3d9\uc791 \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["\uac04\ub2e8\ud558\uac8c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\uc11c \uc124\uc815\ud55c\ub300\ub85c \ub3d9\uc791\uc774 \ub418\ub294\uc9c0 \ud655\uc778\ud574\ubcf4\uc558\ub2e4.",(0,a.jsx)(n.br,{}),"\n","save \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 ",(0,a.jsx)(n.code,{children:"@Transactional"}),", findById \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 ",(0,a.jsx)(n.code,{children:"@Transactional(readOnly = true)"}),"\uac00 \uc124\uc815\ub418\uc5b4\uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub85c\uadf8\ub97c \ud1b5\ud574 save\uc758 \uacbd\uc6b0 source db\ub85c findById\uc758 \uacbd\uc6b0 replica db\ub85c \uc694\uccad\uc744 \ud558\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="MemberServiceTest"',children:'@SpringBootTest\nclass MemberServiceTest {\n\n @Autowired\n private MemberService memberService;\n\n @Test\n void \uc0ac\uc6a9\uc790\ub97c_\uc800\uc7a5\ud55c\ub2e4() {\n // RoutingDataSource log: readOnly = false\n memberService.save("bbiac");\n }\n\n @Test\n void \uc0ac\uc6a9\uc790\ub97c_\uc870\ud68c\ud55c\ub2e4() {\n // RoutingDataSource log: readOnly = true\n assertThatThrownBy(() -> memberService.findById(MAX_VALUE))\n .isInstanceOf(NoSuchElementException.class);\n }\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"DB\uc5d0\uc11c\ub294 \ud655\uc778\ud558\ub824\uba74 root \uacc4\uc815\uc73c\ub85c \uc811\uc18d\ud55c \ud6c4 general log\ub97c \ud65c\uc131\ud654 \uc2dc\ud0a8\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SET GLOBAL log_output = 'table';\nSET GLOBAL general_log = 1;\n"})}),"\n",(0,a.jsxs)(n.p,{children:["general log\ub97c \ud65c\uc131\ud654 \ud55c \ud6c4 \uc77d\uae30 \uc804\uc6a9 \uba54\uc11c\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","server_id, \uc2e4\ud589\ud55c \ucffc\ub9ac\ubb38\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like '%select%';\n\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n| user_host | thread_id | server_id | convert(argument using utf8) |\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n| user[user] @ [172.25.0.1] | 277 | 2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n"})}),"\n",(0,a.jsx)(n.p,{children:"\ud655\uc778 \ud6c4 general log\ub97c \ube44\ud65c\uc131\ud654 \ud55c \ud6c4 \ube44\ud65c\uc131\ud654 \ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SET GLOBAL general_log = 0;\nSHOW VARIABLES LIKE '%general%';\n\n+------------------+---------------------------------+\n| Variable_name | Value |\n+------------------+---------------------------------+\n| general_log | OFF |\n| general_log_file | /var/lib/mysql/4b6b9db98290.log |\n+------------------+---------------------------------+\n"})}),"\n",(0,a.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(n.p,{children:["16\uc7a5 \ubcf5\uc81c, Real MySQL 8.0 - \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.1/en/replication.html",children:"Replication, MySQL Docs"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://huisam.tistory.com/entry/mysql-replication",children:"MySql - Master Slave Replication \uad6c\uc870 \ub9cc\ub4e4\uc5b4\ubcf4\uae30"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://cheese10yun.github.io/spring-transaction/",children:"Spring \ub808\ud50c\ub9ac\ucf00\uc774\uc158 \ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac \ubc29\uc2dd"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://github.com/kwon37xi/replication-datasource",children:"replication-datasource"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/pulse/simplified-guide-mysql-replication-docker-compose-rakesh-shekhawat/",children:"Simplified Guide to MySQL Replication with Docker Compose"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://www.daleseo.com/dockerfile/",children:"Dockerfile\uc5d0\uc11c \uc790\uc8fc \uc4f0\uc774\ub294 \uba85\ub839\uc5b4"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.1/en/change-replication-source-to.html",children:"CHANGE REPLICATION SOURCE TO Statement"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://kwonnam.pe.kr/wiki/springframework/lazyconnectiondatasourceproxy",children:"LazyConnectionDataSourceProxy"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://hudi.blog/database-replication-with-springboot-and-mysql/",children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ub808\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ud1b5\ud55c \ucffc\ub9ac \uc131\ub2a5 \uac1c\uc120 (feat. Mysql, SpringBoot)"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://chagokx2.tistory.com/100",children:"\ubd80\ud558 \ubd84\uc0b0\uc744 \uc704\ud55c MySQL Replication \uad6c\uc131 \ubc0f \ucffc\ub9ac \uc694\uccad \ubd84\uae30"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.docker.com/get-started/08_using_compose/",children:"Use Docker Compose, Docker"})]})]})}function h(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var a=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,a)}return r}function l(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var c=a.createContext({}),o=function(e){var n=a.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):l(l({},n),e)),r},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var r=e.components,t=e.mdxType,i=e.originalType,c=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=o(r),h=t,S=p["".concat(c,".").concat(h)]||p[h]||u[h]||i;return r?a.createElement(S,l(l({ref:n},d),{},{components:r})):a.createElement(S,l({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,r)=>{r.d(n,{Z:()=>l});r(67294);var a=r(86010);const t={tabItem:"tabItem_Ymn6"};var i=r(85893);function l(e){let{children:n,hidden:r,className:l}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,a.Z)(t.tabItem,l),hidden:r,children:n})}},74866:(e,n,r)=>{r.d(n,{Z:()=>R});var a=r(67294),t=r(86010),i=r(12466),l=r(16550),s=r(20469),c=r(91980),o=r(67392),u=r(50012);function d(e){return a.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:r}=e;return(0,a.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:r,attributes:a,default:t}}=e;return{value:n,label:r,attributes:a,default:t}}))}(r);return function(e){const n=(0,o.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,r])}function h(e){let{value:n,tabValues:r}=e;return r.some((e=>e.value===n))}function S(e){let{queryString:n=!1,groupId:r}=e;const t=(0,l.k6)(),i=function(e){let{queryString:n=!1,groupId:r}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!r)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return r??null}({queryString:n,groupId:r});return[(0,c._X)(i),(0,a.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(t.location.search);n.set(i,e),t.replace({...t.location,search:n.toString()})}),[i,t])]}function x(e){const{defaultValue:n,queryString:r=!1,groupId:t}=e,i=p(e),[l,c]=(0,a.useState)((()=>function(e){let{defaultValue:n,tabValues:r}=e;if(0===r.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:r}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${r.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const a=r.find((e=>e.default))??r[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:n,tabValues:i}))),[o,d]=S({queryString:r,groupId:t}),[x,m]=function(e){let{groupId:n}=e;const r=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,i]=(0,u.Nk)(r);return[t,(0,a.useCallback)((e=>{r&&i.set(e)}),[r,i])]}({groupId:t}),b=(()=>{const e=o??x;return h({value:e,tabValues:i})?e:null})();(0,s.Z)((()=>{b&&c(b)}),[b]);return{selectedValue:l,selectValue:(0,a.useCallback)((e=>{if(!h({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),d(e),m(e)}),[d,m,i]),tabValues:i}}var m=r(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var j=r(85893);function g(e){let{className:n,block:r,selectedValue:a,selectValue:l,tabValues:s}=e;const c=[],{blockElementScrollPositionUntilNextRender:o}=(0,i.o5)(),u=e=>{const n=e.currentTarget,r=c.indexOf(n),t=s[r].value;t!==a&&(o(n),l(t))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const r=c.indexOf(e.currentTarget)+1;n=c[r]??c[0];break}case"ArrowLeft":{const r=c.indexOf(e.currentTarget)-1;n=c[r]??c[c.length-1];break}}n?.focus()};return(0,j.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.Z)("tabs",{"tabs--block":r},n),children:s.map((e=>{let{value:n,label:r,attributes:i}=e;return(0,j.jsx)("li",{role:"tab",tabIndex:a===n?0:-1,"aria-selected":a===n,ref:e=>c.push(e),onKeyDown:d,onClick:u,...i,className:(0,t.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":a===n}),children:r??n},n)}))})}function _(e){let{lazy:n,children:r,selectedValue:t}=e;const i=(Array.isArray(r)?r:[r]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===t));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return(0,j.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function y(e){const n=x(e);return(0,j.jsxs)("div",{className:(0,t.Z)("tabs-container",b.tabList),children:[(0,j.jsx)(g,{...e,...n}),(0,j.jsx)(_,{...e,...n})]})}function R(e){const n=(0,m.Z)();return(0,j.jsx)(y,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file diff --git a/assets/js/92fef07b.fcbe78e8.js b/assets/js/92fef07b.753706d5.js similarity index 98% rename from assets/js/92fef07b.fcbe78e8.js rename to assets/js/92fef07b.753706d5.js index 9ac0ec002..b4ce56689 100644 --- a/assets/js/92fef07b.fcbe78e8.js +++ b/assets/js/92fef07b.753706d5.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[300],{41632:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>i,default:()=>x,frontMatter:()=>s,metadata:()=>c,toc:()=>l});var t=n(85893),a=n(3905);const s={title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",slug:"racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/racing-car-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-racingcar/pull/510",date:"2023-02-14T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 14\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.625,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",slug:"racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",permalink:"/ladder-retrospective"},nextItem:{title:"Parameterized Tests",permalink:"/parameterized-tests"}},o={authorsImageUrls:[]},l=[{value:"\uc790\ub3d9\ucc28 \uacbd\uc8fc",id:"\uc790\ub3d9\ucc28-\uacbd\uc8fc",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",hr:"hr",li:"li",mermaid:"mermaid",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-racingcar/pull/510",children:"https://github.com/woowacourse/java-racingcar/pull/510"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-racingcar/pull/538",children:"https://github.com/woowacourse/java-racingcar/pull/538"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\uc790\ub3d9\ucc28-\uacbd\uc8fc",children:"\uc790\ub3d9\ucc28 \uacbd\uc8fc"}),"\n",(0,t.jsxs)(r.p,{children:["\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158\uc5d0\uc11c\ub294 \ub2e4\uc990\uacfc \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\ud14c\ucf54 \ub4e4\uc5b4\uc640\uc11c \uccab \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\uc774\ub77c \ub9ce\uc774 \ub5a8\ub838\uc9c0\ub9cc, \ub2e4\uc990\uc774 \ub300\ud654\ub97c \uc798 \uc774\ub04c\uc5b4\uc918 \ub108\ubb34 \uc990\uac70\uc6e0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uccab\ub0a0\uc740 \uac04\ub2e8\ud788 \ucee8\ubca4\uc158\uacfc \ud658\uacbd\uc744 \uc124\uc815\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc84c\uace0 \ub2e4\uc74c \ub0a0\ubd80\ud130 \uc790\ub3d9\ucc28 \uacbd\uc8fc\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc2dc\uc791\uc740 \uac04\ub2e8\ud558\uac8c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud558\uace0, \uc5b4\ub5bb\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud560\uc9c0 \uac19\uc774 \uace0\ubbfc\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc2dc\uc791\ud558\uae30 \uc804 \uc544\ub798\uc640 \uac19\uc774 mermaid\ub97c \uc774\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc5d0 \ub300\ud574\uc11c \uac04\ub2e8\ud55c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \ub9cc\ub4e4\uace0 \uc2dc\uc791\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","mermaid\ub294 \ucf54\ub4dc\ub85c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \uc0dd\uc131 \ud574\uc8fc\ub294 \ub3c4\uad6c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc774 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"\ucf54\ub4dc \uae30\ubc18\uc774\ub77c \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \uc0dd\uac01\ud55c \uac83\uc744 \uc2dc\uac01\ud654\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(r.li,{children:"github\uc5d0\uc11c mermaid\ub97c \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \ucf54\ub4dc\ub97c \uc774\ud574\ud560 \uc218 \uc788\ub294 \ubd80\uac00\uc801\uc778 \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(r.mermaid,{value:"---\ntitle: \uc790\ub3d9\ucc28 \uacbd\uc8fc \uccab \ub9ac\ubdf0 \uc694\uccad\uc2dc \uad6c\uc870\n---\ngraph TD\n Cars --\x3e Car\n Car --\x3e Name\n Car --\x3e Position\n RacingGame --\x3e Count\n RacingGame --\x3e NumberGenerator\n RacingGame --\x3e Cars\n RacingCarController --\x3e RacingGame\n RandomNumberGenerator -.-> NumberGenerator\n RacingCarController --\x3e InputView\n InputView --\x3e InputValidator\n RacingCarController --\x3e OutputView"}),"\n",(0,t.jsx)(r.p,{children:"\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \ub370 \ud070 \uc5b4\ub824\uc6c0\uc774 \uc788\uc9c0\ub294 \uc54a\uc558\uace0, \ud398\uc5b4\ub97c \ub9c8\uce58\uae30 \uc804 \uc11c\ub85c \uace0\ubbfc\ub418\ub294 \ubd80\ubd84\uc744 \uc815\ub9ac\ud588\uc744 \ub54c \uc88b\uc558\ub2e4."}),"\n",(0,t.jsxs)(r.p,{children:["\ud398\uc5b4\ud558\uba74\uc11c \uc798\ud588\ub2e4\uace0 \uc0dd\uac01\ud588\ub358 \uc810\uc740 \uc11c\ub85c\uc758 \uc0dd\uac01\uacfc \ub9ac\ubdf0 \ubc1b\uc740 \uac83\uc744 \uacf5\uc720\ud55c \uac83\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub9ac\ud329\ud130\ub9c1\uc744 \uc5b4\ub5bb\uac8c \ud588\ub294\uc9c0? \uc774\ub7f0 \ub9ac\ubdf0\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \uc0dd\uac01\ud558\ub294\uc9c0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c8 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\ub9ac\ud329\ud130\ub9c1\uc774 \ub05d\ub09c \ud6c4 \uba54\uc11c\ub4dc\uba85, \ud14c\uc2a4\ud2b8\uc2dc \ucd9c\ub825\ud558\ub294 \uba54\uc2dc\uc9c0\uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\uac00 \ub9ce\uc774 \ub2ec\ub838\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uac1d\uccb4\uac00 \uc5b4\ub5a4 \ucc45\uc784\uacfc \uc5ed\ud560\uc744 \uac00\uc9c0\ub294\uc9c0 \uc0dd\uac01\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uba85\ud655\ud55c \uba54\uc11c\ub4dc\uba85\uc744 \uc791\uc131\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ud3c9\uc18c\uc5d0 \ud504\ub85c\uadf8\ub798\ubc0d \uc774\uc57c\uae30\uac00 \uc544\ub2cc \ub2e4\ub978 \uc8fc\uc81c\ub85c \uc774\uc57c\uae30\ud558\uba74 \uc798 \ub4e4\uc73c\ub824\uace0 \ud558\ub294 \ud3b8\uc774\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \uc88b\uc544\ud558\ub294 \uc8fc\uc81c, \uad00\uc2ec\uac00\ub294 \uc8fc\uc81c\uc778 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub97c \ud560 \ub550 \ub9d0\uc774 \ub9ce\uc544\uc9c4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130\ub294 \ub354 \ub9ce\uc740 \uc2dc\uac04\uc744 \ud398\uc5b4\uc758 \uc758\uacac\uacfc \uc774\uc57c\uae30\ub97c \ub4e3\ub294 \uacf3\uc5d0 \uc0ac\uc6a9\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Assertions extracting"})}),"\n",(0,t.jsxs)(r.p,{children:["\uacb0\uacfc \ub0b4\ubd80\uc5d0 \uc788\ub294 \uac12\uc744 \ud655\uc778\ud558\uace0 \uc2f6\uc744 \ub54c extracting \ud0a4\uc6cc\ub4dc\ub97c \uc774\uc6a9\ud574\uc11c \ub0b4\ubd80\uc758 \uac12\uc744 \uac80\uc99d\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0\ub294 \ud544\uc694\uc5d0 \ub530\ub77c stream\uc744 \uc774\uc6a9\ud558\uc5ec \uac80\uc99d\ud560 \uac12\uc744 \uc0dd\uc131\ud588\uc9c0\ub9cc, \ud574\ub2f9 \ubc29\ubc95\uc744 \uc774\uc6a9\ud574\uc11c \uc808\ucc28\ub97c \uc904\uc77c \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'@Test\nvoid extracting() {\n final Cars cars = new Cars(List.of("car1", "car2"));\n\n assertThat(cars.getCars())\n .extracting(Car::getName)\n .containsExactly("car1", "car2");\n}\n'})}),"\n",(0,t.jsx)(r.hr,{}),"\n",(0,t.jsx)(r.p,{children:"\uc544\ub798\ub294 \ub9ac\ubdf0\uc5b4\ub2d8\uacfc \ub300\ud654\ub97c \ub098\ub204\uba74\uc11c \uc5bb\uc740 \ub2f5\ubcc0 + \ub098\uc758 \uc758\uacac\uc774\ub2e4."}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8"})}),"\n",(0,t.jsxs)(r.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc0c1\uc774 \uac80\uc99d\ub41c \uac83\uc774\ub77c\uba74 \uc791\uc131\ud558\uc9c0 \uc54a\uac70\ub098, \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uc791\uc131\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uac74 \uac1c\uc778\uc801\uc778 \uc0dd\uac01\uc774\uc9c0\ub9cc \ub0b4\uac00 \uc548\uc815\uac10\uc774 \ub4e4 \uc218 \uc788\uc744 \uc815\ub3c4\ub85c \ucd9c\ub825 \ubc94\uc704 \ub0b4\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud558\ub294\uc9c0 \uc815\ub3c4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub2e8\uc21c \uc704\uc784\uc744 \ud558\ub294 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc704\uc784\uc774\ub77c\ub294 \uac83\uc740 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc99d\ud558\ub294 \uac83\ubcf4\ub2e4 \uacb0\uacfc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub2e8\uc21c\ud788 \uc704\uc784\ub9cc \ud558\ub294 \ud14c\uc2a4\ud2b8\uc758 \uacbd\uc6b0 \uacb0\uacfc\ub97c \uac80\uc99d\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc911\ubcf5\ub418\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \uc911\ubcf5\ub41c \ud14c\uc2a4\ud2b8\ub97c \uc904\uc774\uae30 \uc704\ud574 \ub0b4\ubd80\uc758 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0 \uac80\uc99d\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\ub294 \uac83\uc744 \uc54c\uac8c \ub418\uc5c8\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\uc548\uc815\uc801\uc73c\ub85c \uacb0\uacfc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c getter \uc0ac\uc6a9"})}),"\n",(0,t.jsxs)(r.p,{children:["\ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\ub85c \ub3c4\uba54\uc778\uc5d0 \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc740 \uc88b\uc9c0 \ubabb\ud558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud544\uc694\uc758 \uacbd\uc6b0 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc9c0\ub9cc, \uae30\uc874\uc5d0 \uc788\ub294 \uba54\uc11c\ub4dc\ub4e4\uc744 \ud65c\uc6a9\ud574\ubcf4\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub9e4\uc6b0 \ub3d9\uc758\ud558\uace0, \uc55e\uc73c\ub85c\ub3c4 \ucd5c\ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \ucf54\ub4dc\ub97c \ub3c4\uba54\uc778\uc5d0 \uc791\uc131\ud558\uc9c0 \uc54a\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\uc9c8\ubb38\uc774\ub098 \uc0dd\uac01\ud560 \uc810\uc774 \uc788\uc744 \ub54c \ub9e4\uc6b0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc0dd\uac01\uc744 \uc815\ub9ac\ud55c \ud6c4 \uc790\uc2e0\uc758 \uc758\uacac\uc744 \uba85\ub8cc\ud558\uac8c \uc804\ub2ec\ud574\uc8fc\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc2dd\uc744 \ud6a8\uc728\uc801\uc73c\ub85c \uc2b5\ub4dd\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub09c \uc0dd\uac01\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc740 \ucc44\ub85c \ub0b4\ubc84\ub824 \ub454 \uc595\uc740 \uc9c0\uc2dd\uc774 \ub9ce\uc740 \uac83 \uac19\ub2e4. (\uc774\ub7f0 \uac83\ub3c4 \uc544\ub294 \uac83\uc774\ub77c\uace0 \ud560 \uc218 \uc788\uc744\uae4c?)",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc870\uae08 \ub354 \uba38\ub9bf\uc18d\uc5d0\uc11c \uc815\ub9ac\ud558\uace0, \ubb38\uc81c\uc5d0 \ub300\ud574 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \ub298\ub824\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uac1c\ubc1c\uc5d0 \uc5f4\uc815\uc744 \uac00\uc9c4 \uac8c \ub290\uaef4\uc9c4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \uac1c\ubc1c\uc744 \uc88b\uc544\ud558\uc9c0\ub9cc, \ucd5c\uadfc\uc5d0\ub294 \uc758\uc9c0\uac00 \uc57d\ud574\uc84c\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc5f4\uc815\uc774 \uac00\ub4dd\ud55c \uc0ac\ub78c\uc744 \ub9cc\ub098\ub2c8 \ub098\ub3c4 \uc5f4\uc815\uc801\uc778 \uc0ac\ub78c\uc774 \ub418\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uce6d\ucc2c\uc744 \ub9ce\uc774 \ud574\uc900\ub2e4. \ub2e8\uc21c\ud788 \ub9ce\uc774 \ud574\uc8fc\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc9c4\uc2ec\uc744 \ub2f4\uae34 \uce6d\ucc2c\uc744 \ud574\uc92c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uce6d\ucc2c\uc740 \uace0\ub798\ub3c4 \ucda4\ucd94\uac8c \ud558\ub358\uac00?",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\uc11c \uc990\uac70\uc6b4 \ub9c8\uc74c\uc73c\ub85c \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud588\uc5c8\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc5b4\ub5a4 \uc774\uc720 \ub54c\ubb38\uc778\uc9c0 \ubaa8\ub974\uaca0\uc9c0\ub9cc \uac19\uc774 \ud398\uc5b4\ud558\ub294\ub370 \ud3b8\ud55c \ub9c8\uc74c\uc774 \ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uac74 \ubc14\ub85c \ubc30\uc6b8 \uc218 \uc5c6\uc9c0\ub9cc.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \uac19\uc774 \uc77c\ud560 \ub54c \ud3b8\ud55c \uc0ac\ub78c, \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub418\uae30 \uc704\ud574 \uae4a\uc774 \uace0\ubbfc\ud574\ubd10\uc57c\uaca0\ub2e4."]})]})}function x(e={}){const{wrapper:r}={...(0,a.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function a(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function s(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(a[n]=e[n]);return a}(e,r);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var o=t.createContext({}),l=function(e){var r=t.useContext(o),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},x=t.forwardRef((function(e,r){var n=e.components,a=e.mdxType,s=e.originalType,o=e.parentName,x=c(e,["components","mdxType","originalType","parentName"]),d=l(n),j=a,h=d["".concat(o,".").concat(j)]||d[j]||p[j]||s;return n?t.createElement(h,i(i({ref:r},x),{},{components:n})):t.createElement(h,i({ref:r},x))}));x.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[300],{41632:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>i,default:()=>x,frontMatter:()=>s,metadata:()=>c,toc:()=>l});var t=n(85893),a=n(3905);const s={title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",slug:"racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/racing-car-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-racingcar/pull/510",date:"2023-02-14T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 14\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.625,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",slug:"racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"Parameterized Tests",permalink:"/parameterized-tests"},nextItem:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",permalink:"/ladder-retrospective"}},o={authorsImageUrls:[]},l=[{value:"\uc790\ub3d9\ucc28 \uacbd\uc8fc",id:"\uc790\ub3d9\ucc28-\uacbd\uc8fc",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",hr:"hr",li:"li",mermaid:"mermaid",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-racingcar/pull/510",children:"https://github.com/woowacourse/java-racingcar/pull/510"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-racingcar/pull/538",children:"https://github.com/woowacourse/java-racingcar/pull/538"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\uc790\ub3d9\ucc28-\uacbd\uc8fc",children:"\uc790\ub3d9\ucc28 \uacbd\uc8fc"}),"\n",(0,t.jsxs)(r.p,{children:["\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158\uc5d0\uc11c\ub294 \ub2e4\uc990\uacfc \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\ud14c\ucf54 \ub4e4\uc5b4\uc640\uc11c \uccab \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\uc774\ub77c \ub9ce\uc774 \ub5a8\ub838\uc9c0\ub9cc, \ub2e4\uc990\uc774 \ub300\ud654\ub97c \uc798 \uc774\ub04c\uc5b4\uc918 \ub108\ubb34 \uc990\uac70\uc6e0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uccab\ub0a0\uc740 \uac04\ub2e8\ud788 \ucee8\ubca4\uc158\uacfc \ud658\uacbd\uc744 \uc124\uc815\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc84c\uace0 \ub2e4\uc74c \ub0a0\ubd80\ud130 \uc790\ub3d9\ucc28 \uacbd\uc8fc\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc2dc\uc791\uc740 \uac04\ub2e8\ud558\uac8c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud558\uace0, \uc5b4\ub5bb\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud560\uc9c0 \uac19\uc774 \uace0\ubbfc\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc2dc\uc791\ud558\uae30 \uc804 \uc544\ub798\uc640 \uac19\uc774 mermaid\ub97c \uc774\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc5d0 \ub300\ud574\uc11c \uac04\ub2e8\ud55c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \ub9cc\ub4e4\uace0 \uc2dc\uc791\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","mermaid\ub294 \ucf54\ub4dc\ub85c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \uc0dd\uc131 \ud574\uc8fc\ub294 \ub3c4\uad6c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc774 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"\ucf54\ub4dc \uae30\ubc18\uc774\ub77c \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \uc0dd\uac01\ud55c \uac83\uc744 \uc2dc\uac01\ud654\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(r.li,{children:"github\uc5d0\uc11c mermaid\ub97c \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \ucf54\ub4dc\ub97c \uc774\ud574\ud560 \uc218 \uc788\ub294 \ubd80\uac00\uc801\uc778 \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(r.mermaid,{value:"---\ntitle: \uc790\ub3d9\ucc28 \uacbd\uc8fc \uccab \ub9ac\ubdf0 \uc694\uccad\uc2dc \uad6c\uc870\n---\ngraph TD\n Cars --\x3e Car\n Car --\x3e Name\n Car --\x3e Position\n RacingGame --\x3e Count\n RacingGame --\x3e NumberGenerator\n RacingGame --\x3e Cars\n RacingCarController --\x3e RacingGame\n RandomNumberGenerator -.-> NumberGenerator\n RacingCarController --\x3e InputView\n InputView --\x3e InputValidator\n RacingCarController --\x3e OutputView"}),"\n",(0,t.jsx)(r.p,{children:"\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \ub370 \ud070 \uc5b4\ub824\uc6c0\uc774 \uc788\uc9c0\ub294 \uc54a\uc558\uace0, \ud398\uc5b4\ub97c \ub9c8\uce58\uae30 \uc804 \uc11c\ub85c \uace0\ubbfc\ub418\ub294 \ubd80\ubd84\uc744 \uc815\ub9ac\ud588\uc744 \ub54c \uc88b\uc558\ub2e4."}),"\n",(0,t.jsxs)(r.p,{children:["\ud398\uc5b4\ud558\uba74\uc11c \uc798\ud588\ub2e4\uace0 \uc0dd\uac01\ud588\ub358 \uc810\uc740 \uc11c\ub85c\uc758 \uc0dd\uac01\uacfc \ub9ac\ubdf0 \ubc1b\uc740 \uac83\uc744 \uacf5\uc720\ud55c \uac83\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub9ac\ud329\ud130\ub9c1\uc744 \uc5b4\ub5bb\uac8c \ud588\ub294\uc9c0? \uc774\ub7f0 \ub9ac\ubdf0\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \uc0dd\uac01\ud558\ub294\uc9c0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c8 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\ub9ac\ud329\ud130\ub9c1\uc774 \ub05d\ub09c \ud6c4 \uba54\uc11c\ub4dc\uba85, \ud14c\uc2a4\ud2b8\uc2dc \ucd9c\ub825\ud558\ub294 \uba54\uc2dc\uc9c0\uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\uac00 \ub9ce\uc774 \ub2ec\ub838\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uac1d\uccb4\uac00 \uc5b4\ub5a4 \ucc45\uc784\uacfc \uc5ed\ud560\uc744 \uac00\uc9c0\ub294\uc9c0 \uc0dd\uac01\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uba85\ud655\ud55c \uba54\uc11c\ub4dc\uba85\uc744 \uc791\uc131\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ud3c9\uc18c\uc5d0 \ud504\ub85c\uadf8\ub798\ubc0d \uc774\uc57c\uae30\uac00 \uc544\ub2cc \ub2e4\ub978 \uc8fc\uc81c\ub85c \uc774\uc57c\uae30\ud558\uba74 \uc798 \ub4e4\uc73c\ub824\uace0 \ud558\ub294 \ud3b8\uc774\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \uc88b\uc544\ud558\ub294 \uc8fc\uc81c, \uad00\uc2ec\uac00\ub294 \uc8fc\uc81c\uc778 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub97c \ud560 \ub550 \ub9d0\uc774 \ub9ce\uc544\uc9c4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130\ub294 \ub354 \ub9ce\uc740 \uc2dc\uac04\uc744 \ud398\uc5b4\uc758 \uc758\uacac\uacfc \uc774\uc57c\uae30\ub97c \ub4e3\ub294 \uacf3\uc5d0 \uc0ac\uc6a9\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Assertions extracting"})}),"\n",(0,t.jsxs)(r.p,{children:["\uacb0\uacfc \ub0b4\ubd80\uc5d0 \uc788\ub294 \uac12\uc744 \ud655\uc778\ud558\uace0 \uc2f6\uc744 \ub54c extracting \ud0a4\uc6cc\ub4dc\ub97c \uc774\uc6a9\ud574\uc11c \ub0b4\ubd80\uc758 \uac12\uc744 \uac80\uc99d\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0\ub294 \ud544\uc694\uc5d0 \ub530\ub77c stream\uc744 \uc774\uc6a9\ud558\uc5ec \uac80\uc99d\ud560 \uac12\uc744 \uc0dd\uc131\ud588\uc9c0\ub9cc, \ud574\ub2f9 \ubc29\ubc95\uc744 \uc774\uc6a9\ud574\uc11c \uc808\ucc28\ub97c \uc904\uc77c \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'@Test\nvoid extracting() {\n final Cars cars = new Cars(List.of("car1", "car2"));\n\n assertThat(cars.getCars())\n .extracting(Car::getName)\n .containsExactly("car1", "car2");\n}\n'})}),"\n",(0,t.jsx)(r.hr,{}),"\n",(0,t.jsx)(r.p,{children:"\uc544\ub798\ub294 \ub9ac\ubdf0\uc5b4\ub2d8\uacfc \ub300\ud654\ub97c \ub098\ub204\uba74\uc11c \uc5bb\uc740 \ub2f5\ubcc0 + \ub098\uc758 \uc758\uacac\uc774\ub2e4."}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8"})}),"\n",(0,t.jsxs)(r.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc0c1\uc774 \uac80\uc99d\ub41c \uac83\uc774\ub77c\uba74 \uc791\uc131\ud558\uc9c0 \uc54a\uac70\ub098, \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uc791\uc131\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uac74 \uac1c\uc778\uc801\uc778 \uc0dd\uac01\uc774\uc9c0\ub9cc \ub0b4\uac00 \uc548\uc815\uac10\uc774 \ub4e4 \uc218 \uc788\uc744 \uc815\ub3c4\ub85c \ucd9c\ub825 \ubc94\uc704 \ub0b4\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud558\ub294\uc9c0 \uc815\ub3c4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub2e8\uc21c \uc704\uc784\uc744 \ud558\ub294 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc704\uc784\uc774\ub77c\ub294 \uac83\uc740 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc99d\ud558\ub294 \uac83\ubcf4\ub2e4 \uacb0\uacfc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub2e8\uc21c\ud788 \uc704\uc784\ub9cc \ud558\ub294 \ud14c\uc2a4\ud2b8\uc758 \uacbd\uc6b0 \uacb0\uacfc\ub97c \uac80\uc99d\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc911\ubcf5\ub418\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \uc911\ubcf5\ub41c \ud14c\uc2a4\ud2b8\ub97c \uc904\uc774\uae30 \uc704\ud574 \ub0b4\ubd80\uc758 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0 \uac80\uc99d\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\ub294 \uac83\uc744 \uc54c\uac8c \ub418\uc5c8\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\uc548\uc815\uc801\uc73c\ub85c \uacb0\uacfc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c getter \uc0ac\uc6a9"})}),"\n",(0,t.jsxs)(r.p,{children:["\ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\ub85c \ub3c4\uba54\uc778\uc5d0 \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc740 \uc88b\uc9c0 \ubabb\ud558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud544\uc694\uc758 \uacbd\uc6b0 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc9c0\ub9cc, \uae30\uc874\uc5d0 \uc788\ub294 \uba54\uc11c\ub4dc\ub4e4\uc744 \ud65c\uc6a9\ud574\ubcf4\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub9e4\uc6b0 \ub3d9\uc758\ud558\uace0, \uc55e\uc73c\ub85c\ub3c4 \ucd5c\ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \ucf54\ub4dc\ub97c \ub3c4\uba54\uc778\uc5d0 \uc791\uc131\ud558\uc9c0 \uc54a\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\uc9c8\ubb38\uc774\ub098 \uc0dd\uac01\ud560 \uc810\uc774 \uc788\uc744 \ub54c \ub9e4\uc6b0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc0dd\uac01\uc744 \uc815\ub9ac\ud55c \ud6c4 \uc790\uc2e0\uc758 \uc758\uacac\uc744 \uba85\ub8cc\ud558\uac8c \uc804\ub2ec\ud574\uc8fc\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc2dd\uc744 \ud6a8\uc728\uc801\uc73c\ub85c \uc2b5\ub4dd\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub09c \uc0dd\uac01\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc740 \ucc44\ub85c \ub0b4\ubc84\ub824 \ub454 \uc595\uc740 \uc9c0\uc2dd\uc774 \ub9ce\uc740 \uac83 \uac19\ub2e4. (\uc774\ub7f0 \uac83\ub3c4 \uc544\ub294 \uac83\uc774\ub77c\uace0 \ud560 \uc218 \uc788\uc744\uae4c?)",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc870\uae08 \ub354 \uba38\ub9bf\uc18d\uc5d0\uc11c \uc815\ub9ac\ud558\uace0, \ubb38\uc81c\uc5d0 \ub300\ud574 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \ub298\ub824\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uac1c\ubc1c\uc5d0 \uc5f4\uc815\uc744 \uac00\uc9c4 \uac8c \ub290\uaef4\uc9c4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \uac1c\ubc1c\uc744 \uc88b\uc544\ud558\uc9c0\ub9cc, \ucd5c\uadfc\uc5d0\ub294 \uc758\uc9c0\uac00 \uc57d\ud574\uc84c\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc5f4\uc815\uc774 \uac00\ub4dd\ud55c \uc0ac\ub78c\uc744 \ub9cc\ub098\ub2c8 \ub098\ub3c4 \uc5f4\uc815\uc801\uc778 \uc0ac\ub78c\uc774 \ub418\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uce6d\ucc2c\uc744 \ub9ce\uc774 \ud574\uc900\ub2e4. \ub2e8\uc21c\ud788 \ub9ce\uc774 \ud574\uc8fc\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc9c4\uc2ec\uc744 \ub2f4\uae34 \uce6d\ucc2c\uc744 \ud574\uc92c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uce6d\ucc2c\uc740 \uace0\ub798\ub3c4 \ucda4\ucd94\uac8c \ud558\ub358\uac00?",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\uc11c \uc990\uac70\uc6b4 \ub9c8\uc74c\uc73c\ub85c \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud588\uc5c8\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc5b4\ub5a4 \uc774\uc720 \ub54c\ubb38\uc778\uc9c0 \ubaa8\ub974\uaca0\uc9c0\ub9cc \uac19\uc774 \ud398\uc5b4\ud558\ub294\ub370 \ud3b8\ud55c \ub9c8\uc74c\uc774 \ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uac74 \ubc14\ub85c \ubc30\uc6b8 \uc218 \uc5c6\uc9c0\ub9cc.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \uac19\uc774 \uc77c\ud560 \ub54c \ud3b8\ud55c \uc0ac\ub78c, \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub418\uae30 \uc704\ud574 \uae4a\uc774 \uace0\ubbfc\ud574\ubd10\uc57c\uaca0\ub2e4."]})]})}function x(e={}){const{wrapper:r}={...(0,a.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function a(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function s(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(a[n]=e[n]);return a}(e,r);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var o=t.createContext({}),l=function(e){var r=t.useContext(o),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},x=t.forwardRef((function(e,r){var n=e.components,a=e.mdxType,s=e.originalType,o=e.parentName,x=c(e,["components","mdxType","originalType","parentName"]),d=l(n),j=a,h=d["".concat(o,".").concat(j)]||d[j]||p[j]||s;return n?t.createElement(h,i(i({ref:r},x),{},{components:n})):t.createElement(h,i({ref:r},x))}));x.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/9b43eac8.90a09cb8.js b/assets/js/9b43eac8.65478c34.js similarity index 96% rename from assets/js/9b43eac8.90a09cb8.js rename to assets/js/9b43eac8.65478c34.js index dc419d12e..5aceac825 100644 --- a/assets/js/9b43eac8.90a09cb8.js +++ b/assets/js/9b43eac8.65478c34.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9286],{8617:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var n=t(85893),s=t(3905);const i={title:"2022\ub144 \ud68c\uace0",slug:"2022-retrospective",tags:["Retrospective"]},o=void 0,c={permalink:"/2022-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",title:"2022\ub144 \ud68c\uace0",description:"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70",date:"2023-01-02T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 2\uc77c",tags:[{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.705,hasTruncateMarker:!1,authors:[],frontMatter:{title:"2022\ub144 \ud68c\uace0",slug:"2022-retrospective",tags:["Retrospective"]},unlisted:!1,prevItem:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",permalink:"/the-essence-of-object-orientation"},nextItem:{title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",permalink:"/book-writer"}},l={authorsImageUrls:[]},a=[{value:"\uc804\uc5ed",id:"\uc804\uc5ed",level:3},{value:"\uc790\ubc14",id:"\uc790\ubc14",level:3},{value:"\uc2a4\ud130\ub514",id:"\uc2a4\ud130\ub514",level:3},{value:"\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4",id:"\uc6b0\uc544\ud55c-\ud14c\ud06c\ucf54\uc2a4",level:3},{value:"2023\ub144\uc5d0\ub294",id:"2023\ub144\uc5d0\ub294",level:3}];function p(e){const r={a:"a",br:"br",h3:"h3",p:"p",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.p,{children:"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70"}),"\n",(0,n.jsx)(r.h3,{id:"\uc804\uc5ed",children:"\uc804\uc5ed"}),"\n",(0,n.jsxs)(r.p,{children:["\uc57d 1\ub144 6\uac1c\uc6d4\uac04\uc758 \uacf5\uad70 \uc815\ubcf4\ubcf4\ud638\ubcd1 \uc0dd\ud65c\uc744 \ub9c8\uce58\uace0 \uc804\uc5ed\uc744 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc870\uae30 \uc804\uc5ed \ub54c\ubb38\uc5d0 2021\ub144 12\uc6d4\uc5d0 \ub098\uc654\uc9c0\ub9cc, \uc2e4\uc81c \uc804\uc5ed \ub0a0\uc9dc\ub294 2022\ub144\uc774\ub2c8 \ud68c\uace0\uc5d0 \uc801\uc5b4\ub3c4 \uc0c1\uad00\uc5c6\uaca0\uc9c0."]}),"\n",(0,n.jsxs)(r.p,{children:["\uc870\uae08 \ub354 \ubbf8\ub798\uc5d0 \ub300\ud55c \uc0dd\uac01\uc744 \ud574\ubcfc\uac78 \uadf8\ub7ac\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc804\uc5ed\uc744 \ud588\uc9c0\ub9cc \ubb50 \ud558\ub098 \uc81c\ub300\ub85c \ud560 \uc904 \uc544\ub294 \uac83\ub3c4 \uc5c6\uc73c\ub2c8 \ub113\uc740 \ubc14\ub2f7\uc18d\uc5d0 \ub369\uadf8\ub7ec\ub2c8 \ub193\uc544\uc9c4 \uae30\ubd84\uc774 \uad1c\ud788 \ub4e4\uc5c8\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc77c\ucc0d \uc0dd\uac01\uc744 \uc815\ub9ac\ud558\uc5ec \ubc29\ud5a5\uc744 \uc7a1\uc9c0 \ubabb\ud588\uae30\uc5d0 \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub0a8\uc558\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc790\ubc14",children:"\uc790\ubc14"}),"\n",(0,n.jsxs)(r.p,{children:["\uc804\uc5ed\uc744 \ud558\uace0 \uc9c4\ub85c\ub97c \uace0\ubbfc\ud558\ub2e4 \ud5a5\ub85c\ub2d8\uc758 ",(0,n.jsx)(r.a,{href:"https://jojoldu.tistory.com/609",children:"\uc790\ubc14 \uacf5\ud654\uad6d"})," \ud3ec\uc2a4\ud305\uc744 \uc77d\uace0 \ub098\uc11c \uc790\ubc14 \uacf5\ubd80\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc720\uba85\ud55c \uc778\ud504\ub7f0\uc758 \uae40\uc601\ud55c\ub2d8\uc758 \uc2a4\ud504\ub9c1 \uac15\uc758\ub3c4 \uc788\uace0, \uc88b\uc740 \uc790\ubc14 \uac1c\ubc1c \uc11c\uc801\uc774 \ub9ce\uc544\uc11c \ub3c5\ud559\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud558\ub2e4 \ubcf4\ub2c8 \uc790\ubc14\uc640 \uc2a4\ud504\ub9c1\uc744 \uacf5\ubd80\ud558\uba74\uc11c \u201c\uc65c \uc9c4\uc791\ud558\uc9c0 \uc54a\uc558\uc9c0\u201d\ub77c\ub294 \uc0dd\uac01\ub3c4 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc591\uc9c8\uc758 \uc790\ub8cc\ub3c4 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0, \uc608\uc804\uc5d0 \ub178\ub4dc\ub85c \uac1c\ubc1c\ud588\uc744 \ub54c \ud480\uc9c0 \ubabb\ud588\ub358 \ub2f5\ub2f5\ud568\uc744 \ub9ce\uc774 \ud574\uc18c\ud588\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["23\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae4a\uac8c \uc790\ubc14\ub97c \uacf5\ubd80\ud574\ubcfc \uc0dd\uac01\uc774\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc5b8\uc5b4\ub97c \ud558\ub098 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ub9ce\uc740 \ub3c4\uc6c0\uc774 \ub418\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc2a4\ud130\ub514",children:"\uc2a4\ud130\ub514"}),"\n",(0,n.jsxs)(r.p,{children:["\uae40\uc601\ud55c\ub2d8\uc758 \uac15\uc758\ub97c \uac70\uc758 \ub2e4 \ub4e4\uc5c8\uc744 \ub54c\ucbe4, \ud56d\uc0c1 \uac15\uc758\uc5d0\uc11c \uc5b8\uae09\ub418\ub294 \ud1a0\ube44\uc758 \uc2a4\ud504\ub9c1\uc744 \uc77d\uc5b4\ubcf4\uace0 \uc2f6\uc5b4\uc84c\uace0",(0,n.jsx)(r.br,{}),"\n","\ud63c\uc790 \uacf5\ubd80\ud558\uae30\uc5d0\ub294 \ub3d9\uae30\ubd80\uc5ec\ub3c4 \ubd80\uc871\ud588\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud130\ub514\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\uc744 \ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uacf5\ubd80\ub97c \ud560 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\uc9c0\ub9cc \ub098\uc5d0\uac8c\ub294 \ub0b4\uc6a9\uc774 \uaf64\ub098 \uc5b4\ub824\uc6cc\uc11c \uc2dc\uac04\uc744 \ub9ce\uc774 \uc18c\ube44\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uac19\uc774 \uc2a4\ud130\ub514\ud558\uc2dc\ub294 \ubd84\uacfc 7\uac1c\uc6d4 \ub3d9\uc548 \uc2a4\ud130\ub514\ub97c \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00 \ucd1d 3\uad8c\uc758 \ucc45\uc744 \uc77d\uc744 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc6b0\uc544\ud55c-\ud14c\ud06c\ucf54\uc2a4",children:"\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4"}),"\n",(0,n.jsxs)(r.p,{children:["\uad70 \ubcf5\ubb34 \uc911\uc77c \ub54c \uc9c0\uc6d0\ud588\ub2e4 \ub5a8\uc5b4\uc9c4 \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ub2e4\uc2dc \uc9c0\uc6d0\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88 \uc5f0\ub3c4\uc5d0 \ucde8\uc5c5\uc744 \ud558\ub294 \uac8c \ubaa9\ud45c\uc600\uc9c0\ub9cc \ub0b4\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud2b9\ubcc4\ud55c \ubb34\uae30\uac00 \uc5c6\ub2e4\ub294 \uac78 \uae68\ub2ec\uc558\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc801\uc9c0 \uc54a\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574 \uc900\ube44\ub97c \ud588\uace0, \uac10\uc0ac\ud558\uac8c\ub3c4 \uc774\ubc88\uc5d0\ub294 \ucd5c\uc885 \ud569\uaca9\uc744 \ud588\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub09c \uc0ac\ub78c\ub4e4\uacfc \uc18c\ud1b5\ud558\uace0, \ud611\uc5c5\ud558\ub294 \ub2a5\ub825\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ud1b5\ud574 \uadf8 \ube48 \ubd80\ubd84\uc744 \ucc44\uc6b0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"2023\ub144\uc5d0\ub294",children:"2023\ub144\uc5d0\ub294"}),"\n",(0,n.jsxs)(r.p,{children:["\ub9c8\uc74c\uc758 \uc5ec\uc720\uac00 \uc5c6\uc5c8\ub358 2022\ub144\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud558\uace0 \uc2f6\uc740 \uac74 \ub9ce\uc9c0\ub9cc, \uc774\ubc88\uc5d0\ub294 \uc5ec\uc720\ub97c \uac00\uc9c0\uace0 \ud560 \uc218 \uc788\ub294 \uac83\uc5d0 \ucd5c\uc120\uc744 \ub2e4\ud574\uc57c\uaca0\ub2e4."]})]})}function u(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>a});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function o(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=n.createContext({}),a=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):o(o({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=a(t),b=s,j=d["".concat(l,".").concat(b)]||d[b]||p[b]||i;return t?n.createElement(j,o(o({ref:r},u),{},{components:t})):n.createElement(j,o({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9286],{8617:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var n=t(85893),s=t(3905);const i={title:"2022\ub144 \ud68c\uace0",slug:"2022-retrospective",tags:["Retrospective"]},o=void 0,c={permalink:"/2022-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",title:"2022\ub144 \ud68c\uace0",description:"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70",date:"2023-01-02T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 2\uc77c",tags:[{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.705,hasTruncateMarker:!1,authors:[],frontMatter:{title:"2022\ub144 \ud68c\uace0",slug:"2022-retrospective",tags:["Retrospective"]},unlisted:!1,prevItem:{title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",permalink:"/book-writer"},nextItem:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",permalink:"/the-essence-of-object-orientation"}},l={authorsImageUrls:[]},a=[{value:"\uc804\uc5ed",id:"\uc804\uc5ed",level:3},{value:"\uc790\ubc14",id:"\uc790\ubc14",level:3},{value:"\uc2a4\ud130\ub514",id:"\uc2a4\ud130\ub514",level:3},{value:"\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4",id:"\uc6b0\uc544\ud55c-\ud14c\ud06c\ucf54\uc2a4",level:3},{value:"2023\ub144\uc5d0\ub294",id:"2023\ub144\uc5d0\ub294",level:3}];function p(e){const r={a:"a",br:"br",h3:"h3",p:"p",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.p,{children:"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70"}),"\n",(0,n.jsx)(r.h3,{id:"\uc804\uc5ed",children:"\uc804\uc5ed"}),"\n",(0,n.jsxs)(r.p,{children:["\uc57d 1\ub144 6\uac1c\uc6d4\uac04\uc758 \uacf5\uad70 \uc815\ubcf4\ubcf4\ud638\ubcd1 \uc0dd\ud65c\uc744 \ub9c8\uce58\uace0 \uc804\uc5ed\uc744 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc870\uae30 \uc804\uc5ed \ub54c\ubb38\uc5d0 2021\ub144 12\uc6d4\uc5d0 \ub098\uc654\uc9c0\ub9cc, \uc2e4\uc81c \uc804\uc5ed \ub0a0\uc9dc\ub294 2022\ub144\uc774\ub2c8 \ud68c\uace0\uc5d0 \uc801\uc5b4\ub3c4 \uc0c1\uad00\uc5c6\uaca0\uc9c0."]}),"\n",(0,n.jsxs)(r.p,{children:["\uc870\uae08 \ub354 \ubbf8\ub798\uc5d0 \ub300\ud55c \uc0dd\uac01\uc744 \ud574\ubcfc\uac78 \uadf8\ub7ac\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc804\uc5ed\uc744 \ud588\uc9c0\ub9cc \ubb50 \ud558\ub098 \uc81c\ub300\ub85c \ud560 \uc904 \uc544\ub294 \uac83\ub3c4 \uc5c6\uc73c\ub2c8 \ub113\uc740 \ubc14\ub2f7\uc18d\uc5d0 \ub369\uadf8\ub7ec\ub2c8 \ub193\uc544\uc9c4 \uae30\ubd84\uc774 \uad1c\ud788 \ub4e4\uc5c8\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc77c\ucc0d \uc0dd\uac01\uc744 \uc815\ub9ac\ud558\uc5ec \ubc29\ud5a5\uc744 \uc7a1\uc9c0 \ubabb\ud588\uae30\uc5d0 \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub0a8\uc558\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc790\ubc14",children:"\uc790\ubc14"}),"\n",(0,n.jsxs)(r.p,{children:["\uc804\uc5ed\uc744 \ud558\uace0 \uc9c4\ub85c\ub97c \uace0\ubbfc\ud558\ub2e4 \ud5a5\ub85c\ub2d8\uc758 ",(0,n.jsx)(r.a,{href:"https://jojoldu.tistory.com/609",children:"\uc790\ubc14 \uacf5\ud654\uad6d"})," \ud3ec\uc2a4\ud305\uc744 \uc77d\uace0 \ub098\uc11c \uc790\ubc14 \uacf5\ubd80\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc720\uba85\ud55c \uc778\ud504\ub7f0\uc758 \uae40\uc601\ud55c\ub2d8\uc758 \uc2a4\ud504\ub9c1 \uac15\uc758\ub3c4 \uc788\uace0, \uc88b\uc740 \uc790\ubc14 \uac1c\ubc1c \uc11c\uc801\uc774 \ub9ce\uc544\uc11c \ub3c5\ud559\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud558\ub2e4 \ubcf4\ub2c8 \uc790\ubc14\uc640 \uc2a4\ud504\ub9c1\uc744 \uacf5\ubd80\ud558\uba74\uc11c \u201c\uc65c \uc9c4\uc791\ud558\uc9c0 \uc54a\uc558\uc9c0\u201d\ub77c\ub294 \uc0dd\uac01\ub3c4 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc591\uc9c8\uc758 \uc790\ub8cc\ub3c4 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0, \uc608\uc804\uc5d0 \ub178\ub4dc\ub85c \uac1c\ubc1c\ud588\uc744 \ub54c \ud480\uc9c0 \ubabb\ud588\ub358 \ub2f5\ub2f5\ud568\uc744 \ub9ce\uc774 \ud574\uc18c\ud588\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["23\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae4a\uac8c \uc790\ubc14\ub97c \uacf5\ubd80\ud574\ubcfc \uc0dd\uac01\uc774\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc5b8\uc5b4\ub97c \ud558\ub098 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ub9ce\uc740 \ub3c4\uc6c0\uc774 \ub418\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc2a4\ud130\ub514",children:"\uc2a4\ud130\ub514"}),"\n",(0,n.jsxs)(r.p,{children:["\uae40\uc601\ud55c\ub2d8\uc758 \uac15\uc758\ub97c \uac70\uc758 \ub2e4 \ub4e4\uc5c8\uc744 \ub54c\ucbe4, \ud56d\uc0c1 \uac15\uc758\uc5d0\uc11c \uc5b8\uae09\ub418\ub294 \ud1a0\ube44\uc758 \uc2a4\ud504\ub9c1\uc744 \uc77d\uc5b4\ubcf4\uace0 \uc2f6\uc5b4\uc84c\uace0",(0,n.jsx)(r.br,{}),"\n","\ud63c\uc790 \uacf5\ubd80\ud558\uae30\uc5d0\ub294 \ub3d9\uae30\ubd80\uc5ec\ub3c4 \ubd80\uc871\ud588\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud130\ub514\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\uc744 \ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uacf5\ubd80\ub97c \ud560 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\uc9c0\ub9cc \ub098\uc5d0\uac8c\ub294 \ub0b4\uc6a9\uc774 \uaf64\ub098 \uc5b4\ub824\uc6cc\uc11c \uc2dc\uac04\uc744 \ub9ce\uc774 \uc18c\ube44\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uac19\uc774 \uc2a4\ud130\ub514\ud558\uc2dc\ub294 \ubd84\uacfc 7\uac1c\uc6d4 \ub3d9\uc548 \uc2a4\ud130\ub514\ub97c \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00 \ucd1d 3\uad8c\uc758 \ucc45\uc744 \uc77d\uc744 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc6b0\uc544\ud55c-\ud14c\ud06c\ucf54\uc2a4",children:"\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4"}),"\n",(0,n.jsxs)(r.p,{children:["\uad70 \ubcf5\ubb34 \uc911\uc77c \ub54c \uc9c0\uc6d0\ud588\ub2e4 \ub5a8\uc5b4\uc9c4 \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ub2e4\uc2dc \uc9c0\uc6d0\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88 \uc5f0\ub3c4\uc5d0 \ucde8\uc5c5\uc744 \ud558\ub294 \uac8c \ubaa9\ud45c\uc600\uc9c0\ub9cc \ub0b4\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud2b9\ubcc4\ud55c \ubb34\uae30\uac00 \uc5c6\ub2e4\ub294 \uac78 \uae68\ub2ec\uc558\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc801\uc9c0 \uc54a\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574 \uc900\ube44\ub97c \ud588\uace0, \uac10\uc0ac\ud558\uac8c\ub3c4 \uc774\ubc88\uc5d0\ub294 \ucd5c\uc885 \ud569\uaca9\uc744 \ud588\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub09c \uc0ac\ub78c\ub4e4\uacfc \uc18c\ud1b5\ud558\uace0, \ud611\uc5c5\ud558\ub294 \ub2a5\ub825\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ud1b5\ud574 \uadf8 \ube48 \ubd80\ubd84\uc744 \ucc44\uc6b0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"2023\ub144\uc5d0\ub294",children:"2023\ub144\uc5d0\ub294"}),"\n",(0,n.jsxs)(r.p,{children:["\ub9c8\uc74c\uc758 \uc5ec\uc720\uac00 \uc5c6\uc5c8\ub358 2022\ub144\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud558\uace0 \uc2f6\uc740 \uac74 \ub9ce\uc9c0\ub9cc, \uc774\ubc88\uc5d0\ub294 \uc5ec\uc720\ub97c \uac00\uc9c0\uace0 \ud560 \uc218 \uc788\ub294 \uac83\uc5d0 \ucd5c\uc120\uc744 \ub2e4\ud574\uc57c\uaca0\ub2e4."]})]})}function u(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>a});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function o(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=n.createContext({}),a=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):o(o({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=a(t),b=s,j=d["".concat(l,".").concat(b)]||d[b]||p[b]||i;return t?n.createElement(j,o(o({ref:r},u),{},{components:t})):n.createElement(j,o({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/9bad5ae7.fa0f41bc.js b/assets/js/9bad5ae7.eedb04d6.js similarity index 98% rename from assets/js/9bad5ae7.fa0f41bc.js rename to assets/js/9bad5ae7.eedb04d6.js index f2cb67078..3e134ee75 100644 --- a/assets/js/9bad5ae7.fa0f41bc.js +++ b/assets/js/9bad5ae7.eedb04d6.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2153],{27555:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>i,metadata:()=>l,toc:()=>d});var r=t(85893),c=t(3905);const i={title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"innodb-lock",tags:["DataBase","Lock","InnoDB"]},s=void 0,l={permalink:"/innodb-lock",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",source:"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",description:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",date:"2023-04-07T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 7\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Lock",permalink:"/tags/lock"},{label:"InnoDB",permalink:"/tags/inno-db"}],readingTime:5.805,hasTruncateMarker:!1,authors:[],frontMatter:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"innodb-lock",tags:["DataBase","Lock","InnoDB"]},unlisted:!1,prevItem:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",permalink:"/book-leadership-and-self-deception"},nextItem:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/mysql-lock"}},o={authorsImageUrls:[]},d=[{value:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",id:"innodb-\uc2a4\ud1a0\ub9ac\uc9c0-\uc5d4\uc9c4\uc758-\uc7a0\uae08",level:2},{value:"Shared & Exclusive Locks",id:"shared--exclusive-locks",level:3},{value:"Intention Locks",id:"intention-locks",level:3},{value:"Record Locks",id:"record-locks",level:3},{value:"Gap Locks",id:"gap-locks",level:3},{value:"Next-Key Locks",id:"next-key-locks",level:3},{value:"AUTO-INC Locks",id:"auto-inc-locks",level:3},{value:"\uc7a0\uae08 \uc608\uc2dc",id:"\uc7a0\uae08-\uc608\uc2dc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function a(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,c.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"innodb-\uc2a4\ud1a0\ub9ac\uc9c0-\uc5d4\uc9c4\uc758-\uc7a0\uae08",children:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08"}),"\n",(0,r.jsxs)(n.p,{children:["MySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08\uacfc \ubcc4\uac1c\ub85c \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub0b4\ubd80\uc5d0\uc11c \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubcf4\ud1b5 \uba85\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\ub294 \ub4dc\ubb3c\uace0, \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ubb35\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc774 \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub3d9\uc2dc\uc131 \uc81c\uc5b4 \ubc29\uc2dd\uc5d0\ub294 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uacfc \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc774 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB\ub294 \uae30\ubcf8\uc801\uc73c\ub85c MVCC(\ub2e4\uc911 \ubc84\uc804 \ub3d9\uc2dc\uc131 \uc81c\uc5b4)\ub97c \ud1b5\ud574 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uace0 \ub77d\uc744 \ud1b5\ud574 \ud2b9\uc815 \uc0c1\ud669\uc5d0\uc11c \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.admonition,{title:"\ub099\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(OCC, Optimistic concurrency control)",type:"note",children:(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \uc11c\ub85c \ucda9\ub3cc\ud558\uc9c0 \uc54a\ub294\ub2e4\uace0 \uac00\uc815\ud558\ub294 \ubc29\uc2dd"})}),"\n",(0,r.jsx)(n.admonition,{title:"\ube44\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(PCC, Pessimistic Concurrency Control)",type:"note",children:(0,r.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc774 \ucda9\ub3cc\ud558\ub294 \uac00\uc815\ud558\uc5d0 \uc7a0\uae08\uc744 \uac70\ub294 \ubc29\uc2dd",(0,r.jsx)(n.br,{}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c\xa0Shared Lock, Exclusive Lock\uc744 \ud1b5\ud574 \uc774\ub97c \uad6c\ud604\ud55c\ub2e4."]})}),"\n",(0,r.jsx)(n.h3,{id:"shared--exclusive-locks",children:"Shared & Exclusive Locks"}),"\n",(0,r.jsx)(n.p,{children:"InnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc218\ud589\ud560 \ub54c \uacf5\uc720 \uc7a0\uae08\uacfc \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uacf5\uc720 \uc7a0\uae08(S, shared lock)"})}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130 \uc870\ud68c\ub97c \uc704\ud55c \ub77d, \uc77d\uae30 \uc7a0\uae08(read lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uae30\uac00 \uac00\ub2a5\ud558\uc9c0\ub9cc, \uc4f0\uae30\ub294 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608) ",(0,r.jsx)(n.code,{children:"SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;"})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\ubc30\ud0c0\uc801 \uc7a0\uae08(X, exclusive lock)"})}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130 \ubcc0\uacbd\uc744 \uc704\ud55c \ub77d, \uc4f0\uae30 \uc7a0\uae08(write lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub77d\uc744 \uac74 \ud2b8\ub79c\uc7ad\uc158\ub9cc\uc774 \ud574\ub2f9 \ub370\uc774\ud130\uc5d0 \uc811\uadfc \uac00\ub2a5\ud558\ub2e4. \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \uc77d\uae30, \uc4f0\uae30\uac00 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608) ",(0,r.jsx)(n.code,{children:"SELECT * FROM table_name WHERE id = 1 FOR UPDATE;"})]}),"\n",(0,r.jsx)(n.h3,{id:"intention-locks",children:"Intention Locks"}),"\n",(0,r.jsxs)(n.p,{children:["InnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uacfc \ud14c\uc774\ube14 \uc7a0\uae08\uc758 \uacf5\uc874\uc744 \uc704\ud574 \uc778\ud14d\uc158 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ub85c\uc6b0\uc5d0 \ub300\ud574\uc11c \ub098\uc911\uc5d0 \uc694\uccad\ub418\ub294 \uac83\uc774 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uc7a0\uae08\uc778\uc9c0 \uac00\ub9ac\ud0a4\uae30 \uc704\ud574 \uc0ac\uc6a9\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 \uc778\ud150\uc158 \uc7a0\uae08\uc744 \uba3c\uc800 \ud68d\ub4dd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc778\ud150\uc158 \ub77d\uc740 \uae30\ubcf8\uc801\uc73c\ub85c \ucda9\ub3cc\uc744 \ubc29\uc9c0\ud558\uace0 \ub370\ub4dc\ub77d\uc744 \ubc29\uc9c0\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uc778\ud150\uc158 \uacf5\uc720 \uc7a0\uae08(IS, intention shared lock)"})}),"\n",(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \uacf5\uc720 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uc778\ud150\uc158 \ubc30\ud0c0\uc801 \uc7a0\uae08(IX, intention exclusive lock)"})}),"\n",(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:"** \uc7a0\uae08\uac04\uc758 \ud638\ud658\uc131 **"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{}),(0,r.jsx)(n.th,{children:"X"}),(0,r.jsx)(n.th,{children:"IX"}),(0,r.jsx)(n.th,{children:"S"}),(0,r.jsx)(n.th,{children:"IS"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"X"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"IX"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"S"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"IS"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"record-locks",children:"Record Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc \uc790\uccb4\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc740 \ub808\ucf54\ub4dc \uc790\uccb4\uac00 \uc544\ub2c8\ub77c \uc778\ub371\uc2a4\uc758 \ub808\ucf54\ub4dc\ub97c \uc7a0\uadfc\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"gap-locks",children:"Gap Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub808\ucf54\ub4dc\uc640 \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\uc5d0 \uc0c8\ub85c\uc6b4 \ub808\ucf54\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \uc81c\uc5b4\ud558\uace0, \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc758 \uc77c\ubd80\ub85c \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"next-key-locks",children:"Next-Key Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ud32c\ud140 \ub9ac\ub4dc\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uc7a0\uae08\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"auto-inc-locks",children:"AUTO-INC Locks"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"AUTO_INCREMENT"})," \uce7c\ub9bc\uc774 \uc0ac\uc6a9\ub41c \ud14c\uc774\ube14\uc5d0 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \ub808\ucf54\ub4dc\uac00 ",(0,r.jsx)(n.code,{children:"INSERT"}),"\ub418\ub294 \uacbd\uc6b0, \uac01 \ub808\ucf54\ub4dc\ub294 \uc911\ubcf5\ub418\uc9c0 \uc54a\uace0 \uc800\uc7a5\ub41c \uc21c\uc11c\ub300\ub85c \uc99d\uac00\ud558\ub294 \uc77c\ub828\ubc88\ud638 \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB \ub294 \ub0b4\ubd80\uc801\uc73c\ub85c AUTO-INC \ub77d\uc774\ub77c\uace0 \ud558\ub294 \ud14c\uc774\ube14 \uc218\uc900\uc758 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uacfc \uad00\uacc4 \uc5c6\uc774 ",(0,r.jsx)(n.code,{children:"INSERT"}),"\ub098 ",(0,r.jsx)(n.code,{children:"REPLACE"})," \ubb38\uc7a5\uc5d0\uc11c ",(0,r.jsx)(n.code,{children:"AUTO_INCREMENT"})," \uac12\uc744 \uac00\uc838\uc624\ub294 \uc21c\uac04\ub9cc \ub77d\uc774 \uac78\ub838\ub2e4\uac00 \ud574\uc81c\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc7a0\uae08-\uc608\uc2dc",children:"\uc7a0\uae08 \uc608\uc2dc"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-sql",children:"-- \ub808\ucf54\ub4dc\ub294 id \uae30\uc900 10, 20, 30, 40, 50\uc774 \uc788\ub2e4\uace0 \uac00\uc815\n-- Record Locks: 10\uc5d0 \ub300\ud574 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id = 10 for update;\n\n-- Gap Locks: 51\ubd80\ud130 PositiveInfinity\uae4c\uc9c0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id > 100 for update;\n\n-- Next-Key Locks: 21\ubd80\ud130 30, 31\ubd80\ud130 40\uc5d0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id BETWEEN 25 AND 35 for update;\n"})}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.ibm.com/docs/en/rational-clearquest/9.0.0?topic=clearquest-optimistic-pessimistic-record-locking",children:"Optimistic and Pessimistic record locking, IBM"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://cecil1018.wordpress.com/2016/06/18/mysql-innodb-locks/",children:"MySQL Innodb Locks, cecil1018"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html",children:"MySQL 8.0 InnoDB Locks, MySQL"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html",children:"Locks Set by Different SQL Statements in InnoDB, MySQL"})]})]})}function h(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var r=t(67294);function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(c[t]=e[t]);return c}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(c[t]=e[t])}return c}var o=r.createContext({}),d=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},a={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},h=r.forwardRef((function(e,n){var t=e.components,c=e.mdxType,i=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),x=d(t),j=c,p=x["".concat(o,".").concat(j)]||x[j]||a[j]||i;return t?r.createElement(p,s(s({ref:n},h),{},{components:t})):r.createElement(p,s({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2153],{27555:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>i,metadata:()=>l,toc:()=>d});var r=t(85893),c=t(3905);const i={title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"innodb-lock",tags:["DataBase","Lock","InnoDB"]},s=void 0,l={permalink:"/innodb-lock",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",source:"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",description:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",date:"2023-04-07T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 7\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Lock",permalink:"/tags/lock"},{label:"InnoDB",permalink:"/tags/inno-db"}],readingTime:5.805,hasTruncateMarker:!1,authors:[],frontMatter:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"innodb-lock",tags:["DataBase","Lock","InnoDB"]},unlisted:!1,prevItem:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/mysql-lock"},nextItem:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",permalink:"/book-leadership-and-self-deception"}},o={authorsImageUrls:[]},d=[{value:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",id:"innodb-\uc2a4\ud1a0\ub9ac\uc9c0-\uc5d4\uc9c4\uc758-\uc7a0\uae08",level:2},{value:"Shared & Exclusive Locks",id:"shared--exclusive-locks",level:3},{value:"Intention Locks",id:"intention-locks",level:3},{value:"Record Locks",id:"record-locks",level:3},{value:"Gap Locks",id:"gap-locks",level:3},{value:"Next-Key Locks",id:"next-key-locks",level:3},{value:"AUTO-INC Locks",id:"auto-inc-locks",level:3},{value:"\uc7a0\uae08 \uc608\uc2dc",id:"\uc7a0\uae08-\uc608\uc2dc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function a(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,c.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"innodb-\uc2a4\ud1a0\ub9ac\uc9c0-\uc5d4\uc9c4\uc758-\uc7a0\uae08",children:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08"}),"\n",(0,r.jsxs)(n.p,{children:["MySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08\uacfc \ubcc4\uac1c\ub85c \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub0b4\ubd80\uc5d0\uc11c \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubcf4\ud1b5 \uba85\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\ub294 \ub4dc\ubb3c\uace0, \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ubb35\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc774 \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub3d9\uc2dc\uc131 \uc81c\uc5b4 \ubc29\uc2dd\uc5d0\ub294 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uacfc \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc774 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB\ub294 \uae30\ubcf8\uc801\uc73c\ub85c MVCC(\ub2e4\uc911 \ubc84\uc804 \ub3d9\uc2dc\uc131 \uc81c\uc5b4)\ub97c \ud1b5\ud574 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uace0 \ub77d\uc744 \ud1b5\ud574 \ud2b9\uc815 \uc0c1\ud669\uc5d0\uc11c \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.admonition,{title:"\ub099\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(OCC, Optimistic concurrency control)",type:"note",children:(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \uc11c\ub85c \ucda9\ub3cc\ud558\uc9c0 \uc54a\ub294\ub2e4\uace0 \uac00\uc815\ud558\ub294 \ubc29\uc2dd"})}),"\n",(0,r.jsx)(n.admonition,{title:"\ube44\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(PCC, Pessimistic Concurrency Control)",type:"note",children:(0,r.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc774 \ucda9\ub3cc\ud558\ub294 \uac00\uc815\ud558\uc5d0 \uc7a0\uae08\uc744 \uac70\ub294 \ubc29\uc2dd",(0,r.jsx)(n.br,{}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c\xa0Shared Lock, Exclusive Lock\uc744 \ud1b5\ud574 \uc774\ub97c \uad6c\ud604\ud55c\ub2e4."]})}),"\n",(0,r.jsx)(n.h3,{id:"shared--exclusive-locks",children:"Shared & Exclusive Locks"}),"\n",(0,r.jsx)(n.p,{children:"InnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc218\ud589\ud560 \ub54c \uacf5\uc720 \uc7a0\uae08\uacfc \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uacf5\uc720 \uc7a0\uae08(S, shared lock)"})}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130 \uc870\ud68c\ub97c \uc704\ud55c \ub77d, \uc77d\uae30 \uc7a0\uae08(read lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uae30\uac00 \uac00\ub2a5\ud558\uc9c0\ub9cc, \uc4f0\uae30\ub294 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608) ",(0,r.jsx)(n.code,{children:"SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;"})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\ubc30\ud0c0\uc801 \uc7a0\uae08(X, exclusive lock)"})}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130 \ubcc0\uacbd\uc744 \uc704\ud55c \ub77d, \uc4f0\uae30 \uc7a0\uae08(write lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub77d\uc744 \uac74 \ud2b8\ub79c\uc7ad\uc158\ub9cc\uc774 \ud574\ub2f9 \ub370\uc774\ud130\uc5d0 \uc811\uadfc \uac00\ub2a5\ud558\ub2e4. \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \uc77d\uae30, \uc4f0\uae30\uac00 \ubd88\uac00\ub2a5\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608) ",(0,r.jsx)(n.code,{children:"SELECT * FROM table_name WHERE id = 1 FOR UPDATE;"})]}),"\n",(0,r.jsx)(n.h3,{id:"intention-locks",children:"Intention Locks"}),"\n",(0,r.jsxs)(n.p,{children:["InnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uacfc \ud14c\uc774\ube14 \uc7a0\uae08\uc758 \uacf5\uc874\uc744 \uc704\ud574 \uc778\ud14d\uc158 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ub85c\uc6b0\uc5d0 \ub300\ud574\uc11c \ub098\uc911\uc5d0 \uc694\uccad\ub418\ub294 \uac83\uc774 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uc7a0\uae08\uc778\uc9c0 \uac00\ub9ac\ud0a4\uae30 \uc704\ud574 \uc0ac\uc6a9\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 \uc778\ud150\uc158 \uc7a0\uae08\uc744 \uba3c\uc800 \ud68d\ub4dd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc778\ud150\uc158 \ub77d\uc740 \uae30\ubcf8\uc801\uc73c\ub85c \ucda9\ub3cc\uc744 \ubc29\uc9c0\ud558\uace0 \ub370\ub4dc\ub77d\uc744 \ubc29\uc9c0\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uc778\ud150\uc158 \uacf5\uc720 \uc7a0\uae08(IS, intention shared lock)"})}),"\n",(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \uacf5\uc720 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"\uc778\ud150\uc158 \ubc30\ud0c0\uc801 \uc7a0\uae08(IX, intention exclusive lock)"})}),"\n",(0,r.jsx)(n.p,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:"** \uc7a0\uae08\uac04\uc758 \ud638\ud658\uc131 **"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{}),(0,r.jsx)(n.th,{children:"X"}),(0,r.jsx)(n.th,{children:"IX"}),(0,r.jsx)(n.th,{children:"S"}),(0,r.jsx)(n.th,{children:"IS"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"X"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"IX"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"S"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"IS"}),(0,r.jsx)(n.td,{children:"Conflict"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"}),(0,r.jsx)(n.td,{children:"Compatible"})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"record-locks",children:"Record Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc \uc790\uccb4\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc740 \ub808\ucf54\ub4dc \uc790\uccb4\uac00 \uc544\ub2c8\ub77c \uc778\ub371\uc2a4\uc758 \ub808\ucf54\ub4dc\ub97c \uc7a0\uadfc\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"gap-locks",children:"Gap Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub808\ucf54\ub4dc\uc640 \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\uc5d0 \uc0c8\ub85c\uc6b4 \ub808\ucf54\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \uc81c\uc5b4\ud558\uace0, \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc758 \uc77c\ubd80\ub85c \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"next-key-locks",children:"Next-Key Locks"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ud32c\ud140 \ub9ac\ub4dc\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uc7a0\uae08\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"auto-inc-locks",children:"AUTO-INC Locks"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"AUTO_INCREMENT"})," \uce7c\ub9bc\uc774 \uc0ac\uc6a9\ub41c \ud14c\uc774\ube14\uc5d0 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \ub808\ucf54\ub4dc\uac00 ",(0,r.jsx)(n.code,{children:"INSERT"}),"\ub418\ub294 \uacbd\uc6b0, \uac01 \ub808\ucf54\ub4dc\ub294 \uc911\ubcf5\ub418\uc9c0 \uc54a\uace0 \uc800\uc7a5\ub41c \uc21c\uc11c\ub300\ub85c \uc99d\uac00\ud558\ub294 \uc77c\ub828\ubc88\ud638 \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","InnoDB \ub294 \ub0b4\ubd80\uc801\uc73c\ub85c AUTO-INC \ub77d\uc774\ub77c\uace0 \ud558\ub294 \ud14c\uc774\ube14 \uc218\uc900\uc758 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uacfc \uad00\uacc4 \uc5c6\uc774 ",(0,r.jsx)(n.code,{children:"INSERT"}),"\ub098 ",(0,r.jsx)(n.code,{children:"REPLACE"})," \ubb38\uc7a5\uc5d0\uc11c ",(0,r.jsx)(n.code,{children:"AUTO_INCREMENT"})," \uac12\uc744 \uac00\uc838\uc624\ub294 \uc21c\uac04\ub9cc \ub77d\uc774 \uac78\ub838\ub2e4\uac00 \ud574\uc81c\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc7a0\uae08-\uc608\uc2dc",children:"\uc7a0\uae08 \uc608\uc2dc"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-sql",children:"-- \ub808\ucf54\ub4dc\ub294 id \uae30\uc900 10, 20, 30, 40, 50\uc774 \uc788\ub2e4\uace0 \uac00\uc815\n-- Record Locks: 10\uc5d0 \ub300\ud574 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id = 10 for update;\n\n-- Gap Locks: 51\ubd80\ud130 PositiveInfinity\uae4c\uc9c0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id > 100 for update;\n\n-- Next-Key Locks: 21\ubd80\ud130 30, 31\ubd80\ud130 40\uc5d0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\nSELECT * FROM table_name where id BETWEEN 25 AND 35 for update;\n"})}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.ibm.com/docs/en/rational-clearquest/9.0.0?topic=clearquest-optimistic-pessimistic-record-locking",children:"Optimistic and Pessimistic record locking, IBM"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://cecil1018.wordpress.com/2016/06/18/mysql-innodb-locks/",children:"MySQL Innodb Locks, cecil1018"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html",children:"MySQL 8.0 InnoDB Locks, MySQL"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html",children:"Locks Set by Different SQL Statements in InnoDB, MySQL"})]})]})}function h(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var r=t(67294);function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(c[t]=e[t]);return c}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(c[t]=e[t])}return c}var o=r.createContext({}),d=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},a={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},h=r.forwardRef((function(e,n){var t=e.components,c=e.mdxType,i=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),x=d(t),j=c,p=x["".concat(o,".").concat(j)]||x[j]||a[j]||i;return t?r.createElement(p,s(s({ref:n},h),{},{components:t})):r.createElement(p,s({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/9d1fd2b0.80d4a2ec.js b/assets/js/9d1fd2b0.dffb724e.js similarity index 96% rename from assets/js/9d1fd2b0.80d4a2ec.js rename to assets/js/9d1fd2b0.dffb724e.js index d432ef7b7..76e1f679e 100644 --- a/assets/js/9d1fd2b0.80d4a2ec.js +++ b/assets/js/9d1fd2b0.dffb724e.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7972],{30138:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>s,metadata:()=>i,toc:()=>l});var n=t(85893),o=t(3905);const s={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",slug:"woowacourse-level2-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/woowacourse-level2-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",description:"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.",date:"2023-06-11T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:2.545,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",slug:"woowacourse-level2-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"Docusaurus",permalink:"/docusaurus"},nextItem:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",permalink:"/level2-interview-retrospective"}},a={authorsImageUrls:[]},l=[{value:"\ud559\uc2b5",id:"\ud559\uc2b5",level:3},{value:"\uc218\uba74",id:"\uc218\uba74",level:3},{value:"\ud611\uc5c5",id:"\ud611\uc5c5",level:3},{value:"\ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70",id:"\ub808\ubca8-2\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70",level:3}];function p(e){const r={br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(r.p,{children:["23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ube60\ub974\uac8c \uc9c0\ub098\uac00\uc11c \uc870\uae08 \uc544\uc27d\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud559\uc2b5",children:"\ud559\uc2b5"}),"\n",(0,n.jsxs)(r.p,{children:["\ud68c\uace0\ub97c \uc791\uc131\ud558\uae30 \uc804\uc5d0 \ub808\ubca8 2 \ub3d9\uc548 \ubcf4\ub0c8\ub358 PR\uacfc \ud68c\uace0\ub97c \ucb49 \uc77d\uc5b4\ubd24\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud56d\uc0c1 \uc544\uc26c\uc6b4 \uacf3\uc740 \uc788\uae30 \ub9c8\ub828\uc774\uc9c0\ub9cc, \uc798 \ud559\uc2b5\ud55c \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc744 \ud558\uba74\uc11c \uae30\uc220\uc744 \uc5b4\ub5bb\uac8c \uc120\ud0dd\ud558\uace0, \uc801\uc6a9\ud560 \uac83\uc778\uc9c0 \uace0\ubbfc\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \uaf64\ub098 \ub9ce\uc740 \uc131\uc7a5\uc744 \ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\uace0\ubbfc\uc740 \uae4a\uc5c8\uc9c0\ub9cc \uc774\ub860\uc801\uc778 \ud559\uc2b5\uc774 \ubd80\uc871\ud55c \ub808\ubca8 2\uc600\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc29\ud559 \uadf8\ub9ac\uace0 \ub808\ubca8 3 \ub54c\ub294 \uc870\uae08 \ub354 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc744 \ud559\uc2b5\ud558\ub294\ub370 \uc9d1\uc911\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\uc810\ucc28 \ud559\uc2b5 \ubc94\uc704\uac00 \ub113\uc5b4\uc9c0\uba74\uc11c \uc790\uc5f0\uc2a4\ub7fd\uac8c \ubaa8\ub974\ub294 \ub0b4\uc6a9\uc774 \uc313\uc5ec\uac04\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud544\uc694\ud55c \ub0b4\uc6a9\uc740 \uc55e\uc73c\ub85c \ucc9c\ucc9c\ud788 \ud559\uc2b5\ud558\uba74 \ub418\ub2c8\uae4c \uc870\uae09\ud574\uc9c0\uc9c0 \ub9d0\uc544\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc218\uba74",children:"\uc218\uba74"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 2\ub97c \uc9c4\ud589\ud558\ub294 \ub3d9\uc548 \uc218\uba74\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\uc5c8\uace0, \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \uadf8\ub0a0\uc758 \ucee8\ub514\uc158\uc744 \ub9ce\uc774 \uc88c\uc6b0\ud588\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc218\uba74 \uc2dc\uac04\uc744 \ub298\ub9ac\uace0, \uc88b\uc740 \uc218\uba74 \uc2b5\uad00\uc744 \uac00\uc9c0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud611\uc5c5",children:"\ud611\uc5c5"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 2 \ub9c8\uc9c0\ub9c9\uc5d0 \ud611\uc5c5 \ubbf8\uc158\uc774 \uc788\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc9c0\uae08\uae4c\uc9c0\ub294 \ubc31\uc5d4\ub4dc \ud06c\ub8e8\ub4e4\uacfc \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \ud611\uc5c5\uc744 \uacbd\ud5d8\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \ud504\ub7f0\ud2b8\uc5d4\ub4dc \ud06c\ub8e8\uc640 \ud611\uc5c5\uc744 \ud588\ub2e4. \uc18c\ud1b5\uc740 \uc798 \ub41c \uac83 \uac19\uc9c0\ub9cc API \uba85\uc138\ub97c \uc815\ud558\ub294 \ubd80\ubd84\uc774 \uc544\uc9c1 \ubbf8\uc219\ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 3 \ub54c\ubd80\ud130 \ubcf8\uaca9\uc801\uc73c\ub85c \ud504\ub85c\uc81d\ud2b8\uac00 \uc2dc\uc791\ub41c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud300\uc744 \uc704\ud574 \uc5b4\ub5a4 \uac83\uc744 \ud560 \uc218 \uc788\uc744\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud574\ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ub808\ubca8-2\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70",children:"\ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70"}),"\n",(0,n.jsx)(r.p,{children:"\ud68c\uace0 \uc791\uc131\ud558\uba74\uc11c \ub808\ubca8 2\uc5d0\uc11c \ud588\ub358 \uac83\ub4e4\uc744 \ubc18\ucd94\ud574 \ubd24\ub294\ub370 \ubd80\uc871\ud55c \uc810\uc740 \ub9ce\uc558\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \uac00\uace0 \uc788\ub294 \uac83 \uac19\ub2e4.\n\uc77d\uace0 \uc2f6\uc740 \ucc45\ub3c4 \uc77d\uace0, \ubd80\uc871\ud55c \ubd80\ubd84 \ucc44\uc6b0\uba74\uc11c \uc26c\uc5b4\uc57c\uaca0\ub2e4."})]})}function u(e={}){const{wrapper:r}={...(0,o.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function s(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,s=e.originalType,a=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),d=l(t),h=o,b=d["".concat(a,".").concat(h)]||d[h]||p[h]||s;return t?n.createElement(b,c(c({ref:r},u),{},{components:t})):n.createElement(b,c({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7972],{30138:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>s,metadata:()=>i,toc:()=>l});var n=t(85893),o=t(3905);const s={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",slug:"woowacourse-level2-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/woowacourse-level2-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",description:"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.",date:"2023-06-11T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:2.545,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",slug:"woowacourse-level2-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",permalink:"/level2-interview-retrospective"},nextItem:{title:"Docusaurus",permalink:"/docusaurus"}},a={authorsImageUrls:[]},l=[{value:"\ud559\uc2b5",id:"\ud559\uc2b5",level:3},{value:"\uc218\uba74",id:"\uc218\uba74",level:3},{value:"\ud611\uc5c5",id:"\ud611\uc5c5",level:3},{value:"\ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70",id:"\ub808\ubca8-2\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70",level:3}];function p(e){const r={br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(r.p,{children:["23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ube60\ub974\uac8c \uc9c0\ub098\uac00\uc11c \uc870\uae08 \uc544\uc27d\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud559\uc2b5",children:"\ud559\uc2b5"}),"\n",(0,n.jsxs)(r.p,{children:["\ud68c\uace0\ub97c \uc791\uc131\ud558\uae30 \uc804\uc5d0 \ub808\ubca8 2 \ub3d9\uc548 \ubcf4\ub0c8\ub358 PR\uacfc \ud68c\uace0\ub97c \ucb49 \uc77d\uc5b4\ubd24\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud56d\uc0c1 \uc544\uc26c\uc6b4 \uacf3\uc740 \uc788\uae30 \ub9c8\ub828\uc774\uc9c0\ub9cc, \uc798 \ud559\uc2b5\ud55c \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubbf8\uc158\uc744 \ud558\uba74\uc11c \uae30\uc220\uc744 \uc5b4\ub5bb\uac8c \uc120\ud0dd\ud558\uace0, \uc801\uc6a9\ud560 \uac83\uc778\uc9c0 \uace0\ubbfc\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \uaf64\ub098 \ub9ce\uc740 \uc131\uc7a5\uc744 \ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\uace0\ubbfc\uc740 \uae4a\uc5c8\uc9c0\ub9cc \uc774\ub860\uc801\uc778 \ud559\uc2b5\uc774 \ubd80\uc871\ud55c \ub808\ubca8 2\uc600\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc29\ud559 \uadf8\ub9ac\uace0 \ub808\ubca8 3 \ub54c\ub294 \uc870\uae08 \ub354 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc744 \ud559\uc2b5\ud558\ub294\ub370 \uc9d1\uc911\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\uc810\ucc28 \ud559\uc2b5 \ubc94\uc704\uac00 \ub113\uc5b4\uc9c0\uba74\uc11c \uc790\uc5f0\uc2a4\ub7fd\uac8c \ubaa8\ub974\ub294 \ub0b4\uc6a9\uc774 \uc313\uc5ec\uac04\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud544\uc694\ud55c \ub0b4\uc6a9\uc740 \uc55e\uc73c\ub85c \ucc9c\ucc9c\ud788 \ud559\uc2b5\ud558\uba74 \ub418\ub2c8\uae4c \uc870\uae09\ud574\uc9c0\uc9c0 \ub9d0\uc544\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc218\uba74",children:"\uc218\uba74"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 2\ub97c \uc9c4\ud589\ud558\ub294 \ub3d9\uc548 \uc218\uba74\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\uc5c8\uace0, \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \uadf8\ub0a0\uc758 \ucee8\ub514\uc158\uc744 \ub9ce\uc774 \uc88c\uc6b0\ud588\ub358 \uac83 \uac19\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc218\uba74 \uc2dc\uac04\uc744 \ub298\ub9ac\uace0, \uc88b\uc740 \uc218\uba74 \uc2b5\uad00\uc744 \uac00\uc9c0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud611\uc5c5",children:"\ud611\uc5c5"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 2 \ub9c8\uc9c0\ub9c9\uc5d0 \ud611\uc5c5 \ubbf8\uc158\uc774 \uc788\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc9c0\uae08\uae4c\uc9c0\ub294 \ubc31\uc5d4\ub4dc \ud06c\ub8e8\ub4e4\uacfc \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \ud611\uc5c5\uc744 \uacbd\ud5d8\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \ud504\ub7f0\ud2b8\uc5d4\ub4dc \ud06c\ub8e8\uc640 \ud611\uc5c5\uc744 \ud588\ub2e4. \uc18c\ud1b5\uc740 \uc798 \ub41c \uac83 \uac19\uc9c0\ub9cc API \uba85\uc138\ub97c \uc815\ud558\ub294 \ubd80\ubd84\uc774 \uc544\uc9c1 \ubbf8\uc219\ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 3 \ub54c\ubd80\ud130 \ubcf8\uaca9\uc801\uc73c\ub85c \ud504\ub85c\uc81d\ud2b8\uac00 \uc2dc\uc791\ub41c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud300\uc744 \uc704\ud574 \uc5b4\ub5a4 \uac83\uc744 \ud560 \uc218 \uc788\uc744\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud574\ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ub808\ubca8-2\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70",children:"\ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70"}),"\n",(0,n.jsx)(r.p,{children:"\ud68c\uace0 \uc791\uc131\ud558\uba74\uc11c \ub808\ubca8 2\uc5d0\uc11c \ud588\ub358 \uac83\ub4e4\uc744 \ubc18\ucd94\ud574 \ubd24\ub294\ub370 \ubd80\uc871\ud55c \uc810\uc740 \ub9ce\uc558\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \uac00\uace0 \uc788\ub294 \uac83 \uac19\ub2e4.\n\uc77d\uace0 \uc2f6\uc740 \ucc45\ub3c4 \uc77d\uace0, \ubd80\uc871\ud55c \ubd80\ubd84 \ucc44\uc6b0\uba74\uc11c \uc26c\uc5b4\uc57c\uaca0\ub2e4."})]})}function u(e={}){const{wrapper:r}={...(0,o.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function s(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,s=e.originalType,a=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),d=l(t),h=o,b=d["".concat(a,".").concat(h)]||d[h]||p[h]||s;return t?n.createElement(b,c(c({ref:r},u),{},{components:t})):n.createElement(b,c({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/9e2e3982.6ece4d4c.js b/assets/js/9e2e3982.247afb43.js similarity index 97% rename from assets/js/9e2e3982.6ece4d4c.js rename to assets/js/9e2e3982.247afb43.js index 6b7efde37..d85e90e42 100644 --- a/assets/js/9e2e3982.6ece4d4c.js +++ b/assets/js/9e2e3982.247afb43.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7617],{15448:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>l,metadata:()=>s,toc:()=>o});var r=n(85893),i=n(3905);const l={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",slug:"route-image-intro",tags:["image","awt"]},a=void 0,s={permalink:"/route-image-intro",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",source:"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",description:"./route.png",date:"2023-07-27T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 27\uc77c",tags:[{label:"image",permalink:"/tags/image"},{label:"awt",permalink:"/tags/awt"}],readingTime:5.865,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",slug:"route-image-intro",tags:["image","awt"]},unlisted:!1,prevItem:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",permalink:"/mock-static-method"},nextItem:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",permalink:"/java-spring-springboot"}},c={authorsImageUrls:[]},o=[{value:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784",id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc758-\ucc45\uc784",level:3},{value:"\uace0\ub824\ud55c \uae30\uc220",id:"\uace0\ub824\ud55c-\uae30\uc220",level:3},{value:"Python & Matplotlib",id:"python--matplotlib",level:2},{value:"Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac",id:"java-awt-\uc774\uc678\uc758-\ub77c\uc774\ube0c\ub7ec\ub9ac",level:3},{value:"Java & AWT(Abstract Window Toolkit)",id:"java--awtabstract-window-toolkit",level:3},{value:"\uae30\uc220 \uc120\ud0dd",id:"\uae30\uc220-\uc120\ud0dd",level:3},{value:"\uc720\uc9c0 \ubcf4\uc218",id:"\uc720\uc9c0-\ubcf4\uc218",level:3},{value:"\ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00",id:"\ub808\ubca8-3\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70-\ub0b4\uc6a9-\ucd94\uac00",level:3}];function d(e){const t={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"./route.png",src:n(29632).Z+"",width:"1014",height:"902"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc758-\ucc45\uc784",children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784"}),"\n",(0,r.jsxs)(t.p,{children:["\uc704 \uc640\uc774\uc5b4 \ud504\ub808\uc784\uc5d0\uc11c ",(0,r.jsx)(t.code,{children:"\uc5ec\ud589 \ud788\uc2a4\ud1a0\ub9ac"}),"\uc640 ",(0,r.jsx)(t.code,{children:"\uc5ec\ud589\uc5d0 \ub300\ud55c \uac10\uc0c1\uc744 \uc704\ud55c \uacbd\ub85c \uc774\ubbf8\uc9c0"}),"\uc758 \uacbd\uc6b0 \ub124\uc774\ubc84 \uc9c0\ub3c4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \uc218 \uc5c6\uc73c\ub2c8 \ub2f9\uc5f0\ud788 \ub9f5 API\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub3c4\ud615 \uadf8\ub9ac\uae30 API(\ub124\uc774\ubc84 \ub9f5 API \uae30\uc900 Polyline)\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub530\ub77c\uc11c \uc774\ubbf8\uc9c0\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uac70\ub098, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c1\uc811 \uc704\uacbd\ub3c4\ub97c \uc774\uc6a9\ud558\uc5ec \uadf8\ub824\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:"\ud574\ub2f9 \uc694\uad6c\uc0ac\ud56d\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uae30\ub2a5\uc744 \uac00\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud544\uc694\ud558\ub2e4."}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131"}),"\n",(0,r.jsx)(t.li,{children:"\uc120\uacfc \uc810 \ud45c\ud604"}),"\n",(0,r.jsx)(t.li,{children:"\ud22c\uba85\ud55c \ubc30\uacbd\uc0c9"}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"\ud604\uc7ac \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ubc14\uc05c \uc77c\uc815\uacfc \uae30\ub2a5 \uad6c\ud604\uc5d0 \uc788\uc5b4 \uc57d\uac04\uc758 \uc5f0\uc0b0\uc774 \ub4e4\uc5b4\uac04\ub2e4\ub294 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uc5ec \ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30\ub85c \uacb0\uc815\uc744 \ub0b4\ub838\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"\uace0\ub824\ud55c-\uae30\uc220",children:"\uace0\ub824\ud55c \uae30\uc220"}),"\n",(0,r.jsx)(t.p,{children:"\ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uae30 \uc704\ud574 \ub2e4\uc74c\uacfc \uac19\uc740 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 \uae30\uc220\ub4e4\uc744 \ud655\uc778\ud574 \ubcf4\uc558\ub2e4."}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"Python\uc758 Matplotlib"}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.strong,{children:"AWT(Abstract Window Toolkit) [\ucd5c\uc885 \uc120\ud0dd]"})}),"\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \ucc98\ub9ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ubc0f Java\uc5d0\uc11c \ub0b4\ubd80\uc801\uc73c\ub85c Matplotlib \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac (\uc6d0\ud558\ub294 \uae30\ub2a5 \uc5c6\uc74c)"}),"\n",(0,r.jsx)(t.li,{children:"Java Swing, Java FX (\ub2e8\uc21c\ud55c \uc120 \uadf8\ub9ac\uae30 + \uc810 \ucc0d\uae30\ub77c \ubd88\ud544\uc694)"}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"python--matplotlib",children:"Python & Matplotlib"}),"\n",(0,r.jsxs)(t.p,{children:["\ub370\uc774\ud130 \uc2dc\uac01\ud654 \ub77c\uc774\ube0c\ub7ec\ub9ac",(0,r.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 0.2\ucd08"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ucf54\ub4dc\uac00 \uac04\ub2e8\ud574\uc11c \uc720\uc9c0 \ubcf4\uc218\uc131\uc774 \uc88b\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"AWS Lambda \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ucef4\ud4e8\ud305 \uc11c\ube44\uc2a4\ub098 FastAPI\uc640 \uac19\uc740 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\ub85c \ucd94\uac00\uc801\uc778 API\ub97c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"Spring Boot\uc5d0\uc11c \ucd94\uac00\uc801\uc778 API \ud638\ucd9c\uc744 \ud574\uc57c\ud558\uace0, \ud655\uc7a5\uc131\uacfc \ube44\ub3d9\uae30 \ucc98\ub9ac \ub4f1 \uace0\ub824 \ud574\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"java-awt-\uc774\uc678\uc758-\ub77c\uc774\ube0c\ub7ec\ub9ac",children:"Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),"\n",(0,r.jsx)(t.p,{children:"Python\uc774 \uc544\ub2cc Java\uc5d0\uc11c\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub3c4 \uace0\ub824\ub97c \ud574\ubd24\uc9c0\ub9cc \uc694\uad6c\uc0ac\ud56d\uc5d0 \uc801\ud569\ud558\uc9c0 \uc54a\uac70\ub098, \uc801\uc740 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac70\uc6b4 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\uc678\ud588\ub2e4."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"\ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.th,{children:"\uc124\uba85"}),(0,r.jsx)(t.th,{children:"\uc81c\uc678 \uc774\uc720"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Swing"}),(0,r.jsx)(t.td,{children:"AWT \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, \ub124\uc774\ud2f0\ube0c UI\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubaa8\ub4e0 \uc6b4\uc601\uccb4\uc81c \uc0c1\uc5d0\uc11c \ub3d9\uc77c\ud55c UI\ub97c \uac00\uc9c0\ub3c4\ub85d \ud568"}),(0,r.jsx)(t.td,{children:"\uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"JavaFX"}),(0,r.jsx)(t.td,{children:"Swing \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, 3\ucc28\uc6d0 \uadf8\ub798\ud53d\uc744 \uc9c0\uc6d0\ud568"}),(0,r.jsx)(t.td,{children:"\uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://github.com/yuriy-g/simple-java-plot",children:"simple-java-plot"})}),(0,r.jsx)(t.td,{children:"AWT\ub85c \uad6c\ud604\ub41c \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.td,{children:"AWT \uae30\ubc18\uc774\uae34 \ud558\uc9c0\ub9cc \uc9c1\uc811 AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc5d0 \ube44\ud574 \uba54\ub9ac\ud2b8\uac00 \uc5c6\uc74c, \ucee4\uc2a4\ud140 \uc124\uc815 \uae30\ub2a5\uc774 \uc5c6\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://github.com/sh0nk/matplotlib4j",children:"matplotlib4j"})}),(0,r.jsx)(t.td,{children:"Matplotlib\ub97c Java\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud558\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.td,{children:"\ub0b4\ubd80\uc801\uc73c\ub85c \ud30c\uc774\uc36c \uc0ac\uc6a9\ud558\uae30\uc5d0 \ubb34\uac70\uc6c0, \ubc30\uacbd \ud22c\uba85\ud654 \uae30\ub2a5 \uc5c6\uc74c"})]})]})]}),"\n",(0,r.jsx)(t.h3,{id:"java--awtabstract-window-toolkit",children:"Java & AWT(Abstract Window Toolkit)"}),"\n",(0,r.jsxs)(t.p,{children:["\uadf8\ub798\ud53d\uacfc \uc774\ubbf8\uc9c0\ub97c \uadf8\ub9ac\uae30 \uc704\ud55c \ub3c4\uad6c",(0,r.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 1.75\ucd08"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ubcf4\ub2e4 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub2e4\uc18c \uc18c\uc694\ub418\uae30 \ub54c\ubb38\uc5d0 \ube60\ub978 \uc751\ub2f5 \ubc18\ud658\uc744 \uc704\ud574 \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"\uae30\uc220-\uc120\ud0dd",children:"\uae30\uc220 \uc120\ud0dd"}),"\n",(0,r.jsxs)(t.p,{children:["AWT\uc758 \uacbd\uc6b0 Matplotlib\uc5d0 \ube44\ud574 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc788\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub354 \ub9ce\uc774 \uac78\ub9ac\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub418\ub294 \ubd80\ubd84, Python\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc778 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uace0\ub824\ud558\uc5ec AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc720\uc9c0-\ubcf4\uc218",children:"\uc720\uc9c0 \ubcf4\uc218"}),"\n",(0,r.jsxs)(t.p,{children:["AWT\ub77c\ub294 \uc0dd\uc18c\ud55c \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc720\uc9c0 \ubcf4\uc218\uc131\uc744 \uc704\ud574 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub530\ub77c\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\ubc95\uc73c\ub85c \uacf5\uc720\ud558\uae30\ub85c \ud588\ub2e4."]}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"\ucf54\ub4dc \ub9ac\ubdf0\uc640 PR\uc744 \ud1b5\ud574 \uc791\uc131\ud55c AWT \ucf54\ub4dc\uc5d0 \ub300\ud55c \uc124\uba85 \ubc0f \ub9ac\ubdf0 \ubc1b\ub294\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"AWT\ub97c \uc0ac\uc6a9\ud55c \ubd80\ubd84\uc744 \ubb38\uc11c\ud654\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"\ub808\ubca8-3\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70-\ub0b4\uc6a9-\ucd94\uac00",children:"\ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00"}),"\n",(0,r.jsxs)(t.p,{children:["\uae30\uc220 \uc120\ud0dd\uc744 \ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815\uc5d0 \uc624\ub958\uac00 \uc788\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589 \uc2dc\uac04\uc744 \uc81c\uc678\ud558\uba74 \ud30c\uc774\uc36c\uacfc \ube44\uc2b7\ud55c \uc2dc\uac04\uc548\uc5d0 \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud560 \uc218 \uc788\uc5c8\ub2e4."]})]})}function h(e={}){const{wrapper:t}={...(0,i.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>o});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var c=r.createContext({}),o=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,l=e.originalType,c=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),j=o(n),p=i,x=j["".concat(c,".").concat(p)]||j[p]||d[p]||l;return n?r.createElement(x,a(a({ref:t},h),{},{components:n})):r.createElement(x,a({ref:t},h))}));h.displayName="MDXCreateElement"},29632:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/route-89cacb9b7815a3191ab1f9d9e23c43a1.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7617],{15448:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>l,metadata:()=>s,toc:()=>o});var r=n(85893),i=n(3905);const l={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",slug:"route-image-intro",tags:["image","awt"]},a=void 0,s={permalink:"/route-image-intro",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",source:"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",description:"./route.png",date:"2023-07-27T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 27\uc77c",tags:[{label:"image",permalink:"/tags/image"},{label:"awt",permalink:"/tags/awt"}],readingTime:5.865,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",slug:"route-image-intro",tags:["image","awt"]},unlisted:!1,prevItem:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",permalink:"/java-spring-springboot"},nextItem:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",permalink:"/mock-static-method"}},c={authorsImageUrls:[]},o=[{value:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784",id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc758-\ucc45\uc784",level:3},{value:"\uace0\ub824\ud55c \uae30\uc220",id:"\uace0\ub824\ud55c-\uae30\uc220",level:3},{value:"Python & Matplotlib",id:"python--matplotlib",level:2},{value:"Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac",id:"java-awt-\uc774\uc678\uc758-\ub77c\uc774\ube0c\ub7ec\ub9ac",level:3},{value:"Java & AWT(Abstract Window Toolkit)",id:"java--awtabstract-window-toolkit",level:3},{value:"\uae30\uc220 \uc120\ud0dd",id:"\uae30\uc220-\uc120\ud0dd",level:3},{value:"\uc720\uc9c0 \ubcf4\uc218",id:"\uc720\uc9c0-\ubcf4\uc218",level:3},{value:"\ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00",id:"\ub808\ubca8-3\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70-\ub0b4\uc6a9-\ucd94\uac00",level:3}];function d(e){const t={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"./route.png",src:n(29632).Z+"",width:"1014",height:"902"})}),"\n",(0,r.jsx)(t.h3,{id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc758-\ucc45\uc784",children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784"}),"\n",(0,r.jsxs)(t.p,{children:["\uc704 \uc640\uc774\uc5b4 \ud504\ub808\uc784\uc5d0\uc11c ",(0,r.jsx)(t.code,{children:"\uc5ec\ud589 \ud788\uc2a4\ud1a0\ub9ac"}),"\uc640 ",(0,r.jsx)(t.code,{children:"\uc5ec\ud589\uc5d0 \ub300\ud55c \uac10\uc0c1\uc744 \uc704\ud55c \uacbd\ub85c \uc774\ubbf8\uc9c0"}),"\uc758 \uacbd\uc6b0 \ub124\uc774\ubc84 \uc9c0\ub3c4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \uc218 \uc5c6\uc73c\ub2c8 \ub2f9\uc5f0\ud788 \ub9f5 API\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub3c4\ud615 \uadf8\ub9ac\uae30 API(\ub124\uc774\ubc84 \ub9f5 API \uae30\uc900 Polyline)\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub530\ub77c\uc11c \uc774\ubbf8\uc9c0\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uac70\ub098, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c1\uc811 \uc704\uacbd\ub3c4\ub97c \uc774\uc6a9\ud558\uc5ec \uadf8\ub824\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:"\ud574\ub2f9 \uc694\uad6c\uc0ac\ud56d\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uae30\ub2a5\uc744 \uac00\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud544\uc694\ud558\ub2e4."}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131"}),"\n",(0,r.jsx)(t.li,{children:"\uc120\uacfc \uc810 \ud45c\ud604"}),"\n",(0,r.jsx)(t.li,{children:"\ud22c\uba85\ud55c \ubc30\uacbd\uc0c9"}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"\ud604\uc7ac \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ubc14\uc05c \uc77c\uc815\uacfc \uae30\ub2a5 \uad6c\ud604\uc5d0 \uc788\uc5b4 \uc57d\uac04\uc758 \uc5f0\uc0b0\uc774 \ub4e4\uc5b4\uac04\ub2e4\ub294 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uc5ec \ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30\ub85c \uacb0\uc815\uc744 \ub0b4\ub838\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"\uace0\ub824\ud55c-\uae30\uc220",children:"\uace0\ub824\ud55c \uae30\uc220"}),"\n",(0,r.jsx)(t.p,{children:"\ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uae30 \uc704\ud574 \ub2e4\uc74c\uacfc \uac19\uc740 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 \uae30\uc220\ub4e4\uc744 \ud655\uc778\ud574 \ubcf4\uc558\ub2e4."}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"Python\uc758 Matplotlib"}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.strong,{children:"AWT(Abstract Window Toolkit) [\ucd5c\uc885 \uc120\ud0dd]"})}),"\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \ucc98\ub9ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ubc0f Java\uc5d0\uc11c \ub0b4\ubd80\uc801\uc73c\ub85c Matplotlib \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac (\uc6d0\ud558\ub294 \uae30\ub2a5 \uc5c6\uc74c)"}),"\n",(0,r.jsx)(t.li,{children:"Java Swing, Java FX (\ub2e8\uc21c\ud55c \uc120 \uadf8\ub9ac\uae30 + \uc810 \ucc0d\uae30\ub77c \ubd88\ud544\uc694)"}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"python--matplotlib",children:"Python & Matplotlib"}),"\n",(0,r.jsxs)(t.p,{children:["\ub370\uc774\ud130 \uc2dc\uac01\ud654 \ub77c\uc774\ube0c\ub7ec\ub9ac",(0,r.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 0.2\ucd08"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ucf54\ub4dc\uac00 \uac04\ub2e8\ud574\uc11c \uc720\uc9c0 \ubcf4\uc218\uc131\uc774 \uc88b\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"AWS Lambda \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ucef4\ud4e8\ud305 \uc11c\ube44\uc2a4\ub098 FastAPI\uc640 \uac19\uc740 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\ub85c \ucd94\uac00\uc801\uc778 API\ub97c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"Spring Boot\uc5d0\uc11c \ucd94\uac00\uc801\uc778 API \ud638\ucd9c\uc744 \ud574\uc57c\ud558\uace0, \ud655\uc7a5\uc131\uacfc \ube44\ub3d9\uae30 \ucc98\ub9ac \ub4f1 \uace0\ub824 \ud574\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"java-awt-\uc774\uc678\uc758-\ub77c\uc774\ube0c\ub7ec\ub9ac",children:"Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),"\n",(0,r.jsx)(t.p,{children:"Python\uc774 \uc544\ub2cc Java\uc5d0\uc11c\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub3c4 \uace0\ub824\ub97c \ud574\ubd24\uc9c0\ub9cc \uc694\uad6c\uc0ac\ud56d\uc5d0 \uc801\ud569\ud558\uc9c0 \uc54a\uac70\ub098, \uc801\uc740 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac70\uc6b4 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\uc678\ud588\ub2e4."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"\ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.th,{children:"\uc124\uba85"}),(0,r.jsx)(t.th,{children:"\uc81c\uc678 \uc774\uc720"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Swing"}),(0,r.jsx)(t.td,{children:"AWT \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, \ub124\uc774\ud2f0\ube0c UI\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubaa8\ub4e0 \uc6b4\uc601\uccb4\uc81c \uc0c1\uc5d0\uc11c \ub3d9\uc77c\ud55c UI\ub97c \uac00\uc9c0\ub3c4\ub85d \ud568"}),(0,r.jsx)(t.td,{children:"\uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"JavaFX"}),(0,r.jsx)(t.td,{children:"Swing \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, 3\ucc28\uc6d0 \uadf8\ub798\ud53d\uc744 \uc9c0\uc6d0\ud568"}),(0,r.jsx)(t.td,{children:"\uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://github.com/yuriy-g/simple-java-plot",children:"simple-java-plot"})}),(0,r.jsx)(t.td,{children:"AWT\ub85c \uad6c\ud604\ub41c \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.td,{children:"AWT \uae30\ubc18\uc774\uae34 \ud558\uc9c0\ub9cc \uc9c1\uc811 AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc5d0 \ube44\ud574 \uba54\ub9ac\ud2b8\uac00 \uc5c6\uc74c, \ucee4\uc2a4\ud140 \uc124\uc815 \uae30\ub2a5\uc774 \uc5c6\uc74c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://github.com/sh0nk/matplotlib4j",children:"matplotlib4j"})}),(0,r.jsx)(t.td,{children:"Matplotlib\ub97c Java\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud558\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac"}),(0,r.jsx)(t.td,{children:"\ub0b4\ubd80\uc801\uc73c\ub85c \ud30c\uc774\uc36c \uc0ac\uc6a9\ud558\uae30\uc5d0 \ubb34\uac70\uc6c0, \ubc30\uacbd \ud22c\uba85\ud654 \uae30\ub2a5 \uc5c6\uc74c"})]})]})]}),"\n",(0,r.jsx)(t.h3,{id:"java--awtabstract-window-toolkit",children:"Java & AWT(Abstract Window Toolkit)"}),"\n",(0,r.jsxs)(t.p,{children:["\uadf8\ub798\ud53d\uacfc \uc774\ubbf8\uc9c0\ub97c \uadf8\ub9ac\uae30 \uc704\ud55c \ub3c4\uad6c",(0,r.jsx)(t.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 1.75\ucd08"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ubcf4\ub2e4 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub2e4\uc18c \uc18c\uc694\ub418\uae30 \ub54c\ubb38\uc5d0 \ube60\ub978 \uc751\ub2f5 \ubc18\ud658\uc744 \uc704\ud574 \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"\uae30\uc220-\uc120\ud0dd",children:"\uae30\uc220 \uc120\ud0dd"}),"\n",(0,r.jsxs)(t.p,{children:["AWT\uc758 \uacbd\uc6b0 Matplotlib\uc5d0 \ube44\ud574 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc788\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub354 \ub9ce\uc774 \uac78\ub9ac\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud558\uc9c0\ub9cc \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub418\ub294 \ubd80\ubd84, Python\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc778 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uace0\ub824\ud558\uc5ec AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc720\uc9c0-\ubcf4\uc218",children:"\uc720\uc9c0 \ubcf4\uc218"}),"\n",(0,r.jsxs)(t.p,{children:["AWT\ub77c\ub294 \uc0dd\uc18c\ud55c \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc720\uc9c0 \ubcf4\uc218\uc131\uc744 \uc704\ud574 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub530\ub77c\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\ubc95\uc73c\ub85c \uacf5\uc720\ud558\uae30\ub85c \ud588\ub2e4."]}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"\ucf54\ub4dc \ub9ac\ubdf0\uc640 PR\uc744 \ud1b5\ud574 \uc791\uc131\ud55c AWT \ucf54\ub4dc\uc5d0 \ub300\ud55c \uc124\uba85 \ubc0f \ub9ac\ubdf0 \ubc1b\ub294\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"AWT\ub97c \uc0ac\uc6a9\ud55c \ubd80\ubd84\uc744 \ubb38\uc11c\ud654\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"\ub808\ubca8-3\ub97c-\ub9c8\ubb34\ub9ac\ud558\uba70-\ub0b4\uc6a9-\ucd94\uac00",children:"\ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00"}),"\n",(0,r.jsxs)(t.p,{children:["\uae30\uc220 \uc120\ud0dd\uc744 \ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815\uc5d0 \uc624\ub958\uac00 \uc788\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589 \uc2dc\uac04\uc744 \uc81c\uc678\ud558\uba74 \ud30c\uc774\uc36c\uacfc \ube44\uc2b7\ud55c \uc2dc\uac04\uc548\uc5d0 \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud560 \uc218 \uc788\uc5c8\ub2e4."]})]})}function h(e={}){const{wrapper:t}={...(0,i.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>o});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var c=r.createContext({}),o=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,l=e.originalType,c=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),j=o(n),p=i,x=j["".concat(c,".").concat(p)]||j[p]||d[p]||l;return n?r.createElement(x,a(a({ref:t},h),{},{components:n})):r.createElement(x,a({ref:t},h))}));h.displayName="MDXCreateElement"},29632:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/route-89cacb9b7815a3191ab1f9d9e23c43a1.png"}}]); \ No newline at end of file diff --git a/assets/js/a3614f73.63484f4e.js b/assets/js/a3614f73.a53a0551.js similarity index 98% rename from assets/js/a3614f73.63484f4e.js rename to assets/js/a3614f73.a53a0551.js index ef302b988..7c40195ff 100644 --- a/assets/js/a3614f73.63484f4e.js +++ b/assets/js/a3614f73.a53a0551.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8474],{15899:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>c,toc:()=>j});var t=n(85893),s=n(3905);const l={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",slug:"woowacourse-level1-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/woowacourse-level1-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",description:"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.",date:"2023-04-01T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 1\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.48,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",slug:"woowacourse-level1-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",permalink:"/custom-jdbc-template"},nextItem:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",permalink:"/chess-retrospective"}},o={authorsImageUrls:[]},j=[{value:"Keep",id:"keep",level:3},{value:"Problem",id:"problem",level:3},{value:"Try",id:"try",level:3},{value:"\ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70",id:"\ub808\ubca8-1\uc744-\ub9c8\ubb34\ub9ac\ud558\uba70",level:3}];function a(e){const r={br:"br",code:"code",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(r.p,{children:["\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\ud14c\ucf54\ub97c \uc2dc\uc791\ud558\uae30 \uc804 \ub0b4\uac00 \uc815\ud574\ub450\uc5c8\ub358 \ubaa9\ud45c \uc774\uc0c1\uc73c\ub85c \ub2ec\uc131\ud588\uae30 \ub54c\ubb38\uc5d0 \ub9e4\uc6b0 \ub9cc\uc871\uc2a4\ub7fd\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud63c\uc790 \ub3c5\ud559\uc744 \ud560 \ub550 \uc774 \ubc29\ud5a5\uc73c\ub85c \uacf5\ubd80\ud558\ub294 \uac8c \ub9de\ub294\uc9c0 \uacc4\uc18d \ubc18\ucd94\ud558\ub2e4 \uacb0\uad6d \ubb34\uae30\ub825\ud568\uc5d0 \ube60\uc838\ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \uc774\uc81c\ub294 \uac19\uc774 \uacf5\ubd80\ud560 \uc0ac\ub78c\ub3c4 \uc788\uace0, \uc774\uc57c\uae30\ud560 \uc0ac\ub78c\ub3c4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc990\uae30\ub294 \uc77c\ub9cc \ub0a8\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"keep",children:"Keep"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub098\ub9cc\uc758 \ub8e8\ud2f4 \ub9cc\ub4e4\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc2a4\uc2a4\ub85c\uac00 \uc678\ubd80\uc758 \uc601\ud5a5\uc744 \ub9ce\uc774 \ubc1b\ub294\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucd5c\ub300\ud55c \uafb8\uc900\ud788 \ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ub9e4\uc77c 8\uc2dc\uc5d0 \ub3c4\ucc29\ud558\uc5ec \uc544\uce68\uc5d0 \ud574\uc57c \ud560 \uc77c\uc744 \uc815\ub9ac\ud558\uac70\ub098, \uc6b0\uc120\uc21c\uc704\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud558\uace0",(0,t.jsx)(r.br,{}),"\n","\uc18c\ud654\ub2a5\ub825\uc774 \ubd80\uc871\ud558\uae30 \ub54c\ubb38\uc5d0 \uc810\uc2ec\uc740 \ub3c4\uc2dc\ub77d(\uadf8\ub798\ubd24\uc790 \uacc4\ub7802\uac1c)\uc744 \uc900\ube44\ud558\uace0",(0,t.jsx)(r.br,{}),"\n","\ud56d\uc0c1 \ub611\uac19\uc740 \ucee8\ub514\uc158\uc744 \uc720\uc9c0\ud558\uae30 \uc704\ud574 \ud56d\uc0c1 6\uc2dc\uc5d0 \uc9d1\uc5d0 \uac04\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uc81c \ubc14\ube60\uc9c8 \ud14c\ub2c8 \uc77c\ucc0d \uc9d1\uc5d0 \uac00\ub294 \uc77c\uc740 \uc5b4\uca54 \uc218 \uc5c6\uc774 \uc904\uc5b4\ub4e4\uaca0\uc9c0\ub9cc\ud83d\ude22"]}),"\n",(0,t.jsx)(r.p,{children:"\uc120\ud0dd\ub3c4 \ube44\uc6a9\uc774\ub2e4. \uc55e\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\uc774 \ud544\uc694 \uc5c6\ub294 \ubd80\ubd84\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\ub4e4\uc5b4\uc57c\uaca0\ub2e4."}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["10\uba85 \uc815\ub3c4\uc758 \ud06c\ub8e8\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b0\uace0 \uce5c\ud558\uac8c \uc9c0\ub0b8\ub2e4\uba74 \uc131\uacf5\uc801\uc774\ub77c\uace0 \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\ub2e4 \ubcf4\ub2c8 \ub354 \ub9ce\uc740 \ud06c\ub8e8\ub4e4\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b4 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c\ub3c4 \ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uace0 \uc544\ubb34 \ub54c\ub098 \ub9d0\uc744 \uac78 \uc218 \uc788\ub294 \ud06c\ub8e8\uac00 \ub298\uc5b4\ub098\uae38 :)"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uae00\uc4f0\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["\uae00\uc744 \uc798 \uc4f0\ub294 \ud3b8\uc740 \uc544\ub2c8\uc9c0\ub9cc \uafb8\uc900\ud788 \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub9e4 \ubbf8\uc158\ub9c8\ub2e4 \ud68c\uace0\ub97c \uc791\uc131\ud558\ub2c8 \uc0dd\uac01\ub3c4 \uc815\ub9ac\ub418\uace0 \uac1c\uc120\uc810\ub3c4 \ucc3e\uc744 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc5d0\ub294 \ub808\ubca8\ub9c8\ub2e4 \uae00\uc4f0\uae30\ub97c \uc9c4\ud589\ud558\ub294\ub370, \uc6b4\uc774 \uc88b\uac8c \uae00\uc4f0\uae30 \uc0c1\uc744 \ubc1b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc0ac\uc2e4 \uac89\uc73c\ub85c \ub4dc\ub7ec\ub0b4\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uaf2d \ubc1b\uc544\ubcf4\uace0 \uc2f6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uae00\uc4f0\uae30 \uc870\uc6d0, \ud22c\ud45c\ud574 \uc900 \ud06c\ub8e8\ub4e4\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514"})}),"\n",(0,t.jsxs)(r.p,{children:["\ub204\ub204, \uc8fc\ub178, \ub2e4\uc990, \ub9d0\ub791, \ubc15\uc2a4\ud130, \uc624\uc789, \uae43\uc9f1\uc640 \ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514\ub97c \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uacfc\uc5f0 \ub3c4\uc6c0\uc774 \ub420\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud558\uba74\uc11c \uc131\uc7a5\uc744 \ub9ce\uc774 \ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud22c\uc790\ud55c \uc2dc\uac04 \ub300\ube44 \uac00\uc131\ube44\uac00 \uc88b\uc740 \ud65c\ub3d9\uc774\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub204\ub204\uac00 \uc2a4\ud130\ub514\uc7a5\uc778\ub370 \uacfc\uc5f0 \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00\ub824\ub098?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub808\ubca8 \uc778\ud130\ubdf0"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc778\ud130\ubdf0\ud560 \ub54c \ub9ce\uc774 \ub5a8\uc9c0 \uc54a\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub0a8\ub4e4 \uc55e\uc5d0\uc11c \uc774\uc57c\uae30\ub97c \ud558\uac70\ub098, \uba74\uc811\uc744 \ubcf4\uba74 \ud56d\uc0c1 \uc5c4\uccad \ub5a8\uc5b4\uc11c \uac71\uc815\ud588\ub294\ub370",(0,t.jsx)(r.br,{}),"\n","\uae30\uc220\uc801\uc778 \uc9c8\ubb38\uc744 \ubc1b\uc558\uc744 \ub54c \ub5a8\uc9c0 \uc54a\uace0 \uc798 \ub300\ub2f5\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \ub2e4\ub978 \ud06c\ub8e8\uac00 \uc9c8\ubb38\ud588\uc744 \ub54c, \ucd5c\ub300\ud55c \uc774\ud574\ud558\uae30 \uc27d\uac8c \uc124\uba85\ud558\ub824\uace0 \ud588\ub358 \uacbd\ud5d8\uc774 \ub3c4\uc6c0\uc774 \ub41c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ud6c4 \ub808\ubca8 \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"\ub300\ub2f5\ud558\uba74\uc11c \uc9c8\ubb38\uc744 \uacc4\uc18d \uc0dd\uac01\ud558\uba70 \uc78a\uc5b4\ubc84\ub9ac\uc9c0 \ub9d0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\ub450\uad04\uc2dd \ud45c\ud604"}),"\n",(0,t.jsx)(r.li,{children:"\uc124\uba85\ud558\ub2e4\uac00 \uc798\ubabb \uc124\uba85\ud55c \uac83 \uac19\uc73c\uba74 \ub2e4 \ub04a\uace0 \ub2e4\uc2dc \uc774\uc57c\uae30\ud574\ub3c4 \ub420\uc9c0 \ubb3c\uc5b4\ubcf4\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uc124\uba85\ud560 \uc218 \uc788\uc744\ub9cc\ud07c \uc2dc\uac04 \ucda9\ubd84\ud788 \uac00\uc9c0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uc778\ud130\ubdf0\uc5b4\uc758 \uc9c8\ubb38 \uc758\ub3c4\ub97c \uba85\ud655\ud788 \uc774\ud574\ud558\uc9c0 \ubabb\ud588\ub2e4\uba74 \uc758\ub3c4 \ub2e4\uc2dc \ubb3c\uc5b4\ubcf4\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\ub05d\ub9fa\ub294 \ubd80\ubd84 \uc5f0\uc2b5\ud558\uae30(\uc790\uc2e0\uac10 \uc788\uac8c)"}),"\n",(0,t.jsx)(r.li,{children:"\uae30\uc220\uc801\uc778 \uc9d1\ucc29\uac00\uc9c0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud788 \uc900\ube44\ud588\uc73c\uba74 \ud611\uc5c5 \uad00\ub828 \uc9c8\ubb38\ub3c4 \uc900\ube44\ud558\uae30"}),"\n"]}),"\n",(0,t.jsx)(r.h3,{id:"problem",children:"Problem"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ud65c\ub3d9 \uc911 \ud558\ub098\ub77c\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud398\uc5b4\ub294 \ub9e4\ubc88 \ubc14\ub00c\uace0, \ubbf8\uc158\uc758 \ubcf5\uc7a1\ub3c4\ub3c4 \uc99d\uac00\ud558\uae30 \ub54c\ubb38\uc778 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc18c\ud1b5 \ub2a5\ub825, \uc2dc\uac04\uad00\ub9ac\uac00 \ubd80\uc871\ud588\uace0, \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uace0, \ud68c\uace0\ub97c \ud558\ub2e4 \ubcf4\ub2c8 \ub098\ub9cc\uc758 \ub178\ud558\uc6b0\uac00 \uc313\uc774\ub294 \ub290\ub08c\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub808\ubca8 2\uc5d0\uc11c\ub294 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc120\ud558\uc5ec \ud568\uaed8\ud558\uace0 \uc2f6\uc740 \ud398\uc5b4\uac00 \ub418\uace0 \uc2f6\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc9d1\uc911\ud558\ub294 \uc2dc\uac04\u23f1\ufe0f \ubd80\uc871"})}),"\n",(0,t.jsxs)(r.p,{children:["\ub808\ubca8 1\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc9d1\uc911\ud558\ub294 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ub978 \uc544\uce68\uacfc \uc624\ud6c4\uc5d0 \uac1c\uc778\uc801\uc73c\ub85c \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \uacf5\uac04\uc744 \uc608\uc57d\ud574\uc11c \uc628\uc804\ud788 \ub098\ub9cc\uc758 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"try",children:"Try"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud5c8\ube0c\ud83c\udf3f\uc640\uc758 \ud2f0\ud0c0\uc784?"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc744 \ub298\ub9b4 \ubc29\ubc95\uc744 \uc0dd\uac01\ud558\ub2e4\uac00 \ub300\ud654\ub97c \ub098\ub204\uc9c0 \ubabb\ud55c \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \uae5c\uc9dd \ucee4\ud53c\ucc57\uc744 \ud558\uba74 \uc5b4\ub5a8\uae4c \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 \uc7a1\ub2f4\ubc29\uc5d0 ",(0,t.jsx)(r.code,{children:"\uc800\uc640 \ucee4\ud53c\ucc57 \ud558\uc2e4 \ubd84 :)"})," \ud558\uba74\uc11c \uc62c\ub9b4 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucc38\uc5ec\ud558\ub294 \uc0ac\ub78c\uc774 \uc788\uc744\uc9c0, \uc548 \uc88b\uac8c \ubcf4\ub294 \uac8c \uc544\ub2d0\uc9c0 \uac71\uc815\ub418\uc9c0\ub9cc \uadf8\ub798\ub3c4 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc800\ub791 \ud5c8\ube0c\ud2f0 \ud55c\uc794 \ud558\uc2e4\ub798\uc694?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uae30\uc220\uc801\uc778 \ubd80\ubd84"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0 \uc870\uae08 \ub354 \ubb34\uac8c\ub97c \ub450\ub2e4 \ubcf4\ub2c8 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc774 \ubd80\uc871\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc2dc\uac04\uc758 \uc5ec\uc720\uac00 \ub420 \ub54c \ucc45\uc744 \uc870\uae08\uc529 \uc77d\uc5b4\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube14\ub85c\uadf8\uc5d0 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \ub9ce\uc774 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\ub294 \uc2dc\uac04\ub3c4 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ub808\ubca8-1\uc744-\ub9c8\ubb34\ub9ac\ud558\uba70",children:"\ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70"}),"\n",(0,t.jsxs)(r.p,{children:["\uc2dc\uac04\uc774 \ube60\ub974\uac8c \ud758\ub7ec\uac14\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud0c0\uc778\uc5d0\uac8c \uc88b\uc740 \uc601\ud5a5\uc744 \uc8fc\uae30\uc704\ud574, \ubc29\ud559\ub3d9\uc548 \ub098\ub97c \ucc59\uae30\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub610\ud55c \ud568\uaed8 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc744 \ubaa9\ud45c\ub85c \uc55e\uc73c\ub85c\ub3c4 \uafb8\uc900\ud788 \uc758\uc2dd\uc801 \ub178\ub825\uc744 \ud574\uc57c\uaca0\ub2e4."]})]})}function p(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>j});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function l(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var o=t.createContext({}),j=function(e){var r=t.useContext(o),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},a={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},p=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,l=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),x=j(n),d=s,h=x["".concat(o,".").concat(d)]||x[d]||a[d]||l;return n?t.createElement(h,i(i({ref:r},p),{},{components:n})):t.createElement(h,i({ref:r},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8474],{15899:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>c,toc:()=>j});var t=n(85893),s=n(3905);const l={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",slug:"woowacourse-level1-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/woowacourse-level1-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",description:"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.",date:"2023-04-01T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 1\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.48,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",slug:"woowacourse-level1-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",permalink:"/chess-retrospective"},nextItem:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",permalink:"/custom-jdbc-template"}},o={authorsImageUrls:[]},j=[{value:"Keep",id:"keep",level:3},{value:"Problem",id:"problem",level:3},{value:"Try",id:"try",level:3},{value:"\ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70",id:"\ub808\ubca8-1\uc744-\ub9c8\ubb34\ub9ac\ud558\uba70",level:3}];function a(e){const r={br:"br",code:"code",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(r.p,{children:["\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\ud14c\ucf54\ub97c \uc2dc\uc791\ud558\uae30 \uc804 \ub0b4\uac00 \uc815\ud574\ub450\uc5c8\ub358 \ubaa9\ud45c \uc774\uc0c1\uc73c\ub85c \ub2ec\uc131\ud588\uae30 \ub54c\ubb38\uc5d0 \ub9e4\uc6b0 \ub9cc\uc871\uc2a4\ub7fd\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud63c\uc790 \ub3c5\ud559\uc744 \ud560 \ub550 \uc774 \ubc29\ud5a5\uc73c\ub85c \uacf5\ubd80\ud558\ub294 \uac8c \ub9de\ub294\uc9c0 \uacc4\uc18d \ubc18\ucd94\ud558\ub2e4 \uacb0\uad6d \ubb34\uae30\ub825\ud568\uc5d0 \ube60\uc838\ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \uc774\uc81c\ub294 \uac19\uc774 \uacf5\ubd80\ud560 \uc0ac\ub78c\ub3c4 \uc788\uace0, \uc774\uc57c\uae30\ud560 \uc0ac\ub78c\ub3c4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc990\uae30\ub294 \uc77c\ub9cc \ub0a8\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"keep",children:"Keep"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub098\ub9cc\uc758 \ub8e8\ud2f4 \ub9cc\ub4e4\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc2a4\uc2a4\ub85c\uac00 \uc678\ubd80\uc758 \uc601\ud5a5\uc744 \ub9ce\uc774 \ubc1b\ub294\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucd5c\ub300\ud55c \uafb8\uc900\ud788 \ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ub9e4\uc77c 8\uc2dc\uc5d0 \ub3c4\ucc29\ud558\uc5ec \uc544\uce68\uc5d0 \ud574\uc57c \ud560 \uc77c\uc744 \uc815\ub9ac\ud558\uac70\ub098, \uc6b0\uc120\uc21c\uc704\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud558\uace0",(0,t.jsx)(r.br,{}),"\n","\uc18c\ud654\ub2a5\ub825\uc774 \ubd80\uc871\ud558\uae30 \ub54c\ubb38\uc5d0 \uc810\uc2ec\uc740 \ub3c4\uc2dc\ub77d(\uadf8\ub798\ubd24\uc790 \uacc4\ub7802\uac1c)\uc744 \uc900\ube44\ud558\uace0",(0,t.jsx)(r.br,{}),"\n","\ud56d\uc0c1 \ub611\uac19\uc740 \ucee8\ub514\uc158\uc744 \uc720\uc9c0\ud558\uae30 \uc704\ud574 \ud56d\uc0c1 6\uc2dc\uc5d0 \uc9d1\uc5d0 \uac04\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uc81c \ubc14\ube60\uc9c8 \ud14c\ub2c8 \uc77c\ucc0d \uc9d1\uc5d0 \uac00\ub294 \uc77c\uc740 \uc5b4\uca54 \uc218 \uc5c6\uc774 \uc904\uc5b4\ub4e4\uaca0\uc9c0\ub9cc\ud83d\ude22"]}),"\n",(0,t.jsx)(r.p,{children:"\uc120\ud0dd\ub3c4 \ube44\uc6a9\uc774\ub2e4. \uc55e\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\uc774 \ud544\uc694 \uc5c6\ub294 \ubd80\ubd84\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\ub4e4\uc5b4\uc57c\uaca0\ub2e4."}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["10\uba85 \uc815\ub3c4\uc758 \ud06c\ub8e8\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b0\uace0 \uce5c\ud558\uac8c \uc9c0\ub0b8\ub2e4\uba74 \uc131\uacf5\uc801\uc774\ub77c\uace0 \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\ub2e4 \ubcf4\ub2c8 \ub354 \ub9ce\uc740 \ud06c\ub8e8\ub4e4\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b4 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c\ub3c4 \ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uace0 \uc544\ubb34 \ub54c\ub098 \ub9d0\uc744 \uac78 \uc218 \uc788\ub294 \ud06c\ub8e8\uac00 \ub298\uc5b4\ub098\uae38 :)"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uae00\uc4f0\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["\uae00\uc744 \uc798 \uc4f0\ub294 \ud3b8\uc740 \uc544\ub2c8\uc9c0\ub9cc \uafb8\uc900\ud788 \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub9e4 \ubbf8\uc158\ub9c8\ub2e4 \ud68c\uace0\ub97c \uc791\uc131\ud558\ub2c8 \uc0dd\uac01\ub3c4 \uc815\ub9ac\ub418\uace0 \uac1c\uc120\uc810\ub3c4 \ucc3e\uc744 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc5d0\ub294 \ub808\ubca8\ub9c8\ub2e4 \uae00\uc4f0\uae30\ub97c \uc9c4\ud589\ud558\ub294\ub370, \uc6b4\uc774 \uc88b\uac8c \uae00\uc4f0\uae30 \uc0c1\uc744 \ubc1b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc0ac\uc2e4 \uac89\uc73c\ub85c \ub4dc\ub7ec\ub0b4\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uaf2d \ubc1b\uc544\ubcf4\uace0 \uc2f6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uae00\uc4f0\uae30 \uc870\uc6d0, \ud22c\ud45c\ud574 \uc900 \ud06c\ub8e8\ub4e4\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514"})}),"\n",(0,t.jsxs)(r.p,{children:["\ub204\ub204, \uc8fc\ub178, \ub2e4\uc990, \ub9d0\ub791, \ubc15\uc2a4\ud130, \uc624\uc789, \uae43\uc9f1\uc640 \ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514\ub97c \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uacfc\uc5f0 \ub3c4\uc6c0\uc774 \ub420\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud558\uba74\uc11c \uc131\uc7a5\uc744 \ub9ce\uc774 \ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud22c\uc790\ud55c \uc2dc\uac04 \ub300\ube44 \uac00\uc131\ube44\uac00 \uc88b\uc740 \ud65c\ub3d9\uc774\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub204\ub204\uac00 \uc2a4\ud130\ub514\uc7a5\uc778\ub370 \uacfc\uc5f0 \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00\ub824\ub098?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub808\ubca8 \uc778\ud130\ubdf0"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc778\ud130\ubdf0\ud560 \ub54c \ub9ce\uc774 \ub5a8\uc9c0 \uc54a\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub0a8\ub4e4 \uc55e\uc5d0\uc11c \uc774\uc57c\uae30\ub97c \ud558\uac70\ub098, \uba74\uc811\uc744 \ubcf4\uba74 \ud56d\uc0c1 \uc5c4\uccad \ub5a8\uc5b4\uc11c \uac71\uc815\ud588\ub294\ub370",(0,t.jsx)(r.br,{}),"\n","\uae30\uc220\uc801\uc778 \uc9c8\ubb38\uc744 \ubc1b\uc558\uc744 \ub54c \ub5a8\uc9c0 \uc54a\uace0 \uc798 \ub300\ub2f5\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \ub2e4\ub978 \ud06c\ub8e8\uac00 \uc9c8\ubb38\ud588\uc744 \ub54c, \ucd5c\ub300\ud55c \uc774\ud574\ud558\uae30 \uc27d\uac8c \uc124\uba85\ud558\ub824\uace0 \ud588\ub358 \uacbd\ud5d8\uc774 \ub3c4\uc6c0\uc774 \ub41c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ud6c4 \ub808\ubca8 \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"\ub300\ub2f5\ud558\uba74\uc11c \uc9c8\ubb38\uc744 \uacc4\uc18d \uc0dd\uac01\ud558\uba70 \uc78a\uc5b4\ubc84\ub9ac\uc9c0 \ub9d0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\ub450\uad04\uc2dd \ud45c\ud604"}),"\n",(0,t.jsx)(r.li,{children:"\uc124\uba85\ud558\ub2e4\uac00 \uc798\ubabb \uc124\uba85\ud55c \uac83 \uac19\uc73c\uba74 \ub2e4 \ub04a\uace0 \ub2e4\uc2dc \uc774\uc57c\uae30\ud574\ub3c4 \ub420\uc9c0 \ubb3c\uc5b4\ubcf4\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uc124\uba85\ud560 \uc218 \uc788\uc744\ub9cc\ud07c \uc2dc\uac04 \ucda9\ubd84\ud788 \uac00\uc9c0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uc778\ud130\ubdf0\uc5b4\uc758 \uc9c8\ubb38 \uc758\ub3c4\ub97c \uba85\ud655\ud788 \uc774\ud574\ud558\uc9c0 \ubabb\ud588\ub2e4\uba74 \uc758\ub3c4 \ub2e4\uc2dc \ubb3c\uc5b4\ubcf4\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\ub05d\ub9fa\ub294 \ubd80\ubd84 \uc5f0\uc2b5\ud558\uae30(\uc790\uc2e0\uac10 \uc788\uac8c)"}),"\n",(0,t.jsx)(r.li,{children:"\uae30\uc220\uc801\uc778 \uc9d1\ucc29\uac00\uc9c0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud788 \uc900\ube44\ud588\uc73c\uba74 \ud611\uc5c5 \uad00\ub828 \uc9c8\ubb38\ub3c4 \uc900\ube44\ud558\uae30"}),"\n"]}),"\n",(0,t.jsx)(r.h3,{id:"problem",children:"Problem"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ud65c\ub3d9 \uc911 \ud558\ub098\ub77c\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud398\uc5b4\ub294 \ub9e4\ubc88 \ubc14\ub00c\uace0, \ubbf8\uc158\uc758 \ubcf5\uc7a1\ub3c4\ub3c4 \uc99d\uac00\ud558\uae30 \ub54c\ubb38\uc778 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc18c\ud1b5 \ub2a5\ub825, \uc2dc\uac04\uad00\ub9ac\uac00 \ubd80\uc871\ud588\uace0, \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uace0, \ud68c\uace0\ub97c \ud558\ub2e4 \ubcf4\ub2c8 \ub098\ub9cc\uc758 \ub178\ud558\uc6b0\uac00 \uc313\uc774\ub294 \ub290\ub08c\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub808\ubca8 2\uc5d0\uc11c\ub294 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc120\ud558\uc5ec \ud568\uaed8\ud558\uace0 \uc2f6\uc740 \ud398\uc5b4\uac00 \ub418\uace0 \uc2f6\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc9d1\uc911\ud558\ub294 \uc2dc\uac04\u23f1\ufe0f \ubd80\uc871"})}),"\n",(0,t.jsxs)(r.p,{children:["\ub808\ubca8 1\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc9d1\uc911\ud558\ub294 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ub978 \uc544\uce68\uacfc \uc624\ud6c4\uc5d0 \uac1c\uc778\uc801\uc73c\ub85c \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \uacf5\uac04\uc744 \uc608\uc57d\ud574\uc11c \uc628\uc804\ud788 \ub098\ub9cc\uc758 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"try",children:"Try"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud5c8\ube0c\ud83c\udf3f\uc640\uc758 \ud2f0\ud0c0\uc784?"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc744 \ub298\ub9b4 \ubc29\ubc95\uc744 \uc0dd\uac01\ud558\ub2e4\uac00 \ub300\ud654\ub97c \ub098\ub204\uc9c0 \ubabb\ud55c \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \uae5c\uc9dd \ucee4\ud53c\ucc57\uc744 \ud558\uba74 \uc5b4\ub5a8\uae4c \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 \uc7a1\ub2f4\ubc29\uc5d0 ",(0,t.jsx)(r.code,{children:"\uc800\uc640 \ucee4\ud53c\ucc57 \ud558\uc2e4 \ubd84 :)"})," \ud558\uba74\uc11c \uc62c\ub9b4 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucc38\uc5ec\ud558\ub294 \uc0ac\ub78c\uc774 \uc788\uc744\uc9c0, \uc548 \uc88b\uac8c \ubcf4\ub294 \uac8c \uc544\ub2d0\uc9c0 \uac71\uc815\ub418\uc9c0\ub9cc \uadf8\ub798\ub3c4 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc800\ub791 \ud5c8\ube0c\ud2f0 \ud55c\uc794 \ud558\uc2e4\ub798\uc694?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uae30\uc220\uc801\uc778 \ubd80\ubd84"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0 \uc870\uae08 \ub354 \ubb34\uac8c\ub97c \ub450\ub2e4 \ubcf4\ub2c8 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc774 \ubd80\uc871\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc2dc\uac04\uc758 \uc5ec\uc720\uac00 \ub420 \ub54c \ucc45\uc744 \uc870\uae08\uc529 \uc77d\uc5b4\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube14\ub85c\uadf8\uc5d0 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \ub9ce\uc774 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\ub294 \uc2dc\uac04\ub3c4 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ub808\ubca8-1\uc744-\ub9c8\ubb34\ub9ac\ud558\uba70",children:"\ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70"}),"\n",(0,t.jsxs)(r.p,{children:["\uc2dc\uac04\uc774 \ube60\ub974\uac8c \ud758\ub7ec\uac14\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud0c0\uc778\uc5d0\uac8c \uc88b\uc740 \uc601\ud5a5\uc744 \uc8fc\uae30\uc704\ud574, \ubc29\ud559\ub3d9\uc548 \ub098\ub97c \ucc59\uae30\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub610\ud55c \ud568\uaed8 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc744 \ubaa9\ud45c\ub85c \uc55e\uc73c\ub85c\ub3c4 \uafb8\uc900\ud788 \uc758\uc2dd\uc801 \ub178\ub825\uc744 \ud574\uc57c\uaca0\ub2e4."]})]})}function p(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>j});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function l(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var o=t.createContext({}),j=function(e){var r=t.useContext(o),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},a={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},p=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,l=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),x=j(n),d=s,h=x["".concat(o,".").concat(d)]||x[d]||a[d]||l;return n?t.createElement(h,i(i({ref:r},p),{},{components:n})):t.createElement(h,i({ref:r},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/a59d28a9.aacad7b2.js b/assets/js/a59d28a9.ad347984.js similarity index 98% rename from assets/js/a59d28a9.aacad7b2.js rename to assets/js/a59d28a9.ad347984.js index 1649ab254..44d5c801f 100644 --- a/assets/js/a59d28a9.aacad7b2.js +++ b/assets/js/a59d28a9.ad347984.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2012],{63600:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var a=t(85893),i=t(3905);const r={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",slug:"route-image-python",tags:["Image","Python"]},l=void 0,s={permalink:"/route-image-python",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",source:"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",description:"\uac1c\uc694",date:"2023-07-31T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 31\uc77c",tags:[{label:"Image",permalink:"/tags/image"},{label:"Python",permalink:"/tags/python"}],readingTime:6.185,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",slug:"route-image-python",tags:["Image","Python"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",permalink:"/route-image-implementation"},nextItem:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",permalink:"/mock-static-method"}},o={authorsImageUrls:[]},d=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\uc0ac\uc6a9 \uae30\uc220",id:"\uc0ac\uc6a9-\uae30\uc220",level:3},{value:"\uc694\uad6c\uc0ac\ud56d",id:"\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd",id:"\uc774\ubbf8\uc9c0-\ucd9c\ub825-\ubc29\uc2dd",level:3},{value:"\ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604",id:"\ub85c\uceec\uc5d0\uc11c-\uae30\ub2a5-\uad6c\ud604",level:3},{value:"AWS Lambda",id:"aws-lambda",level:3},{value:"\ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131",id:"\ub78c\ub2e4-s3-\uc811\uadfc\uc744-\uc704\ud55c-iam-\uc0dd\uc131",level:3},{value:"\ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc",id:"\ub78c\ub2e4-\ubc30\ud3ec\uc6a9-\ucf54\ub4dc",level:3},{value:"Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131",id:"layer-\ucd94\uac00\ub97c-\uc704\ud55c-zip-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"No module named 'numpy.core._multiarray_umath' \uc5d0\ub7ec",id:"no-module-named-numpycore_multiarray_umath-\uc5d0\ub7ec",level:3},{value:"\uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01",id:"\uc801\uc815\uae30\uc220\uc5d0-\ub300\ud55c-\uc0dd\uac01",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,a.jsx)(n.p,{children:"\uc774\uc804\uc5d0 \uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\uc0ac\ud558\uba74\uc11c \ud30c\uc774\uc36c\uc744 \uc0ac\uc6a9\ud55c \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud55c \ub0b4\uc6a9\uc774\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\uc0ac\uc6a9-\uae30\uc220",children:"\uc0ac\uc6a9 \uae30\uc220"}),"\n",(0,a.jsxs)(n.p,{children:["\uc5b8\uc5b4: Python 3.10",(0,a.jsx)(n.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131: matplotlib",(0,a.jsx)(n.br,{}),"\n","\uc11c\ube44\uc2a4: AWS Lambda, AWS API Gateway",(0,a.jsx)(n.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc800\uc7a5 \ubc0f URL: AWS S3, AWS CloudFront"]}),"\n",(0,a.jsx)(n.p,{children:"\ud50c\ub85c\uc6b0\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n Server -- \uc0dd\uc131 \uc694\uccad --\x3e AG[API Gateway] --\x3e Lambda --\x3e S3\n Client --\x3e CloudFront --\x3e S3"}),"\n",(0,a.jsx)(n.h3,{id:"\uc694\uad6c\uc0ac\ud56d",children:"\uc694\uad6c\uc0ac\ud56d"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"./route.png",src:t(13533).Z+"",width:"1014",height:"902"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc6b0\uce21 \uc0c1\ub2e8\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub824\uace0 \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"\uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \ubc30\uc5f4\uc744 \uc785\ub825\ubc1b\ub294\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131"}),"\n",(0,a.jsx)(n.li,{children:"\uc120\uacfc \uc810 \ud45c\ud604"}),"\n",(0,a.jsx)(n.li,{children:"\ud22c\uba85\ud55c \ubc30\uacbd\uc0c9"}),"\n",(0,a.jsx)(n.li,{children:"\uc704\uacbd\ub3c4 \ucc28\uc774\uac00 \ud06c\ub4e0 \uc791\ub4e0 \uc81c\uacf5\ud558\ub294 \uc774\ubbf8\uc9c0 \ub0b4\uc5d0 \uacbd\ub85c\uac00 \ub2e4 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"\uc774\ubbf8\uc9c0-\ucd9c\ub825-\ubc29\uc2dd",children:"\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"\uc704\uacbd\ub3c4\ub97c \ucc98\ub9ac\ud55c \uac12\uc73c\ub85c \uc9c1\uc811 \uacbd\ub85c\ub97c \uadf8\ub9b0 \ub2e4\uc74c \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5"}),"\n",(0,a.jsx)(n.li,{children:"\ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc0ac\uc6a9\ud558\uc5ec \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5"}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\uc758 \uacbd\uc6b0 1\ubc88\uacfc 2\ubc88\uc744 \uace0\ubbfc\ud588\uc5c8\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud30c\uc774\uc36c\uc73c\ub85c\ub294 \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc778 matplotlib\uc744 \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ub85c\uceec\uc5d0\uc11c-\uae30\ub2a5-\uad6c\ud604",children:"\ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"import time\n\nimport matplotlib.pyplot as plt\n\n\ndef draw(point):\n start = time.time()\n x, y = zip(*point)\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\n draw_lines(pixel_x, pixel_y)\n end = time.time()\n print(end - start)\n \ndef convert_to_pixel_values(x, y):\n max_diff = max(max(x) - min(x), max(y) - min(y))\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\n\n\ndef scale_to_pixel_values(points, max_diff):\n min_value = min(points)\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\n return scaled_coordinates\n\n\ndef draw_lines(x, y):\n figure = plt.gcf()\n figure.set_size_inches(5, 5)\n plt.plot(x, y, c = 'w',linewidth=5)\n plt.scatter(x[3],y[3], c = 'w', s = 125)\n plt.axis('off')\n plt.savefig('name.png', transparent=True, format='png')\n\npoint = [\n [126.96352960597338, 37.590841000217125],\n [126.96987292787792, 37.58435564234159],\n [126.98128481452298, 37.58594375113966],\n [126.99360339342958, 37.58248524741927],\n [126.99867565340067, 37.56778118088622],\n [127.001935378366117, 37.55985240444085],\n [126.9831048919687, 37.548030119488665],\n [126.97189273528845, 37.5119879225856],\n [127.02689859997221, 37.48488593333883]\n]\n\ndraw(point)\n"})}),"\n",(0,a.jsx)(n.p,{children:"\uc0dd\uc131 \uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4. (\uc608\uc2dc\ub97c \uc704\ud574 \uac80\uc740\uc0c9\uc73c\ub85c \ucd9c\ub825)"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"./routeImage.png",src:t(46365).Z+"",width:"500",height:"500"})}),"\n",(0,a.jsx)(n.h3,{id:"aws-lambda",children:"AWS Lambda"}),"\n",(0,a.jsxs)(n.p,{children:["\uc378\ub124\uc77c \uc0dd\uc131 \uc11c\ubc84\ub97c \ub530\ub85c \ub450\uae30\ub294 \uae30\ub2a5 \ub300\ube44 \ube44\uc6a9\uc774 \ub108\ubb34 \ud074 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc11c\ubc84\ub9ac\uc2a4\ub85c \ud30c\uc77c\uc744 \ucc98\ub9ac\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c s3 \uc811\uadfc\uc740 boto3\ub97c \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ub78c\ub2e4-s3-\uc811\uadfc\uc744-\uc704\ud55c-iam-\uc0dd\uc131",children:"\ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131"}),"\n",(0,a.jsx)(n.p,{children:"AmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy \ub450\uac00\uc9c0\ub97c \ucd94\uac00\ud574\uc11c Lambda \uc804\uc6a9 \uc5ed\ud560\uc744 \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud588\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\ub78c\ub2e4-\ubc30\ud3ec\uc6a9-\ucf54\ub4dc",children:"\ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc"}),"\n",(0,a.jsx)(n.p,{children:"\uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \ud655\uc778\ud560 \ub550 \uc704\uce58 \uc810\uc744 \ucc0d\ub294 \uae30\ub2a5\uc744 \ub78c\ub2e4\uc5d0 \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"\nimport io\nimport uuid\n\nimport boto3\nimport matplotlib.pyplot as plt\n\nPIXEL = 255\nBUCKET_NAME = 'image-plot'\nS3 = 's3'\n\ndef lambda_handler(event, context):\n x = event['x']\n y = event['y']\n image_name = str(uuid.uuid4())\n\n img_data = draw(x, y)\n s3 = boto3.client(S3)\n s3.put_object(Body=img_data.getvalue(), ContentType='image/png', Bucket=BUCKET_NAME, Key=image_name)\n url = f'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}'\n\n return {\n 'statusCode': 200,\n 'body': url\n }\n\ndef draw(x, y):\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\n img_data = draw_lines(pixel_x, pixel_y)\n plt.close()\n return img_data\n\ndef convert_to_pixel_values(x, y):\n max_diff = max(max(x) - min(x), max(y) - min(y))\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\n\ndef scale_to_pixel_values(points, max_diff):\n min_value = min(points)\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\n pixel_values = [int(p * PIXEL) for p in scaled_coordinates]\n return pixel_values\n\ndef draw_lines(x, y):\n plt.plot(x, y, 'k-', linewidth=10)\n plt.axis('off')\n img_data = io.BytesIO()\n plt.savefig(img_data, transparent=True, format='png')\n img_data.seek(0)\n return img_data\n\n"})}),"\n",(0,a.jsx)(n.h3,{id:"layer-\ucd94\uac00\ub97c-\uc704\ud55c-zip-\ud30c\uc77c-\uc0dd\uc131",children:"Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,a.jsxs)(n.p,{children:["matplotlib\uc758 \uacbd\uc6b0 \uc678\ubd80 \ub77c\uc774\ube0c\ub7ec\ub9ac\uae30 \ub54c\ubb38\uc5d0 \ub530\ub85c Layer\ub97c \ucd94\uac00\ud574\uc57c \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \uc5c5\ub85c\ub4dc\ud574\uc57c\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub54c python\uc758 Lambda \ub7f0\ud0c0\uc784\uc5d0 \ub300\ud55c \uacc4\uce35 \uacbd\ub85c\ub294 python\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc555\ucd95\ud55c zip \ud30c\uc77c\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \ub744\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"pillow.zip\n\u2502 python/PIL\n\u2514 python/Pillow-5.3.0.dist-info\n"})}),"\n",(0,a.jsx)(n.p,{children:"Ubuntu \uae30\uc900 \ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc0dd\uc131\uc744 \uc9c4\ud589\ud588\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"sudo apt update\nsudo apt install zip\nsudo apt install python3-pip\n\nmkdir python\npip3 install matplotlib -t python # pip3 install \uc124\uce58\ud560_\ud328\ud0a4\uc9c0 -t \uc124\uce58_\uacbd\ub85c\nzip -r my_layer.zip python # zip -r \uc555\ucd95_\ud30c\uc77c\uba85 \uc555\ucd95_\ud30c\uc77c\uc774_\uc874\uc7ac\ud558\ub294_\uacbd\ub85c\n"})}),"\n",(0,a.jsxs)(n.h3,{id:"no-module-named-numpycore_multiarray_umath-\uc5d0\ub7ec",children:[(0,a.jsx)(n.code,{children:"No module named 'numpy.core._multiarray_umath'"})," \uc5d0\ub7ec"]}),"\n",(0,a.jsxs)(n.p,{children:["Layer \ucd94\uac00 \ud6c4 \ub78c\ub2e4 \uc2e4\ud589 \uc2dc \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\uc600\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucc98\uc74c\uc5d0 mac\uc5d0\uc11c zip \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc5c5\ub85c\ub4dc\ud588\ub294\ub370 \ud574\ub2f9 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub294 lambda\uac00 \ub3cc\uc544\uac00\ub294 \ub3d9\uc77c\ud55c \ud658\uacbd\uc5d0\uc11c layer\ub97c \uc704\ud55c zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc9c0 \uc54a\uc544\uc11c \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud558\uac8c ec2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c \ub530\ub85c Layer\ub97c \uc0dd\uc131\ud558\uba74 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\uc801\uc815\uae30\uc220\uc5d0-\ub300\ud55c-\uc0dd\uac01",children:"\uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01"}),"\n",(0,a.jsxs)(n.p,{children:["\ud504\ub85c\uc81d\ud2b8\uc5d0 Lambda\uc640 Python\uc744 \uc0ac\uc6a9\ud558\ub824\uace0 \ud588\uc9c0\ub9cc \uc544\uc27d\uac8c\ub3c4 \ubc18\ub824\ub2f9\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","AWS Lambda\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc778\uc2a4\ud134\uc2a4\uc5d0 \ud574\ub2f9 \ucf54\ub4dc\ub97c \ubc30\ud3ec\ud558\ub294 \uac83\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc77c \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uac00\uc6a9 \uac00\ub2a5\ud55c \uc790\uc6d0, \uae30\uc220\uc758 \ub09c\uc774\ub3c4, \uc0ac\uc6a9\ud558\ub294 \ud300\uc6d0\uc744 \uace0\ub824\ud55c\ub2e4\uba74 Lambda\ub294 \uc801\uc815\uae30\uc220\uc774 \uc544\ub2d0 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud574\ub2f9 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\ub97c \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud560\uc9c0 \uc870\uae08 \ub354 \uace0\ub824\ub97c \ud574\uc57c \ub420 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\ucd5c\uc885\uc801\uc73c\ub85c Java AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4."})}),"\n",(0,a.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://aws.amazon.com/ko/lambda/",children:"AWS Lambda"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html",children:"Lambda Layer"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html",children:"Python Lambda \ud568\uc218\uc5d0 \ub300\ud55c .zip \ud30c\uc77c \uc544\uce74\uc774\ube0c \uc791\uc5c5"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://gist.github.com/ksmin23/0f3f243408a8497f766b43cf589fea7b",children:"No module named 'numpy.core._multiarray_umath'"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://techblog.woowahan.com/6217/",children:"\uc0ac\ub840\ubcc4\ub85c \uc54c\uc544\ubcf8 \uc548\uc804\ud55c S3 \uc0ac\uc6a9 \uac00\uc774\ub4dc"})]})]})}function c(e={}){const{wrapper:n}={...(0,i.ah)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var a=t(67294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var o=a.createContext({}),d=function(e){var n=a.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},p={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,o=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=d(t),x=i,u=m["".concat(o,".").concat(x)]||m[x]||p[x]||r;return t?a.createElement(u,l(l({ref:n},c),{},{components:t})):a.createElement(u,l({ref:n},c))}));c.displayName="MDXCreateElement"},13533:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/route-89cacb9b7815a3191ab1f9d9e23c43a1.png"},46365:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/routeImage-0eac25ba9b356cd034ade6e062c1ce19.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2012],{63600:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var a=t(85893),i=t(3905);const r={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",slug:"route-image-python",tags:["Image","Python"]},l=void 0,s={permalink:"/route-image-python",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",source:"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",description:"\uac1c\uc694",date:"2023-07-31T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 31\uc77c",tags:[{label:"Image",permalink:"/tags/image"},{label:"Python",permalink:"/tags/python"}],readingTime:6.185,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",slug:"route-image-python",tags:["Image","Python"]},unlisted:!1,prevItem:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",permalink:"/mock-static-method"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",permalink:"/route-image-implementation"}},o={authorsImageUrls:[]},d=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\uc0ac\uc6a9 \uae30\uc220",id:"\uc0ac\uc6a9-\uae30\uc220",level:3},{value:"\uc694\uad6c\uc0ac\ud56d",id:"\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd",id:"\uc774\ubbf8\uc9c0-\ucd9c\ub825-\ubc29\uc2dd",level:3},{value:"\ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604",id:"\ub85c\uceec\uc5d0\uc11c-\uae30\ub2a5-\uad6c\ud604",level:3},{value:"AWS Lambda",id:"aws-lambda",level:3},{value:"\ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131",id:"\ub78c\ub2e4-s3-\uc811\uadfc\uc744-\uc704\ud55c-iam-\uc0dd\uc131",level:3},{value:"\ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc",id:"\ub78c\ub2e4-\ubc30\ud3ec\uc6a9-\ucf54\ub4dc",level:3},{value:"Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131",id:"layer-\ucd94\uac00\ub97c-\uc704\ud55c-zip-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"No module named 'numpy.core._multiarray_umath' \uc5d0\ub7ec",id:"no-module-named-numpycore_multiarray_umath-\uc5d0\ub7ec",level:3},{value:"\uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01",id:"\uc801\uc815\uae30\uc220\uc5d0-\ub300\ud55c-\uc0dd\uac01",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,a.jsx)(n.p,{children:"\uc774\uc804\uc5d0 \uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\uc0ac\ud558\uba74\uc11c \ud30c\uc774\uc36c\uc744 \uc0ac\uc6a9\ud55c \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud55c \ub0b4\uc6a9\uc774\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\uc0ac\uc6a9-\uae30\uc220",children:"\uc0ac\uc6a9 \uae30\uc220"}),"\n",(0,a.jsxs)(n.p,{children:["\uc5b8\uc5b4: Python 3.10",(0,a.jsx)(n.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131: matplotlib",(0,a.jsx)(n.br,{}),"\n","\uc11c\ube44\uc2a4: AWS Lambda, AWS API Gateway",(0,a.jsx)(n.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc800\uc7a5 \ubc0f URL: AWS S3, AWS CloudFront"]}),"\n",(0,a.jsx)(n.p,{children:"\ud50c\ub85c\uc6b0\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n Server -- \uc0dd\uc131 \uc694\uccad --\x3e AG[API Gateway] --\x3e Lambda --\x3e S3\n Client --\x3e CloudFront --\x3e S3"}),"\n",(0,a.jsx)(n.h3,{id:"\uc694\uad6c\uc0ac\ud56d",children:"\uc694\uad6c\uc0ac\ud56d"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"./route.png",src:t(13533).Z+"",width:"1014",height:"902"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc6b0\uce21 \uc0c1\ub2e8\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub824\uace0 \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"\uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \ubc30\uc5f4\uc744 \uc785\ub825\ubc1b\ub294\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131"}),"\n",(0,a.jsx)(n.li,{children:"\uc120\uacfc \uc810 \ud45c\ud604"}),"\n",(0,a.jsx)(n.li,{children:"\ud22c\uba85\ud55c \ubc30\uacbd\uc0c9"}),"\n",(0,a.jsx)(n.li,{children:"\uc704\uacbd\ub3c4 \ucc28\uc774\uac00 \ud06c\ub4e0 \uc791\ub4e0 \uc81c\uacf5\ud558\ub294 \uc774\ubbf8\uc9c0 \ub0b4\uc5d0 \uacbd\ub85c\uac00 \ub2e4 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"\uc774\ubbf8\uc9c0-\ucd9c\ub825-\ubc29\uc2dd",children:"\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"\uc704\uacbd\ub3c4\ub97c \ucc98\ub9ac\ud55c \uac12\uc73c\ub85c \uc9c1\uc811 \uacbd\ub85c\ub97c \uadf8\ub9b0 \ub2e4\uc74c \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5"}),"\n",(0,a.jsx)(n.li,{children:"\ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc0ac\uc6a9\ud558\uc5ec \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5"}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\uc758 \uacbd\uc6b0 1\ubc88\uacfc 2\ubc88\uc744 \uace0\ubbfc\ud588\uc5c8\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud30c\uc774\uc36c\uc73c\ub85c\ub294 \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc778 matplotlib\uc744 \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ub85c\uceec\uc5d0\uc11c-\uae30\ub2a5-\uad6c\ud604",children:"\ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"import time\n\nimport matplotlib.pyplot as plt\n\n\ndef draw(point):\n start = time.time()\n x, y = zip(*point)\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\n draw_lines(pixel_x, pixel_y)\n end = time.time()\n print(end - start)\n \ndef convert_to_pixel_values(x, y):\n max_diff = max(max(x) - min(x), max(y) - min(y))\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\n\n\ndef scale_to_pixel_values(points, max_diff):\n min_value = min(points)\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\n return scaled_coordinates\n\n\ndef draw_lines(x, y):\n figure = plt.gcf()\n figure.set_size_inches(5, 5)\n plt.plot(x, y, c = 'w',linewidth=5)\n plt.scatter(x[3],y[3], c = 'w', s = 125)\n plt.axis('off')\n plt.savefig('name.png', transparent=True, format='png')\n\npoint = [\n [126.96352960597338, 37.590841000217125],\n [126.96987292787792, 37.58435564234159],\n [126.98128481452298, 37.58594375113966],\n [126.99360339342958, 37.58248524741927],\n [126.99867565340067, 37.56778118088622],\n [127.001935378366117, 37.55985240444085],\n [126.9831048919687, 37.548030119488665],\n [126.97189273528845, 37.5119879225856],\n [127.02689859997221, 37.48488593333883]\n]\n\ndraw(point)\n"})}),"\n",(0,a.jsx)(n.p,{children:"\uc0dd\uc131 \uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4. (\uc608\uc2dc\ub97c \uc704\ud574 \uac80\uc740\uc0c9\uc73c\ub85c \ucd9c\ub825)"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"./routeImage.png",src:t(46365).Z+"",width:"500",height:"500"})}),"\n",(0,a.jsx)(n.h3,{id:"aws-lambda",children:"AWS Lambda"}),"\n",(0,a.jsxs)(n.p,{children:["\uc378\ub124\uc77c \uc0dd\uc131 \uc11c\ubc84\ub97c \ub530\ub85c \ub450\uae30\ub294 \uae30\ub2a5 \ub300\ube44 \ube44\uc6a9\uc774 \ub108\ubb34 \ud074 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc11c\ubc84\ub9ac\uc2a4\ub85c \ud30c\uc77c\uc744 \ucc98\ub9ac\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c s3 \uc811\uadfc\uc740 boto3\ub97c \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ub78c\ub2e4-s3-\uc811\uadfc\uc744-\uc704\ud55c-iam-\uc0dd\uc131",children:"\ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131"}),"\n",(0,a.jsx)(n.p,{children:"AmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy \ub450\uac00\uc9c0\ub97c \ucd94\uac00\ud574\uc11c Lambda \uc804\uc6a9 \uc5ed\ud560\uc744 \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud588\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\ub78c\ub2e4-\ubc30\ud3ec\uc6a9-\ucf54\ub4dc",children:"\ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc"}),"\n",(0,a.jsx)(n.p,{children:"\uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \ud655\uc778\ud560 \ub550 \uc704\uce58 \uc810\uc744 \ucc0d\ub294 \uae30\ub2a5\uc744 \ub78c\ub2e4\uc5d0 \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"\nimport io\nimport uuid\n\nimport boto3\nimport matplotlib.pyplot as plt\n\nPIXEL = 255\nBUCKET_NAME = 'image-plot'\nS3 = 's3'\n\ndef lambda_handler(event, context):\n x = event['x']\n y = event['y']\n image_name = str(uuid.uuid4())\n\n img_data = draw(x, y)\n s3 = boto3.client(S3)\n s3.put_object(Body=img_data.getvalue(), ContentType='image/png', Bucket=BUCKET_NAME, Key=image_name)\n url = f'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}'\n\n return {\n 'statusCode': 200,\n 'body': url\n }\n\ndef draw(x, y):\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\n img_data = draw_lines(pixel_x, pixel_y)\n plt.close()\n return img_data\n\ndef convert_to_pixel_values(x, y):\n max_diff = max(max(x) - min(x), max(y) - min(y))\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\n\ndef scale_to_pixel_values(points, max_diff):\n min_value = min(points)\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\n pixel_values = [int(p * PIXEL) for p in scaled_coordinates]\n return pixel_values\n\ndef draw_lines(x, y):\n plt.plot(x, y, 'k-', linewidth=10)\n plt.axis('off')\n img_data = io.BytesIO()\n plt.savefig(img_data, transparent=True, format='png')\n img_data.seek(0)\n return img_data\n\n"})}),"\n",(0,a.jsx)(n.h3,{id:"layer-\ucd94\uac00\ub97c-\uc704\ud55c-zip-\ud30c\uc77c-\uc0dd\uc131",children:"Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,a.jsxs)(n.p,{children:["matplotlib\uc758 \uacbd\uc6b0 \uc678\ubd80 \ub77c\uc774\ube0c\ub7ec\ub9ac\uae30 \ub54c\ubb38\uc5d0 \ub530\ub85c Layer\ub97c \ucd94\uac00\ud574\uc57c \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \uc5c5\ub85c\ub4dc\ud574\uc57c\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub54c python\uc758 Lambda \ub7f0\ud0c0\uc784\uc5d0 \ub300\ud55c \uacc4\uce35 \uacbd\ub85c\ub294 python\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc555\ucd95\ud55c zip \ud30c\uc77c\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \ub744\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"pillow.zip\n\u2502 python/PIL\n\u2514 python/Pillow-5.3.0.dist-info\n"})}),"\n",(0,a.jsx)(n.p,{children:"Ubuntu \uae30\uc900 \ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc0dd\uc131\uc744 \uc9c4\ud589\ud588\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"sudo apt update\nsudo apt install zip\nsudo apt install python3-pip\n\nmkdir python\npip3 install matplotlib -t python # pip3 install \uc124\uce58\ud560_\ud328\ud0a4\uc9c0 -t \uc124\uce58_\uacbd\ub85c\nzip -r my_layer.zip python # zip -r \uc555\ucd95_\ud30c\uc77c\uba85 \uc555\ucd95_\ud30c\uc77c\uc774_\uc874\uc7ac\ud558\ub294_\uacbd\ub85c\n"})}),"\n",(0,a.jsxs)(n.h3,{id:"no-module-named-numpycore_multiarray_umath-\uc5d0\ub7ec",children:[(0,a.jsx)(n.code,{children:"No module named 'numpy.core._multiarray_umath'"})," \uc5d0\ub7ec"]}),"\n",(0,a.jsxs)(n.p,{children:["Layer \ucd94\uac00 \ud6c4 \ub78c\ub2e4 \uc2e4\ud589 \uc2dc \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\uc600\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucc98\uc74c\uc5d0 mac\uc5d0\uc11c zip \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc5c5\ub85c\ub4dc\ud588\ub294\ub370 \ud574\ub2f9 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub294 lambda\uac00 \ub3cc\uc544\uac00\ub294 \ub3d9\uc77c\ud55c \ud658\uacbd\uc5d0\uc11c layer\ub97c \uc704\ud55c zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc9c0 \uc54a\uc544\uc11c \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud558\uac8c ec2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c \ub530\ub85c Layer\ub97c \uc0dd\uc131\ud558\uba74 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\uc801\uc815\uae30\uc220\uc5d0-\ub300\ud55c-\uc0dd\uac01",children:"\uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01"}),"\n",(0,a.jsxs)(n.p,{children:["\ud504\ub85c\uc81d\ud2b8\uc5d0 Lambda\uc640 Python\uc744 \uc0ac\uc6a9\ud558\ub824\uace0 \ud588\uc9c0\ub9cc \uc544\uc27d\uac8c\ub3c4 \ubc18\ub824\ub2f9\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","AWS Lambda\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc778\uc2a4\ud134\uc2a4\uc5d0 \ud574\ub2f9 \ucf54\ub4dc\ub97c \ubc30\ud3ec\ud558\ub294 \uac83\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc77c \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uac00\uc6a9 \uac00\ub2a5\ud55c \uc790\uc6d0, \uae30\uc220\uc758 \ub09c\uc774\ub3c4, \uc0ac\uc6a9\ud558\ub294 \ud300\uc6d0\uc744 \uace0\ub824\ud55c\ub2e4\uba74 Lambda\ub294 \uc801\uc815\uae30\uc220\uc774 \uc544\ub2d0 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud574\ub2f9 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\ub97c \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud560\uc9c0 \uc870\uae08 \ub354 \uace0\ub824\ub97c \ud574\uc57c \ub420 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\ucd5c\uc885\uc801\uc73c\ub85c Java AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4."})}),"\n",(0,a.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://aws.amazon.com/ko/lambda/",children:"AWS Lambda"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html",children:"Lambda Layer"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html",children:"Python Lambda \ud568\uc218\uc5d0 \ub300\ud55c .zip \ud30c\uc77c \uc544\uce74\uc774\ube0c \uc791\uc5c5"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://gist.github.com/ksmin23/0f3f243408a8497f766b43cf589fea7b",children:"No module named 'numpy.core._multiarray_umath'"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://techblog.woowahan.com/6217/",children:"\uc0ac\ub840\ubcc4\ub85c \uc54c\uc544\ubcf8 \uc548\uc804\ud55c S3 \uc0ac\uc6a9 \uac00\uc774\ub4dc"})]})]})}function c(e={}){const{wrapper:n}={...(0,i.ah)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var a=t(67294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var o=a.createContext({}),d=function(e){var n=a.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},p={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,o=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=d(t),x=i,u=m["".concat(o,".").concat(x)]||m[x]||p[x]||r;return t?a.createElement(u,l(l({ref:n},c),{},{components:t})):a.createElement(u,l({ref:n},c))}));c.displayName="MDXCreateElement"},13533:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/route-89cacb9b7815a3191ab1f9d9e23c43a1.png"},46365:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/routeImage-0eac25ba9b356cd034ade6e062c1ce19.png"}}]); \ No newline at end of file diff --git a/assets/js/a710d533.89036d73.js b/assets/js/a710d533.ad456f4c.js similarity index 99% rename from assets/js/a710d533.89036d73.js rename to assets/js/a710d533.ad456f4c.js index 5451f5358..32fb04849 100644 --- a/assets/js/a710d533.89036d73.js +++ b/assets/js/a710d533.ad456f4c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1711],{42089:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var r=t(85893),o=t(3905),a=t(74866),i=t(85162);const s={title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},l=void 0,c={permalink:"/tomcat-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1, 2\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-http/pull/302",date:"2023-09-11T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:12.345,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"},nextItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"}},u={authorsImageUrls:[]},d=[{value:"\ud1b0\ucea3 \uad6c\ud604",id:"\ud1b0\ucea3-\uad6c\ud604",level:3},{value:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",level:3},{value:"\ucf54\ub4dc \ub9ac\ubdf0",id:"\ucf54\ub4dc-\ub9ac\ubdf0",level:3},{value:"SessionConfig",id:"sessionconfig",level:3},{value:"HTTP \uc218\uc5c5",id:"http-\uc218\uc5c5",level:3},{value:"Thread \uc218\uc5c5",id:"thread-\uc218\uc5c5",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",pre:"pre",...(0,o.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,r.jsxs)(n.p,{children:["1, 2\ub2e8\uacc4: ",(0,r.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-http/pull/302",children:"https://github.com/woowacourse/jwp-dashboard-http/pull/302"}),(0,r.jsx)(n.br,{}),"\n","3, 4\ub2e8\uacc4: ",(0,r.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-http/pull/431",children:"https://github.com/woowacourse/jwp-dashboard-http/pull/431"})]})}),"\n",(0,r.jsx)(n.h3,{id:"\ud1b0\ucea3-\uad6c\ud604",children:"\ud1b0\ucea3 \uad6c\ud604"}),"\n",(0,r.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2616/",children:"RFC 2616"}),"\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",children:"\ub2e4\uc774\uc5b4\uadf8\ub7a8"}),"\n",(0,r.jsxs)(n.p,{children:["Catalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph coyote\n\t\tHP[Http11Processor] --\x3e A\n\t\tHP --\x3e HttpRequestParser\n\t\tHP --\x3e HttpResponseGenerator\n\t\tA[Adapter]\n end\n\n subgraph catalina\n\t\tRA[RequestAdapter] -.-> A\n\t\tAC[AbstractController] -.-> C[Controller]\n\t\tStaticController -.-> AC\n\t\tSM[SessionManger] -.-> Manager\n\t\tTC[Tomcat] --\x3e RA\n\t\tRA --\x3e C\n\t\tRA --\x3e Manager\n\t\tRA --\x3e RM\n\t\tRM[RequestMapper] --\x3e C\n end\n\n subgraph jwp\n\t\tLC[LoginController] -.-> AC\n\t\tApplication --\x3e TC\n end\n"}),"\n",(0,r.jsx)(n.h3,{id:"\ucf54\ub4dc-\ub9ac\ubdf0",children:"\ucf54\ub4dc \ub9ac\ubdf0"}),"\n",(0,r.jsxs)(n.p,{children:["\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"sessionconfig",children:"SessionConfig"}),"\n",(0,r.jsxs)(n.p,{children:["\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 ",(0,r.jsx)(n.a,{href:"https://github.com/apache/tomcat/pull/660",children:"\ucee8\ud2b8\ub9ac\ubdf0\ud2b8"}),"\ub97c \uc2dc\ub3c4\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n","\n","\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(i.Z,{value:"\uae30\uc874",label:"\uae30\uc874",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_COOKIE_NAME;\n }\n\n return result;\n}\n\npublic static String getSessionUriParamName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_PARAMETER_NAME;\n }\n\n return result;\n}\n\nprivate static String getConfiguredSessionCookieName(Context context) {\n\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc =\n context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n\n return null;\n}\n"})})}),(0,r.jsx)(i.Z,{value:"PR \uc694\uccad",label:"PR \uc694\uccad",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_COOKIE_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_PARAMETER_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n return defaultName;\n}\n"})})}),(0,r.jsx)(i.Z,{value:"\ucd5c\uc885",label:"\ucd5c\uc885",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n return defaultName;\n}\n"})})})]}),"\n",(0,r.jsx)(n.h3,{id:"http-\uc218\uc5c5",children:"HTTP \uc218\uc5c5"}),"\n",(0,r.jsxs)(n.p,{children:["\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","HTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yml",children:"server:\n compression:\n enabled: true\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 ",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/issues/21369",children:"issue"}),"\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network."}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Phil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4."}),"\n",(0,r.jsx)(n.admonition,{title:"ETag",type:"note",children:(0,r.jsxs)(n.p,{children:["ETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","MDN"]})}),"\n",(0,r.jsx)(n.h3,{id:"thread-\uc218\uc5c5",children:"Thread \uc218\uc5c5"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"threads.max"}),": Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"max-connections"}),": Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"accept-count"}),": \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:'graph LR\n C("Client") -- request --\x3e ACQ("\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \n size = accept-count") --\x3e TCQ("Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\n size = max-connections") --\x3e TP("Thread Pool\n size = threads.max")'}),"\n",(0,r.jsx)(n.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2616/",children:"RFC 2616"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag",children:"ETag, mdn"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://tomcat.apache.org/tomcat-8.5-doc/config/http.html",children:"Apache Tomcat 8 Configuration Reference"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://bcho.tistory.com/788",children:"Apache Tomcat Tuning, Terry Cho"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev-ws.tistory.com/96",children:"maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30"})]})]})}function h(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),c=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=c(t),h=o,m=p["".concat(l,".").concat(h)]||p[h]||u[h]||a;return t?r.createElement(m,i(i({ref:n},d),{},{components:t})):r.createElement(m,i({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>i});t(67294);var r=t(86010);const o={tabItem:"tabItem_Ymn6"};var a=t(85893);function i(e){let{children:n,hidden:t,className:i}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.Z)(o.tabItem,i),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>S});var r=t(67294),o=t(86010),a=t(12466),i=t(16550),s=t(20469),l=t(91980),c=t(67392),u=t(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:o}}=e;return{value:n,label:t,attributes:r,default:o}}))}(t);return function(e){const n=(0,c.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const o=(0,i.k6)(),a=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(o.location.search);n.set(a,e),o.replace({...o.location,search:n.toString()})}),[a,o])]}function g(e){const{defaultValue:n,queryString:t=!1,groupId:o}=e,a=p(e),[i,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[c,d]=m({queryString:t,groupId:o}),[g,x]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[o,a]=(0,u.Nk)(t);return[o,(0,r.useCallback)((e=>{t&&a.set(e)}),[t,a])]}({groupId:o}),b=(()=>{const e=c??g;return h({value:e,tabValues:a})?e:null})();(0,s.Z)((()=>{b&&l(b)}),[b]);return{selectedValue:i,selectValue:(0,r.useCallback)((e=>{if(!h({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),x(e)}),[d,x,a]),tabValues:a}}var x=t(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var f=t(85893);function j(e){let{className:n,block:t,selectedValue:r,selectValue:i,tabValues:s}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,a.o5)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),o=s[t].value;o!==r&&(c(n),i(o))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,f.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":t},n),children:s.map((e=>{let{value:n,label:t,attributes:a}=e;return(0,f.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...a,className:(0,o.Z)("tabs__item",b.tabItem,a?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function v(e){let{lazy:n,children:t,selectedValue:o}=e;const a=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===o));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,f.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==o})))})}function C(e){const n=g(e);return(0,f.jsxs)("div",{className:(0,o.Z)("tabs-container",b.tabList),children:[(0,f.jsx)(j,{...e,...n}),(0,f.jsx)(v,{...e,...n})]})}function S(e){const n=(0,x.Z)();return(0,f.jsx)(C,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1711],{42089:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var r=t(85893),o=t(3905),a=t(74866),i=t(85162);const s={title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},l=void 0,c={permalink:"/tomcat-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1, 2\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-http/pull/302",date:"2023-09-11T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:12.345,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"},nextItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"}},u={authorsImageUrls:[]},d=[{value:"\ud1b0\ucea3 \uad6c\ud604",id:"\ud1b0\ucea3-\uad6c\ud604",level:3},{value:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",level:3},{value:"\ucf54\ub4dc \ub9ac\ubdf0",id:"\ucf54\ub4dc-\ub9ac\ubdf0",level:3},{value:"SessionConfig",id:"sessionconfig",level:3},{value:"HTTP \uc218\uc5c5",id:"http-\uc218\uc5c5",level:3},{value:"Thread \uc218\uc5c5",id:"thread-\uc218\uc5c5",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",pre:"pre",...(0,o.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,r.jsxs)(n.p,{children:["1, 2\ub2e8\uacc4: ",(0,r.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-http/pull/302",children:"https://github.com/woowacourse/jwp-dashboard-http/pull/302"}),(0,r.jsx)(n.br,{}),"\n","3, 4\ub2e8\uacc4: ",(0,r.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-dashboard-http/pull/431",children:"https://github.com/woowacourse/jwp-dashboard-http/pull/431"})]})}),"\n",(0,r.jsx)(n.h3,{id:"\ud1b0\ucea3-\uad6c\ud604",children:"\ud1b0\ucea3 \uad6c\ud604"}),"\n",(0,r.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2616/",children:"RFC 2616"}),"\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",children:"\ub2e4\uc774\uc5b4\uadf8\ub7a8"}),"\n",(0,r.jsxs)(n.p,{children:["Catalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph coyote\n\t\tHP[Http11Processor] --\x3e A\n\t\tHP --\x3e HttpRequestParser\n\t\tHP --\x3e HttpResponseGenerator\n\t\tA[Adapter]\n end\n\n subgraph catalina\n\t\tRA[RequestAdapter] -.-> A\n\t\tAC[AbstractController] -.-> C[Controller]\n\t\tStaticController -.-> AC\n\t\tSM[SessionManger] -.-> Manager\n\t\tTC[Tomcat] --\x3e RA\n\t\tRA --\x3e C\n\t\tRA --\x3e Manager\n\t\tRA --\x3e RM\n\t\tRM[RequestMapper] --\x3e C\n end\n\n subgraph jwp\n\t\tLC[LoginController] -.-> AC\n\t\tApplication --\x3e TC\n end\n"}),"\n",(0,r.jsx)(n.h3,{id:"\ucf54\ub4dc-\ub9ac\ubdf0",children:"\ucf54\ub4dc \ub9ac\ubdf0"}),"\n",(0,r.jsxs)(n.p,{children:["\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"sessionconfig",children:"SessionConfig"}),"\n",(0,r.jsxs)(n.p,{children:["\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 ",(0,r.jsx)(n.a,{href:"https://github.com/apache/tomcat/pull/660",children:"\ucee8\ud2b8\ub9ac\ubdf0\ud2b8"}),"\ub97c \uc2dc\ub3c4\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n","\n","\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(i.Z,{value:"\uae30\uc874",label:"\uae30\uc874",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_COOKIE_NAME;\n }\n\n return result;\n}\n\npublic static String getSessionUriParamName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_PARAMETER_NAME;\n }\n\n return result;\n}\n\nprivate static String getConfiguredSessionCookieName(Context context) {\n\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc =\n context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n\n return null;\n}\n"})})}),(0,r.jsx)(i.Z,{value:"PR \uc694\uccad",label:"PR \uc694\uccad",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_COOKIE_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_PARAMETER_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n return defaultName;\n}\n"})})}),(0,r.jsx)(i.Z,{value:"\ucd5c\uc885",label:"\ucd5c\uc885",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public static String getSessionCookieName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n return defaultName;\n}\n"})})})]}),"\n",(0,r.jsx)(n.h3,{id:"http-\uc218\uc5c5",children:"HTTP \uc218\uc5c5"}),"\n",(0,r.jsxs)(n.p,{children:["\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","HTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yml",children:"server:\n compression:\n enabled: true\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 ",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/issues/21369",children:"issue"}),"\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network."}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Phil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4."}),"\n",(0,r.jsx)(n.admonition,{title:"ETag",type:"note",children:(0,r.jsxs)(n.p,{children:["ETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","MDN"]})}),"\n",(0,r.jsx)(n.h3,{id:"thread-\uc218\uc5c5",children:"Thread \uc218\uc5c5"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"threads.max"}),": Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"max-connections"}),": Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"accept-count"}),": \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:'graph LR\n C("Client") -- request --\x3e ACQ("\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \n size = accept-count") --\x3e TCQ("Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\n size = max-connections") --\x3e TP("Thread Pool\n size = threads.max")'}),"\n",(0,r.jsx)(n.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2616/",children:"RFC 2616"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag",children:"ETag, mdn"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://tomcat.apache.org/tomcat-8.5-doc/config/http.html",children:"Apache Tomcat 8 Configuration Reference"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://bcho.tistory.com/788",children:"Apache Tomcat Tuning, Terry Cho"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://dev-ws.tistory.com/96",children:"maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30"})]})]})}function h(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),c=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=c(t),h=o,m=p["".concat(l,".").concat(h)]||p[h]||u[h]||a;return t?r.createElement(m,i(i({ref:n},d),{},{components:t})):r.createElement(m,i({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>i});t(67294);var r=t(86010);const o={tabItem:"tabItem_Ymn6"};var a=t(85893);function i(e){let{children:n,hidden:t,className:i}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.Z)(o.tabItem,i),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>S});var r=t(67294),o=t(86010),a=t(12466),i=t(16550),s=t(20469),l=t(91980),c=t(67392),u=t(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:o}}=e;return{value:n,label:t,attributes:r,default:o}}))}(t);return function(e){const n=(0,c.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const o=(0,i.k6)(),a=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(o.location.search);n.set(a,e),o.replace({...o.location,search:n.toString()})}),[a,o])]}function g(e){const{defaultValue:n,queryString:t=!1,groupId:o}=e,a=p(e),[i,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[c,d]=m({queryString:t,groupId:o}),[g,x]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[o,a]=(0,u.Nk)(t);return[o,(0,r.useCallback)((e=>{t&&a.set(e)}),[t,a])]}({groupId:o}),b=(()=>{const e=c??g;return h({value:e,tabValues:a})?e:null})();(0,s.Z)((()=>{b&&l(b)}),[b]);return{selectedValue:i,selectValue:(0,r.useCallback)((e=>{if(!h({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),x(e)}),[d,x,a]),tabValues:a}}var x=t(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var f=t(85893);function j(e){let{className:n,block:t,selectedValue:r,selectValue:i,tabValues:s}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,a.o5)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),o=s[t].value;o!==r&&(c(n),i(o))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,f.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":t},n),children:s.map((e=>{let{value:n,label:t,attributes:a}=e;return(0,f.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...a,className:(0,o.Z)("tabs__item",b.tabItem,a?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function v(e){let{lazy:n,children:t,selectedValue:o}=e;const a=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===o));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,f.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==o})))})}function C(e){const n=g(e);return(0,f.jsxs)("div",{className:(0,o.Z)("tabs-container",b.tabList),children:[(0,f.jsx)(j,{...e,...n}),(0,f.jsx)(v,{...e,...n})]})}function S(e){const n=(0,x.Z)();return(0,f.jsx)(C,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file diff --git a/assets/js/a8cba70f.18be7e46.js b/assets/js/a8cba70f.b05901e8.js similarity index 98% rename from assets/js/a8cba70f.18be7e46.js rename to assets/js/a8cba70f.b05901e8.js index 8eabafdf5..d2175c622 100644 --- a/assets/js/a8cba70f.18be7e46.js +++ b/assets/js/a8cba70f.b05901e8.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2261],{58367:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>c,toc:()=>j});var t=n(85893),s=n(3905);const l={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",slug:"woowacourse-level1-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/woowacourse-level1-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",description:"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.",date:"2023-04-01T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 1\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.48,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",slug:"woowacourse-level1-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",permalink:"/custom-jdbc-template"},nextItem:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",permalink:"/chess-retrospective"}},o={authorsImageUrls:[]},j=[{value:"Keep",id:"keep",level:3},{value:"Problem",id:"problem",level:3},{value:"Try",id:"try",level:3},{value:"\ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70",id:"\ub808\ubca8-1\uc744-\ub9c8\ubb34\ub9ac\ud558\uba70",level:3}];function a(e){const r={br:"br",code:"code",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(r.p,{children:["\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\ud14c\ucf54\ub97c \uc2dc\uc791\ud558\uae30 \uc804 \ub0b4\uac00 \uc815\ud574\ub450\uc5c8\ub358 \ubaa9\ud45c \uc774\uc0c1\uc73c\ub85c \ub2ec\uc131\ud588\uae30 \ub54c\ubb38\uc5d0 \ub9e4\uc6b0 \ub9cc\uc871\uc2a4\ub7fd\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud63c\uc790 \ub3c5\ud559\uc744 \ud560 \ub550 \uc774 \ubc29\ud5a5\uc73c\ub85c \uacf5\ubd80\ud558\ub294 \uac8c \ub9de\ub294\uc9c0 \uacc4\uc18d \ubc18\ucd94\ud558\ub2e4 \uacb0\uad6d \ubb34\uae30\ub825\ud568\uc5d0 \ube60\uc838\ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \uc774\uc81c\ub294 \uac19\uc774 \uacf5\ubd80\ud560 \uc0ac\ub78c\ub3c4 \uc788\uace0, \uc774\uc57c\uae30\ud560 \uc0ac\ub78c\ub3c4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc990\uae30\ub294 \uc77c\ub9cc \ub0a8\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"keep",children:"Keep"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub098\ub9cc\uc758 \ub8e8\ud2f4 \ub9cc\ub4e4\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc2a4\uc2a4\ub85c\uac00 \uc678\ubd80\uc758 \uc601\ud5a5\uc744 \ub9ce\uc774 \ubc1b\ub294\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucd5c\ub300\ud55c \uafb8\uc900\ud788 \ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ub9e4\uc77c 8\uc2dc\uc5d0 \ub3c4\ucc29\ud558\uc5ec \uc544\uce68\uc5d0 \ud574\uc57c \ud560 \uc77c\uc744 \uc815\ub9ac\ud558\uac70\ub098, \uc6b0\uc120\uc21c\uc704\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud558\uace0",(0,t.jsx)(r.br,{}),"\n","\uc18c\ud654\ub2a5\ub825\uc774 \ubd80\uc871\ud558\uae30 \ub54c\ubb38\uc5d0 \uc810\uc2ec\uc740 \ub3c4\uc2dc\ub77d(\uadf8\ub798\ubd24\uc790 \uacc4\ub7802\uac1c)\uc744 \uc900\ube44\ud558\uace0",(0,t.jsx)(r.br,{}),"\n","\ud56d\uc0c1 \ub611\uac19\uc740 \ucee8\ub514\uc158\uc744 \uc720\uc9c0\ud558\uae30 \uc704\ud574 \ud56d\uc0c1 6\uc2dc\uc5d0 \uc9d1\uc5d0 \uac04\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uc81c \ubc14\ube60\uc9c8 \ud14c\ub2c8 \uc77c\ucc0d \uc9d1\uc5d0 \uac00\ub294 \uc77c\uc740 \uc5b4\uca54 \uc218 \uc5c6\uc774 \uc904\uc5b4\ub4e4\uaca0\uc9c0\ub9cc\ud83d\ude22"]}),"\n",(0,t.jsx)(r.p,{children:"\uc120\ud0dd\ub3c4 \ube44\uc6a9\uc774\ub2e4. \uc55e\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\uc774 \ud544\uc694 \uc5c6\ub294 \ubd80\ubd84\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\ub4e4\uc5b4\uc57c\uaca0\ub2e4."}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["10\uba85 \uc815\ub3c4\uc758 \ud06c\ub8e8\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b0\uace0 \uce5c\ud558\uac8c \uc9c0\ub0b8\ub2e4\uba74 \uc131\uacf5\uc801\uc774\ub77c\uace0 \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\ub2e4 \ubcf4\ub2c8 \ub354 \ub9ce\uc740 \ud06c\ub8e8\ub4e4\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b4 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c\ub3c4 \ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uace0 \uc544\ubb34 \ub54c\ub098 \ub9d0\uc744 \uac78 \uc218 \uc788\ub294 \ud06c\ub8e8\uac00 \ub298\uc5b4\ub098\uae38 :)"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uae00\uc4f0\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["\uae00\uc744 \uc798 \uc4f0\ub294 \ud3b8\uc740 \uc544\ub2c8\uc9c0\ub9cc \uafb8\uc900\ud788 \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub9e4 \ubbf8\uc158\ub9c8\ub2e4 \ud68c\uace0\ub97c \uc791\uc131\ud558\ub2c8 \uc0dd\uac01\ub3c4 \uc815\ub9ac\ub418\uace0 \uac1c\uc120\uc810\ub3c4 \ucc3e\uc744 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc5d0\ub294 \ub808\ubca8\ub9c8\ub2e4 \uae00\uc4f0\uae30\ub97c \uc9c4\ud589\ud558\ub294\ub370, \uc6b4\uc774 \uc88b\uac8c \uae00\uc4f0\uae30 \uc0c1\uc744 \ubc1b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc0ac\uc2e4 \uac89\uc73c\ub85c \ub4dc\ub7ec\ub0b4\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uaf2d \ubc1b\uc544\ubcf4\uace0 \uc2f6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uae00\uc4f0\uae30 \uc870\uc6d0, \ud22c\ud45c\ud574 \uc900 \ud06c\ub8e8\ub4e4\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514"})}),"\n",(0,t.jsxs)(r.p,{children:["\ub204\ub204, \uc8fc\ub178, \ub2e4\uc990, \ub9d0\ub791, \ubc15\uc2a4\ud130, \uc624\uc789, \uae43\uc9f1\uc640 \ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514\ub97c \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uacfc\uc5f0 \ub3c4\uc6c0\uc774 \ub420\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud558\uba74\uc11c \uc131\uc7a5\uc744 \ub9ce\uc774 \ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud22c\uc790\ud55c \uc2dc\uac04 \ub300\ube44 \uac00\uc131\ube44\uac00 \uc88b\uc740 \ud65c\ub3d9\uc774\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub204\ub204\uac00 \uc2a4\ud130\ub514\uc7a5\uc778\ub370 \uacfc\uc5f0 \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00\ub824\ub098?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub808\ubca8 \uc778\ud130\ubdf0"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc778\ud130\ubdf0\ud560 \ub54c \ub9ce\uc774 \ub5a8\uc9c0 \uc54a\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub0a8\ub4e4 \uc55e\uc5d0\uc11c \uc774\uc57c\uae30\ub97c \ud558\uac70\ub098, \uba74\uc811\uc744 \ubcf4\uba74 \ud56d\uc0c1 \uc5c4\uccad \ub5a8\uc5b4\uc11c \uac71\uc815\ud588\ub294\ub370",(0,t.jsx)(r.br,{}),"\n","\uae30\uc220\uc801\uc778 \uc9c8\ubb38\uc744 \ubc1b\uc558\uc744 \ub54c \ub5a8\uc9c0 \uc54a\uace0 \uc798 \ub300\ub2f5\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \ub2e4\ub978 \ud06c\ub8e8\uac00 \uc9c8\ubb38\ud588\uc744 \ub54c, \ucd5c\ub300\ud55c \uc774\ud574\ud558\uae30 \uc27d\uac8c \uc124\uba85\ud558\ub824\uace0 \ud588\ub358 \uacbd\ud5d8\uc774 \ub3c4\uc6c0\uc774 \ub41c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ud6c4 \ub808\ubca8 \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"\ub300\ub2f5\ud558\uba74\uc11c \uc9c8\ubb38\uc744 \uacc4\uc18d \uc0dd\uac01\ud558\uba70 \uc78a\uc5b4\ubc84\ub9ac\uc9c0 \ub9d0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\ub450\uad04\uc2dd \ud45c\ud604"}),"\n",(0,t.jsx)(r.li,{children:"\uc124\uba85\ud558\ub2e4\uac00 \uc798\ubabb \uc124\uba85\ud55c \uac83 \uac19\uc73c\uba74 \ub2e4 \ub04a\uace0 \ub2e4\uc2dc \uc774\uc57c\uae30\ud574\ub3c4 \ub420\uc9c0 \ubb3c\uc5b4\ubcf4\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uc124\uba85\ud560 \uc218 \uc788\uc744\ub9cc\ud07c \uc2dc\uac04 \ucda9\ubd84\ud788 \uac00\uc9c0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uc778\ud130\ubdf0\uc5b4\uc758 \uc9c8\ubb38 \uc758\ub3c4\ub97c \uba85\ud655\ud788 \uc774\ud574\ud558\uc9c0 \ubabb\ud588\ub2e4\uba74 \uc758\ub3c4 \ub2e4\uc2dc \ubb3c\uc5b4\ubcf4\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\ub05d\ub9fa\ub294 \ubd80\ubd84 \uc5f0\uc2b5\ud558\uae30(\uc790\uc2e0\uac10 \uc788\uac8c)"}),"\n",(0,t.jsx)(r.li,{children:"\uae30\uc220\uc801\uc778 \uc9d1\ucc29\uac00\uc9c0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud788 \uc900\ube44\ud588\uc73c\uba74 \ud611\uc5c5 \uad00\ub828 \uc9c8\ubb38\ub3c4 \uc900\ube44\ud558\uae30"}),"\n"]}),"\n",(0,t.jsx)(r.h3,{id:"problem",children:"Problem"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ud65c\ub3d9 \uc911 \ud558\ub098\ub77c\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud398\uc5b4\ub294 \ub9e4\ubc88 \ubc14\ub00c\uace0, \ubbf8\uc158\uc758 \ubcf5\uc7a1\ub3c4\ub3c4 \uc99d\uac00\ud558\uae30 \ub54c\ubb38\uc778 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc18c\ud1b5 \ub2a5\ub825, \uc2dc\uac04\uad00\ub9ac\uac00 \ubd80\uc871\ud588\uace0, \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uace0, \ud68c\uace0\ub97c \ud558\ub2e4 \ubcf4\ub2c8 \ub098\ub9cc\uc758 \ub178\ud558\uc6b0\uac00 \uc313\uc774\ub294 \ub290\ub08c\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub808\ubca8 2\uc5d0\uc11c\ub294 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc120\ud558\uc5ec \ud568\uaed8\ud558\uace0 \uc2f6\uc740 \ud398\uc5b4\uac00 \ub418\uace0 \uc2f6\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc9d1\uc911\ud558\ub294 \uc2dc\uac04\u23f1\ufe0f \ubd80\uc871"})}),"\n",(0,t.jsxs)(r.p,{children:["\ub808\ubca8 1\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc9d1\uc911\ud558\ub294 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ub978 \uc544\uce68\uacfc \uc624\ud6c4\uc5d0 \uac1c\uc778\uc801\uc73c\ub85c \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \uacf5\uac04\uc744 \uc608\uc57d\ud574\uc11c \uc628\uc804\ud788 \ub098\ub9cc\uc758 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"try",children:"Try"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud5c8\ube0c\ud83c\udf3f\uc640\uc758 \ud2f0\ud0c0\uc784?"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc744 \ub298\ub9b4 \ubc29\ubc95\uc744 \uc0dd\uac01\ud558\ub2e4\uac00 \ub300\ud654\ub97c \ub098\ub204\uc9c0 \ubabb\ud55c \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \uae5c\uc9dd \ucee4\ud53c\ucc57\uc744 \ud558\uba74 \uc5b4\ub5a8\uae4c \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 \uc7a1\ub2f4\ubc29\uc5d0 ",(0,t.jsx)(r.code,{children:"\uc800\uc640 \ucee4\ud53c\ucc57 \ud558\uc2e4 \ubd84 :)"})," \ud558\uba74\uc11c \uc62c\ub9b4 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucc38\uc5ec\ud558\ub294 \uc0ac\ub78c\uc774 \uc788\uc744\uc9c0, \uc548 \uc88b\uac8c \ubcf4\ub294 \uac8c \uc544\ub2d0\uc9c0 \uac71\uc815\ub418\uc9c0\ub9cc \uadf8\ub798\ub3c4 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc800\ub791 \ud5c8\ube0c\ud2f0 \ud55c\uc794 \ud558\uc2e4\ub798\uc694?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uae30\uc220\uc801\uc778 \ubd80\ubd84"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0 \uc870\uae08 \ub354 \ubb34\uac8c\ub97c \ub450\ub2e4 \ubcf4\ub2c8 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc774 \ubd80\uc871\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc2dc\uac04\uc758 \uc5ec\uc720\uac00 \ub420 \ub54c \ucc45\uc744 \uc870\uae08\uc529 \uc77d\uc5b4\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube14\ub85c\uadf8\uc5d0 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \ub9ce\uc774 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\ub294 \uc2dc\uac04\ub3c4 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ub808\ubca8-1\uc744-\ub9c8\ubb34\ub9ac\ud558\uba70",children:"\ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70"}),"\n",(0,t.jsxs)(r.p,{children:["\uc2dc\uac04\uc774 \ube60\ub974\uac8c \ud758\ub7ec\uac14\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud0c0\uc778\uc5d0\uac8c \uc88b\uc740 \uc601\ud5a5\uc744 \uc8fc\uae30\uc704\ud574, \ubc29\ud559\ub3d9\uc548 \ub098\ub97c \ucc59\uae30\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub610\ud55c \ud568\uaed8 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc744 \ubaa9\ud45c\ub85c \uc55e\uc73c\ub85c\ub3c4 \uafb8\uc900\ud788 \uc758\uc2dd\uc801 \ub178\ub825\uc744 \ud574\uc57c\uaca0\ub2e4."]})]})}function p(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>j});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function l(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var o=t.createContext({}),j=function(e){var r=t.useContext(o),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},a={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},p=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,l=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),x=j(n),d=s,h=x["".concat(o,".").concat(d)]||x[d]||a[d]||l;return n?t.createElement(h,i(i({ref:r},p),{},{components:n})):t.createElement(h,i({ref:r},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2261],{58367:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>c,toc:()=>j});var t=n(85893),s=n(3905);const l={title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",slug:"woowacourse-level1-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/woowacourse-level1-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",description:"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.",date:"2023-04-01T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 1\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.48,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",slug:"woowacourse-level1-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",permalink:"/chess-retrospective"},nextItem:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",permalink:"/custom-jdbc-template"}},o={authorsImageUrls:[]},j=[{value:"Keep",id:"keep",level:3},{value:"Problem",id:"problem",level:3},{value:"Try",id:"try",level:3},{value:"\ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70",id:"\ub808\ubca8-1\uc744-\ub9c8\ubb34\ub9ac\ud558\uba70",level:3}];function a(e){const r={br:"br",code:"code",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(r.p,{children:["\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\ud14c\ucf54\ub97c \uc2dc\uc791\ud558\uae30 \uc804 \ub0b4\uac00 \uc815\ud574\ub450\uc5c8\ub358 \ubaa9\ud45c \uc774\uc0c1\uc73c\ub85c \ub2ec\uc131\ud588\uae30 \ub54c\ubb38\uc5d0 \ub9e4\uc6b0 \ub9cc\uc871\uc2a4\ub7fd\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud63c\uc790 \ub3c5\ud559\uc744 \ud560 \ub550 \uc774 \ubc29\ud5a5\uc73c\ub85c \uacf5\ubd80\ud558\ub294 \uac8c \ub9de\ub294\uc9c0 \uacc4\uc18d \ubc18\ucd94\ud558\ub2e4 \uacb0\uad6d \ubb34\uae30\ub825\ud568\uc5d0 \ube60\uc838\ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \uc774\uc81c\ub294 \uac19\uc774 \uacf5\ubd80\ud560 \uc0ac\ub78c\ub3c4 \uc788\uace0, \uc774\uc57c\uae30\ud560 \uc0ac\ub78c\ub3c4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc990\uae30\ub294 \uc77c\ub9cc \ub0a8\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"keep",children:"Keep"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub098\ub9cc\uc758 \ub8e8\ud2f4 \ub9cc\ub4e4\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc2a4\uc2a4\ub85c\uac00 \uc678\ubd80\uc758 \uc601\ud5a5\uc744 \ub9ce\uc774 \ubc1b\ub294\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucd5c\ub300\ud55c \uafb8\uc900\ud788 \ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ub9e4\uc77c 8\uc2dc\uc5d0 \ub3c4\ucc29\ud558\uc5ec \uc544\uce68\uc5d0 \ud574\uc57c \ud560 \uc77c\uc744 \uc815\ub9ac\ud558\uac70\ub098, \uc6b0\uc120\uc21c\uc704\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud558\uace0",(0,t.jsx)(r.br,{}),"\n","\uc18c\ud654\ub2a5\ub825\uc774 \ubd80\uc871\ud558\uae30 \ub54c\ubb38\uc5d0 \uc810\uc2ec\uc740 \ub3c4\uc2dc\ub77d(\uadf8\ub798\ubd24\uc790 \uacc4\ub7802\uac1c)\uc744 \uc900\ube44\ud558\uace0",(0,t.jsx)(r.br,{}),"\n","\ud56d\uc0c1 \ub611\uac19\uc740 \ucee8\ub514\uc158\uc744 \uc720\uc9c0\ud558\uae30 \uc704\ud574 \ud56d\uc0c1 6\uc2dc\uc5d0 \uc9d1\uc5d0 \uac04\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uc81c \ubc14\ube60\uc9c8 \ud14c\ub2c8 \uc77c\ucc0d \uc9d1\uc5d0 \uac00\ub294 \uc77c\uc740 \uc5b4\uca54 \uc218 \uc5c6\uc774 \uc904\uc5b4\ub4e4\uaca0\uc9c0\ub9cc\ud83d\ude22"]}),"\n",(0,t.jsx)(r.p,{children:"\uc120\ud0dd\ub3c4 \ube44\uc6a9\uc774\ub2e4. \uc55e\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\uc774 \ud544\uc694 \uc5c6\ub294 \ubd80\ubd84\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\ub4e4\uc5b4\uc57c\uaca0\ub2e4."}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["10\uba85 \uc815\ub3c4\uc758 \ud06c\ub8e8\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b0\uace0 \uce5c\ud558\uac8c \uc9c0\ub0b8\ub2e4\uba74 \uc131\uacf5\uc801\uc774\ub77c\uace0 \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\ub2e4 \ubcf4\ub2c8 \ub354 \ub9ce\uc740 \ud06c\ub8e8\ub4e4\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b4 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c\ub3c4 \ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uace0 \uc544\ubb34 \ub54c\ub098 \ub9d0\uc744 \uac78 \uc218 \uc788\ub294 \ud06c\ub8e8\uac00 \ub298\uc5b4\ub098\uae38 :)"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uae00\uc4f0\uae30"})}),"\n",(0,t.jsxs)(r.p,{children:["\uae00\uc744 \uc798 \uc4f0\ub294 \ud3b8\uc740 \uc544\ub2c8\uc9c0\ub9cc \uafb8\uc900\ud788 \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub9e4 \ubbf8\uc158\ub9c8\ub2e4 \ud68c\uace0\ub97c \uc791\uc131\ud558\ub2c8 \uc0dd\uac01\ub3c4 \uc815\ub9ac\ub418\uace0 \uac1c\uc120\uc810\ub3c4 \ucc3e\uc744 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc5d0\ub294 \ub808\ubca8\ub9c8\ub2e4 \uae00\uc4f0\uae30\ub97c \uc9c4\ud589\ud558\ub294\ub370, \uc6b4\uc774 \uc88b\uac8c \uae00\uc4f0\uae30 \uc0c1\uc744 \ubc1b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc0ac\uc2e4 \uac89\uc73c\ub85c \ub4dc\ub7ec\ub0b4\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uaf2d \ubc1b\uc544\ubcf4\uace0 \uc2f6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uae00\uc4f0\uae30 \uc870\uc6d0, \ud22c\ud45c\ud574 \uc900 \ud06c\ub8e8\ub4e4\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514"})}),"\n",(0,t.jsxs)(r.p,{children:["\ub204\ub204, \uc8fc\ub178, \ub2e4\uc990, \ub9d0\ub791, \ubc15\uc2a4\ud130, \uc624\uc789, \uae43\uc9f1\uc640 \ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514\ub97c \uc9c4\ud589\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uacfc\uc5f0 \ub3c4\uc6c0\uc774 \ub420\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud558\uba74\uc11c \uc131\uc7a5\uc744 \ub9ce\uc774 \ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud22c\uc790\ud55c \uc2dc\uac04 \ub300\ube44 \uac00\uc131\ube44\uac00 \uc88b\uc740 \ud65c\ub3d9\uc774\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub204\ub204\uac00 \uc2a4\ud130\ub514\uc7a5\uc778\ub370 \uacfc\uc5f0 \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00\ub824\ub098?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub808\ubca8 \uc778\ud130\ubdf0"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc778\ud130\ubdf0\ud560 \ub54c \ub9ce\uc774 \ub5a8\uc9c0 \uc54a\uc544\uc11c \uc88b\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub0a8\ub4e4 \uc55e\uc5d0\uc11c \uc774\uc57c\uae30\ub97c \ud558\uac70\ub098, \uba74\uc811\uc744 \ubcf4\uba74 \ud56d\uc0c1 \uc5c4\uccad \ub5a8\uc5b4\uc11c \uac71\uc815\ud588\ub294\ub370",(0,t.jsx)(r.br,{}),"\n","\uae30\uc220\uc801\uc778 \uc9c8\ubb38\uc744 \ubc1b\uc558\uc744 \ub54c \ub5a8\uc9c0 \uc54a\uace0 \uc798 \ub300\ub2f5\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \ub2e4\ub978 \ud06c\ub8e8\uac00 \uc9c8\ubb38\ud588\uc744 \ub54c, \ucd5c\ub300\ud55c \uc774\ud574\ud558\uae30 \uc27d\uac8c \uc124\uba85\ud558\ub824\uace0 \ud588\ub358 \uacbd\ud5d8\uc774 \ub3c4\uc6c0\uc774 \ub41c \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ud6c4 \ub808\ubca8 \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"\ub300\ub2f5\ud558\uba74\uc11c \uc9c8\ubb38\uc744 \uacc4\uc18d \uc0dd\uac01\ud558\uba70 \uc78a\uc5b4\ubc84\ub9ac\uc9c0 \ub9d0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\ub450\uad04\uc2dd \ud45c\ud604"}),"\n",(0,t.jsx)(r.li,{children:"\uc124\uba85\ud558\ub2e4\uac00 \uc798\ubabb \uc124\uba85\ud55c \uac83 \uac19\uc73c\uba74 \ub2e4 \ub04a\uace0 \ub2e4\uc2dc \uc774\uc57c\uae30\ud574\ub3c4 \ub420\uc9c0 \ubb3c\uc5b4\ubcf4\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uc124\uba85\ud560 \uc218 \uc788\uc744\ub9cc\ud07c \uc2dc\uac04 \ucda9\ubd84\ud788 \uac00\uc9c0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uc778\ud130\ubdf0\uc5b4\uc758 \uc9c8\ubb38 \uc758\ub3c4\ub97c \uba85\ud655\ud788 \uc774\ud574\ud558\uc9c0 \ubabb\ud588\ub2e4\uba74 \uc758\ub3c4 \ub2e4\uc2dc \ubb3c\uc5b4\ubcf4\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\ub05d\ub9fa\ub294 \ubd80\ubd84 \uc5f0\uc2b5\ud558\uae30(\uc790\uc2e0\uac10 \uc788\uac8c)"}),"\n",(0,t.jsx)(r.li,{children:"\uae30\uc220\uc801\uc778 \uc9d1\ucc29\uac00\uc9c0\uae30"}),"\n",(0,t.jsx)(r.li,{children:"\uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud788 \uc900\ube44\ud588\uc73c\uba74 \ud611\uc5c5 \uad00\ub828 \uc9c8\ubb38\ub3c4 \uc900\ube44\ud558\uae30"}),"\n"]}),"\n",(0,t.jsx)(r.h3,{id:"problem",children:"Problem"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ud65c\ub3d9 \uc911 \ud558\ub098\ub77c\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud398\uc5b4\ub294 \ub9e4\ubc88 \ubc14\ub00c\uace0, \ubbf8\uc158\uc758 \ubcf5\uc7a1\ub3c4\ub3c4 \uc99d\uac00\ud558\uae30 \ub54c\ubb38\uc778 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc18c\ud1b5 \ub2a5\ub825, \uc2dc\uac04\uad00\ub9ac\uac00 \ubd80\uc871\ud588\uace0, \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uace0, \ud68c\uace0\ub97c \ud558\ub2e4 \ubcf4\ub2c8 \ub098\ub9cc\uc758 \ub178\ud558\uc6b0\uac00 \uc313\uc774\ub294 \ub290\ub08c\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub808\ubca8 2\uc5d0\uc11c\ub294 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc120\ud558\uc5ec \ud568\uaed8\ud558\uace0 \uc2f6\uc740 \ud398\uc5b4\uac00 \ub418\uace0 \uc2f6\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc9d1\uc911\ud558\ub294 \uc2dc\uac04\u23f1\ufe0f \ubd80\uc871"})}),"\n",(0,t.jsxs)(r.p,{children:["\ub808\ubca8 1\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc9d1\uc911\ud558\ub294 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\ub978 \uc544\uce68\uacfc \uc624\ud6c4\uc5d0 \uac1c\uc778\uc801\uc73c\ub85c \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \uacf5\uac04\uc744 \uc608\uc57d\ud574\uc11c \uc628\uc804\ud788 \ub098\ub9cc\uc758 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"try",children:"Try"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud5c8\ube0c\ud83c\udf3f\uc640\uc758 \ud2f0\ud0c0\uc784?"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc744 \ub298\ub9b4 \ubc29\ubc95\uc744 \uc0dd\uac01\ud558\ub2e4\uac00 \ub300\ud654\ub97c \ub098\ub204\uc9c0 \ubabb\ud55c \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \uae5c\uc9dd \ucee4\ud53c\ucc57\uc744 \ud558\uba74 \uc5b4\ub5a8\uae4c \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 \uc7a1\ub2f4\ubc29\uc5d0 ",(0,t.jsx)(r.code,{children:"\uc800\uc640 \ucee4\ud53c\ucc57 \ud558\uc2e4 \ubd84 :)"})," \ud558\uba74\uc11c \uc62c\ub9b4 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucc38\uc5ec\ud558\ub294 \uc0ac\ub78c\uc774 \uc788\uc744\uc9c0, \uc548 \uc88b\uac8c \ubcf4\ub294 \uac8c \uc544\ub2d0\uc9c0 \uac71\uc815\ub418\uc9c0\ub9cc \uadf8\ub798\ub3c4 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc800\ub791 \ud5c8\ube0c\ud2f0 \ud55c\uc794 \ud558\uc2e4\ub798\uc694?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uae30\uc220\uc801\uc778 \ubd80\ubd84"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0 \uc870\uae08 \ub354 \ubb34\uac8c\ub97c \ub450\ub2e4 \ubcf4\ub2c8 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc774 \ubd80\uc871\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc2dc\uac04\uc758 \uc5ec\uc720\uac00 \ub420 \ub54c \ucc45\uc744 \uc870\uae08\uc529 \uc77d\uc5b4\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ube14\ub85c\uadf8\uc5d0 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \ub9ce\uc774 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\ub294 \uc2dc\uac04\ub3c4 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ub808\ubca8-1\uc744-\ub9c8\ubb34\ub9ac\ud558\uba70",children:"\ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70"}),"\n",(0,t.jsxs)(r.p,{children:["\uc2dc\uac04\uc774 \ube60\ub974\uac8c \ud758\ub7ec\uac14\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud0c0\uc778\uc5d0\uac8c \uc88b\uc740 \uc601\ud5a5\uc744 \uc8fc\uae30\uc704\ud574, \ubc29\ud559\ub3d9\uc548 \ub098\ub97c \ucc59\uae30\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub610\ud55c \ud568\uaed8 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc744 \ubaa9\ud45c\ub85c \uc55e\uc73c\ub85c\ub3c4 \uafb8\uc900\ud788 \uc758\uc2dd\uc801 \ub178\ub825\uc744 \ud574\uc57c\uaca0\ub2e4."]})]})}function p(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>j});var t=n(67294);function s(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function l(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(s[n]=e[n]);return s}(e,r);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var o=t.createContext({}),j=function(e){var r=t.useContext(o),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},a={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},p=t.forwardRef((function(e,r){var n=e.components,s=e.mdxType,l=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),x=j(n),d=s,h=x["".concat(o,".").concat(d)]||x[d]||a[d]||l;return n?t.createElement(h,i(i({ref:r},p),{},{components:n})):t.createElement(h,i({ref:r},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/aacfeabc.8863a050.js b/assets/js/aacfeabc.33e0e3f7.js similarity index 98% rename from assets/js/aacfeabc.8863a050.js rename to assets/js/aacfeabc.33e0e3f7.js index 17ab0e722..c978e3ddd 100644 --- a/assets/js/aacfeabc.8863a050.js +++ b/assets/js/aacfeabc.33e0e3f7.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8909],{60965:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var i=s(85893),t=s(3905);const a={title:"Jenkins\ub85c CI/CD \uc124\uc815",slug:"jenkins",tags:["Jenkins","Elastic Beanstalk"]},r=void 0,l={permalink:"/jenkins",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",source:"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",title:"Jenkins\ub85c CI/CD \uc124\uc815",description:"\uc124\uc815 \ud658\uacbd",date:"2023-04-30T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 30\uc77c",tags:[{label:"Jenkins",permalink:"/tags/jenkins"},{label:"Elastic Beanstalk",permalink:"/tags/elastic-beanstalk"}],readingTime:7.495,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Jenkins\ub85c CI/CD \uc124\uc815",slug:"jenkins",tags:["Jenkins","Elastic Beanstalk"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",permalink:"/tecochat-retrospective-2"},nextItem:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",permalink:"/tecochat-retrospective-1"}},o={authorsImageUrls:[]},c=[{value:"\uc124\uc815 \ud658\uacbd",id:"\uc124\uc815-\ud658\uacbd",level:3},{value:"[EC2 CLI] Swap \uba54\ubaa8\ub9ac \uc124\uc815",id:"ec2-cli-swap-\uba54\ubaa8\ub9ac-\uc124\uc815",level:3},{value:"[EC2 CLI] jenkins \uc124\uce58",id:"ec2-cli-jenkins-\uc124\uce58",level:3},{value:"[EC2 CLI] Jenkins \uc2dc\uc791",id:"ec2-cli-jenkins-\uc2dc\uc791",level:3},{value:"[EC2 CLI] nginx & git \uc124\uce58",id:"ec2-cli-nginx--git-\uc124\uce58",level:3},{value:"[EC2 CLI] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815",id:"ec2-cli-nginx-\ub9ac\ubc84\uc2a4-\ud504\ub85d\uc2dc-\uc124\uc815",level:3},{value:"[Jenkins] Jenkins \uc811\uc18d",id:"jenkins-jenkins-\uc811\uc18d",level:3},{value:"[Jenkins] Jenkins Blue Ocean \uc124\uce58",id:"jenkins-jenkins-blue-ocean-\uc124\uce58",level:3},{value:"[AWS IAM & EC2] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30",id:"aws-iam--ec2-iam\uc73c\ub85c-ec2-\uc778\uc2a4\ud134\uc2a4-\uad8c\ud55c-\uc124\uc815\ud558\uae30",level:3},{value:"[AWS S3] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131",id:"aws-s3-jar-\ud30c\uc77c\uc744-\uc5c5\ub85c\ub4dc-\ud560-s3-\ubc84\ud0b7-\uc0dd\uc131",level:3},{value:"[Github] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131",id:"github-blue-ocean\uc5d0\uc11c-\ud30c\uc774\ud504\ub77c\uc778-\uc0dd\uc131\uc5d0-\ud544\uc694\ud55c-github-token-\uc0dd\uc131",level:3},{value:"[Jenkins] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791",id:"jenkins-\ube14\ub8e8-\uc624\uc158-\uc2dc\uc791",level:3},{value:"[Github Repsoitory] Jenkinsfile \uc124\uc815",id:"github-repsoitory-jenkinsfile-\uc124\uc815",level:3},{value:"[Github] Webhooks \uc124\uc815",id:"github-webhooks-\uc124\uc815",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",br:"br",code:"code",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"\uc124\uc815-\ud658\uacbd",children:"\uc124\uc815 \ud658\uacbd"}),"\n",(0,i.jsxs)(n.p,{children:["\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc774\ubbf8\uc9c0: Amazon Linux 2023 AMI",(0,i.jsx)(n.br,{}),"\n","\uc544\ud0a4\ud14d\uccd0: ARM",(0,i.jsx)(n.br,{}),"\n","\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small",(0,i.jsx)(n.br,{}),"\n","\ud658\uacbd \uad6c\uc131\uc774 \uc644\ub8cc\ub41c Elastic Beanstalk",(0,i.jsx)(n.br,{}),"\n","\ub2e8\uc77c Spring Boot \ud504\ub85c\uc81d\ud2b8\uac00 \uc874\uc7ac\ud558\ub294 Github Repository"]}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-swap-\uba54\ubaa8\ub9ac-\uc124\uc815",children:"[EC2 CLI] Swap \uba54\ubaa8\ub9ac \uc124\uc815"}),"\n",(0,i.jsxs)(n.p,{children:["t4g.small\uc774 \ub7a8\uc774 2G\uc778\ub370 \ub7a8\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \ub290\uaef4\uc838\uc11c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc544\ub798 \uba85\ub839\uc5b4\ub97c \ub530\ub77c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud558\uace0 free -h \uba85\ub839\uc5b4\ub97c \ud1b5\ud574 \uc798 \uc124\uc815\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# fallocate \uc774\uc6a9\ud558\uc5ec \uc2a4\uc651 \ud30c\uc77c \uc0dd\uc131\nsudo fallocate -l 2G /swapfile\n\n# \uad8c\ud55c \uc124\uc815\nsudo chmod 600 /swapfile\n\n# \ud30c\uc77c\uc744 Swap \ud3ec\ub9f7\uc73c\ub85c \ubcc0\uacbd \ud6c4 \uc2dc\uc2a4\ud15c\uc5d0 \ub4f1\ub85d\nsudo mkswap /swapfile\nsudo swapon /swapfile\n\n# Swap \uba54\ubaa8\ub9ac \ubd80\ud305\uc2dc \uc790\ub3d9\uc73c\ub85c \ub9c8\uc6b4\ud2b8\ud558\ub3c4\ub85d \uc801\uc6a9\n# \ucd5c\ud558\ub2e8\uc5d0 \ub2e4\uc74c \uad6c\ubb38 \uc124\uc815 -> /swapfile swap swap defaults 0 0\nsudo vim /etc/fstab\n"})}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-jenkins-\uc124\uce58",children:"[EC2 CLI] jenkins \uc124\uce58"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo wget -O /etc/yum.repos.d/jenkins.repo \\\n https://pkg.jenkins.io/redhat-stable/jenkins.repo\nsudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key\nsudo yum upgrade\nsudo yum install java-17-amazon-corretto-devel\nsudo yum install jenkins\nsudo systemctl daemon-reload\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos",children:"Jenkins \uacf5\uc2dd \ud648\ud398\uc774\uc9c0"})," \ub97c \ucc38\uace0\ud558\uc5ec \uc124\uce58\ud558\ub294 \uac8c \uc88b\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-jenkins-\uc2dc\uc791",children:"[EC2 CLI] Jenkins \uc2dc\uc791"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo systemctl enable jenkins\nsudo systemctl start jenkins\n"})}),"\n",(0,i.jsx)(n.p,{children:"enable\ub85c \uc124\uc815\ud558\uc5ec \ubd80\ud305\uc2dc \uc790\ub3d9\uc2dc\uc791 \ub418\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-nginx--git-\uc124\uce58",children:"[EC2 CLI] nginx & git \uc124\uce58"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo yum install nginx\nsudo systemctl enable nginx\nsudo systemctl start nginx\n\nsudo yum install git\n"})}),"\n",(0,i.jsx)(n.p,{children:"nginx\uc640 \ucf54\ub4dc\ub97c \ubd88\ub7ec\uc62c \ub54c \uc0ac\uc6a9\ud560 git\uc744 \uc124\uce58\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-nginx-\ub9ac\ubc84\uc2a4-\ud504\ub85d\uc2dc-\uc124\uc815",children:"[EC2 CLI] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:"\uc544\ub798 \uc124\uc815 \ud30c\uc77c\uc740 \uacf5\uc2dd \ud648\ud398\uc774\uc9c0\uc5d0\uc11c \uc548\ub0b4\ud55c \uae30\ubcf8\uc801\uc778 \uc124\uc815 \ud30c\uc77c\uc774\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'upstream jenkins {\n keepalive 32; # keepalive connections\n server 127.0.0.1:8080; # jenkins ip and port\n}\n\n# Required for Jenkins websocket agents\nmap $http_upgrade $connection_upgrade {\n default upgrade;\n \'\' close;\n}\n\nserver {\n listen 80; # Listen on port 80 for IPv4 requests\n\n server_name jenkins.example.com; # replace \'jenkins.example.com\' with your server domain name\n\n # this is the jenkins web root directory\n # (mentioned in the output of "systemctl cat jenkins")\n root /var/run/jenkins/war/;\n\n access_log /var/log/nginx/jenkins.access.log;\n error_log /var/log/nginx/jenkins.error.log;\n\n # pass through headers from Jenkins that Nginx considers invalid\n ignore_invalid_headers off;\n\n location ~ "^/static/[0-9a-fA-F]{8}\\/(.*)$" {\n # rewrite all static files into requests to the root\n # E.g /static/12345678/css/something.css will become /css/something.css\n rewrite "^/static/[0-9a-fA-F]{8}\\/(.*)" /$1 last;\n }\n\n location /userContent {\n # have nginx handle all the static requests to userContent folder\n # note : This is the $JENKINS_HOME dir\n root /var/lib/jenkins/;\n if (!-f $request_filename){\n # this file does not exist, might be a directory or a /**view** url\n rewrite (.*) /$1 last;\n break;\n }\n sendfile on;\n }\n\n location / {\n sendfile off;\n proxy_pass http://jenkins;\n proxy_redirect default;\n proxy_http_version 1.1;\n\n # Required for Jenkins websocket agents\n proxy_set_header Connection $connection_upgrade;\n proxy_set_header Upgrade $http_upgrade;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_max_temp_file_size 0;\n\n #this is the maximum upload size\n client_max_body_size 10m;\n client_body_buffer_size 128k;\n\n proxy_connect_timeout 90;\n proxy_send_timeout 90;\n proxy_read_timeout 90;\n proxy_buffering off;\n proxy_request_buffering off; # Required for HTTP CLI commands\n proxy_set_header Connection ""; # Clear for keepalive\n }\n\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Jenkins\ub294 8080 \ud3ec\ud2b8\ub85c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc\ub97c \uc124\uc815\ud574\uc900\ub2e4.",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.code,{children:"/etc/nginx/conf.d"}),"\xa0\uc544\ub798\xa0",(0,i.jsx)(n.code,{children:"default.conf"}),"\xa0\ud30c\uc77c\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uace0 \uc704\uc640 \uac19\uc774 \uc785\ub825\ud558\uace0 \uc800\uc7a5\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","nginx\uc758 \uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\uc5d0 \uc874\uc7ac\ud558\ub294\xa0",(0,i.jsx)(n.code,{children:"include /etc/nginx/conf.d/*.conf;"}),"\xa0\uc124\uc815 \ub54c\ubb38\uc5d0\xa0",(0,i.jsx)(n.code,{children:".conf"}),"\xa0\ub85c \ub05d\ub09c\ub2e4\uba74 \uc124\uc815\uc774 \uc801\uc6a9\ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc124\uc815 \ud6c4\xa0",(0,i.jsx)(n.code,{children:"sudo nginx -t"}),"\ub85c \uc124\uc815\ud30c\uc77c\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud558\uace0,\xa0",(0,i.jsx)(n.code,{children:"sudo systemctl restart nginx"}),"\xa0\uba85\ub839\uc5b4\ub85c nginx\ub97c \uc7ac\uc2dc\uc791\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-jenkins-\uc811\uc18d",children:"[Jenkins] Jenkins \uc811\uc18d"}),"\n",(0,i.jsxs)(n.p,{children:["Jenkins\ub97c \uc124\uce58\ud55c EC2 \uc778\uc2a4\ud134\uc2a4 \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc5d0 80\ubc88 \ud3ec\ud2b8\uac00 \uc5f4\ub824\uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","EC2\uc758 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \ub4e4\uc5b4\uac00\uba74 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-start",src:s(71399).Z+"",width:"2008",height:"1836"})}),"\n",(0,i.jsxs)(n.p,{children:["\ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud558\ub294\ub370 ",(0,i.jsx)(n.code,{children:"sudo cat /var/lib/jenkins/secrets/initialAdminPasswor"})," \ub97c \uc785\ub825\ud574 \ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc5bb\uc744 \uc218 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 \ud50c\ub7ec\uadf8\uc778 \uc124\uc815 \ucc3d\uc774 \ub098\uc62c\ud150\ub370 ",(0,i.jsx)(n.code,{children:"install suggested plugins"}),"\uc744 \ud074\ub9ad\ud558\uc5ec Jenkins\uac00 \ucd94\ucc9c\ud558\ub294 \uae30\ubcf8 \ud50c\ub7ec\uadf8\uc778\ub4e4\uc744 \uc124\uce58\ud558\uba74 \ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud50c\ub7ec\uadf8\uc778\uc744 \uc124\uce58\ud558\uba74 \uacc4\uc815 \ubc0f \uc8fc\uc18c \uc124\uc815\uc744 \ud574\uc57c\ud558\ub294\ub370 \uc774\uac74 \ud3b8\ud558\uac8c \uc124\uc815\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-jenkins-blue-ocean-\uc124\uce58",children:"[Jenkins] Jenkins Blue Ocean \uc124\uce58"}),"\n",(0,i.jsx)(n.p,{children:"Jenkins \uad00\ub9ac \u2192 Plugin Manager\uc5d0\uc11c Blue Ocean\uc744 \uac80\uc0c9\ud574 \uc124\uce58\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"aws-iam--ec2-iam\uc73c\ub85c-ec2-\uc778\uc2a4\ud134\uc2a4-\uad8c\ud55c-\uc124\uc815\ud558\uae30",children:"[AWS IAM & EC2] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30"}),"\n",(0,i.jsxs)(n.p,{children:["S3\uc640 Elastic Beanstalk\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub824\uba74 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk \ub450 \uac1c\uc758 \uc815\ucc45\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uc5ed\ud560\uc744 \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","IAM\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc774 \uc5ed\ud560\uc744 \ud558\ub098 \uc0c8\ub85c \uc0dd\uc131\ud55c\ub2e4."]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"\uc5d4\ud130\ud2f0 \uc120\ud0dd"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam1",src:s(30618).Z+"",width:"2282",height:"1028"})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsx)(n.li,{children:"\uad8c\ud55c \ucd94\uac00"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam2",src:s(56786).Z+"",width:"2300",height:"880"})}),"\n",(0,i.jsxs)(n.ol,{start:"3",children:["\n",(0,i.jsx)(n.li,{children:"\uc774\ub984 \uc9c0\uc815, \uac80\ud1a0 \ubc0f \uc0dd\uc131"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam3",src:s(63303).Z+"",width:"1872",height:"1724"})}),"\n",(0,i.jsxs)(n.ol,{start:"4",children:["\n",(0,i.jsx)(n.li,{children:"\uc0dd\uc131\ud55c IAM EC2 Jenkins \uc778\uc2a4\ud134\uc2a4\ub97c \uc120\ud0dd\ud558\uace0, \uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc744 \ub20c\ub7ec Role \uc124\uc815"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam4",src:s(82150).Z+"",width:"2264",height:"602"})}),"\n",(0,i.jsx)(n.h3,{id:"aws-s3-jar-\ud30c\uc77c\uc744-\uc5c5\ub85c\ub4dc-\ud560-s3-\ubc84\ud0b7-\uc0dd\uc131",children:"[AWS S3] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131"}),"\n",(0,i.jsx)(n.p,{children:"\ubc84\ud0b7\uc744 \uc0dd\uc131\ud560 \ub54c \ub2e4\uc74c \uc124\uc815\uc744 \uc81c\uc678\ud558\uace0 \ubaa8\ub450 \ucc28\ub2e8 \ud65c\uc131\ud654\ub97c \ud574\uc900\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"\uc0c8 ACL(\uc561\uc138\uc2a4 \uc81c\uc5b4 \ubaa9\ub85d)\uc744 \ud1b5\ud574 \ubd80\uc5ec\ub41c \ubc84\ud0b7 \ubc0f \uac1d\uccb4\uc5d0 \ub300\ud55c \ud37c\ube14\ub9ad \uc561\uc138\uc2a4 \ucc28\ub2e8"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-s3",src:s(36238).Z+"",width:"1636",height:"1258"})}),"\n",(0,i.jsx)(n.h3,{id:"github-blue-ocean\uc5d0\uc11c-\ud30c\uc774\ud504\ub77c\uc778-\uc0dd\uc131\uc5d0-\ud544\uc694\ud55c-github-token-\uc0dd\uc131",children:"[Github] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131"}),"\n",(0,i.jsxs)(n.p,{children:["repo, user",":email"," \uad8c\ud55c\uc774 \uc788\ub294 \ud1a0\ud070\uc774 \ud544\uc694\ud558\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-\ube14\ub8e8-\uc624\uc158-\uc2dc\uc791",children:"[Jenkins] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean1",src:s(29666).Z+"",width:"2390",height:"1372"})}),"\n",(0,i.jsxs)(n.p,{children:["\ube14\ub8e8 \uc624\uc158 \uc5f4\uae30\ub85c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc0dd\uc131\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud1a0\ud070 \uc785\ub825 \u2192 \uc870\uc9c1 \uc120\ud0dd \u2192 CI/CD \uc124\uc815\ud560 Repository \uc120\ud0dd\uc744 \ud558\uba74 \ud30c\uc774\ud504\ub77c\uc778 \ucc3d\uc73c\ub85c \ub118\uc5b4\uac04\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Jenkinsfile\uc744 \uc9c1\uc811 \uc791\uc131\ud558\uc5ec \uc124\uc815\ud558\uae30 \uc704\ud574 \uac04\ub2e8\ud558\uac8c print \ud558\ub098 \ucd9c\ub825\ud558\ub294 \uac83\uc73c\ub85c \uc124\uc815\ud588\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean2",src:s(49614).Z+"",width:"2076",height:"638"})}),"\n",(0,i.jsx)(n.p,{children:"\ud30c\uc774\ud504\ub77c\uc778\uc774 \uc2e4\ud589\ub420 \ud150\ub370 pipeline status\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ucd08\ub85d\ubd88\uc774 \ub728\uba74 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean3",src:s(71079).Z+"",width:"1084",height:"626"})}),"\n",(0,i.jsx)(n.h3,{id:"github-repsoitory-jenkinsfile-\uc124\uc815",children:"[Github Repsoitory] Jenkinsfile \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:"\ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\uc744 \ud1b5\ud574 \uc124\uc815\ud558\uba74 Jenkinsfile\uc774 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc9c0\uace0, \uc544\ub798\uc640 \uac19\uc774 \uc6d0\ud558\ub294 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc124\uc815\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"pipeline {\n agent any\n stages {\n stage('build and test') {\n steps {\n sh '/gradlew clean build'\n }\n }\n stage('zip') {\n steps {\n sh 'mv ./build/libs/woowachat.jar .'\n sh 'zip -r woowachat.zip .platform delivery.jar Procfile'\n }\n }\n stage('upload') {\n steps {\n sh 'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2'\n }\n }\n stage('deploy') {\n steps {\n sh 'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket=\"woowa-chat\",S3Key=\"woowachat.zip\"'\n sh 'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}'\n }\n }\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"github-webhooks-\uc124\uc815",children:"[Github] Webhooks \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"github-hook",src:s(36642).Z+"",width:"1428",height:"1148"})}),"\n",(0,i.jsxs)(n.p,{children:["push \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud560 \ub54c ",(0,i.jsx)(n.code,{children:"http://Jenkins\uc8fc\uc18c/github-webhook/"})," \ub85c post request\ub97c \ud558\ub3c4\ub85d \uc6f9\ud6c5\uc744 \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos",children:"Install Jenkins - CentOS, Jenkins"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/",children:"Nginx Reverse Proxy Configuration, Jenkins"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html",children:"Amazon Corretto 17 JDK Install, AWS"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/linux/al2023/release-notes/all-packages-al2023-20230419.html",children:"Amazon Linux 2023 packages, AWS"})]})]})}function h(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3905:(e,n,s)=>{s.d(n,{ah:()=>c});var i=s(67294);function t(e,n,s){return n in e?Object.defineProperty(e,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[n]=s,e}function a(e,n){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),s.push.apply(s,i)}return s}function r(e){for(var n=1;n=0||(t[s]=e[s]);return t}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,s)&&(t[s]=e[s])}return t}var o=i.createContext({}),c=function(e){var n=i.useContext(o),s=n;return e&&(s="function"==typeof e?e(n):r(r({},n),e)),s},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},h=i.forwardRef((function(e,n){var s=e.components,t=e.mdxType,a=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),p=c(s),u=t,j=p["".concat(o,".").concat(u)]||p[u]||d[u]||a;return s?i.createElement(j,r(r({ref:n},h),{},{components:s})):i.createElement(j,r({ref:n},h))}));h.displayName="MDXCreateElement"},30618:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam1-e6d63be6b9f41d63e91d604138e6b07c.png"},56786:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam2-557683fc91b1c22330d081d6050dfe82.png"},63303:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam3-94248e9194dd58bb16d0289af47a4260.png"},82150:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam4-54ccc5a4e64d31f7eeab89d39ebf772f.png"},36238:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-s3-757380d36e5492c962f75dae024994e5.png"},36642:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/github-hook-e9ebe0acb3ff0086ecebbd8c857ffe39.png"},29666:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean1-bd108d887d700ea081e4b0a3d83ad459.png"},49614:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean2-408c6c90e4a5371becc4d1013fba1212.png"},71079:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean3-4050a206b3efe95a3c9f39c3f7a47ad7.png"},71399:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-start-dce0d7051054c398d2a707c75c685234.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8909],{60965:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var i=s(85893),t=s(3905);const a={title:"Jenkins\ub85c CI/CD \uc124\uc815",slug:"jenkins",tags:["Jenkins","Elastic Beanstalk"]},r=void 0,l={permalink:"/jenkins",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",source:"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",title:"Jenkins\ub85c CI/CD \uc124\uc815",description:"\uc124\uc815 \ud658\uacbd",date:"2023-04-30T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 30\uc77c",tags:[{label:"Jenkins",permalink:"/tags/jenkins"},{label:"Elastic Beanstalk",permalink:"/tags/elastic-beanstalk"}],readingTime:7.495,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Jenkins\ub85c CI/CD \uc124\uc815",slug:"jenkins",tags:["Jenkins","Elastic Beanstalk"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",permalink:"/tecochat-retrospective-1"},nextItem:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",permalink:"/tecochat-retrospective-2"}},o={authorsImageUrls:[]},c=[{value:"\uc124\uc815 \ud658\uacbd",id:"\uc124\uc815-\ud658\uacbd",level:3},{value:"[EC2 CLI] Swap \uba54\ubaa8\ub9ac \uc124\uc815",id:"ec2-cli-swap-\uba54\ubaa8\ub9ac-\uc124\uc815",level:3},{value:"[EC2 CLI] jenkins \uc124\uce58",id:"ec2-cli-jenkins-\uc124\uce58",level:3},{value:"[EC2 CLI] Jenkins \uc2dc\uc791",id:"ec2-cli-jenkins-\uc2dc\uc791",level:3},{value:"[EC2 CLI] nginx & git \uc124\uce58",id:"ec2-cli-nginx--git-\uc124\uce58",level:3},{value:"[EC2 CLI] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815",id:"ec2-cli-nginx-\ub9ac\ubc84\uc2a4-\ud504\ub85d\uc2dc-\uc124\uc815",level:3},{value:"[Jenkins] Jenkins \uc811\uc18d",id:"jenkins-jenkins-\uc811\uc18d",level:3},{value:"[Jenkins] Jenkins Blue Ocean \uc124\uce58",id:"jenkins-jenkins-blue-ocean-\uc124\uce58",level:3},{value:"[AWS IAM & EC2] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30",id:"aws-iam--ec2-iam\uc73c\ub85c-ec2-\uc778\uc2a4\ud134\uc2a4-\uad8c\ud55c-\uc124\uc815\ud558\uae30",level:3},{value:"[AWS S3] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131",id:"aws-s3-jar-\ud30c\uc77c\uc744-\uc5c5\ub85c\ub4dc-\ud560-s3-\ubc84\ud0b7-\uc0dd\uc131",level:3},{value:"[Github] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131",id:"github-blue-ocean\uc5d0\uc11c-\ud30c\uc774\ud504\ub77c\uc778-\uc0dd\uc131\uc5d0-\ud544\uc694\ud55c-github-token-\uc0dd\uc131",level:3},{value:"[Jenkins] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791",id:"jenkins-\ube14\ub8e8-\uc624\uc158-\uc2dc\uc791",level:3},{value:"[Github Repsoitory] Jenkinsfile \uc124\uc815",id:"github-repsoitory-jenkinsfile-\uc124\uc815",level:3},{value:"[Github] Webhooks \uc124\uc815",id:"github-webhooks-\uc124\uc815",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",br:"br",code:"code",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"\uc124\uc815-\ud658\uacbd",children:"\uc124\uc815 \ud658\uacbd"}),"\n",(0,i.jsxs)(n.p,{children:["\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc774\ubbf8\uc9c0: Amazon Linux 2023 AMI",(0,i.jsx)(n.br,{}),"\n","\uc544\ud0a4\ud14d\uccd0: ARM",(0,i.jsx)(n.br,{}),"\n","\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small",(0,i.jsx)(n.br,{}),"\n","\ud658\uacbd \uad6c\uc131\uc774 \uc644\ub8cc\ub41c Elastic Beanstalk",(0,i.jsx)(n.br,{}),"\n","\ub2e8\uc77c Spring Boot \ud504\ub85c\uc81d\ud2b8\uac00 \uc874\uc7ac\ud558\ub294 Github Repository"]}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-swap-\uba54\ubaa8\ub9ac-\uc124\uc815",children:"[EC2 CLI] Swap \uba54\ubaa8\ub9ac \uc124\uc815"}),"\n",(0,i.jsxs)(n.p,{children:["t4g.small\uc774 \ub7a8\uc774 2G\uc778\ub370 \ub7a8\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \ub290\uaef4\uc838\uc11c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc544\ub798 \uba85\ub839\uc5b4\ub97c \ub530\ub77c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud558\uace0 free -h \uba85\ub839\uc5b4\ub97c \ud1b5\ud574 \uc798 \uc124\uc815\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# fallocate \uc774\uc6a9\ud558\uc5ec \uc2a4\uc651 \ud30c\uc77c \uc0dd\uc131\nsudo fallocate -l 2G /swapfile\n\n# \uad8c\ud55c \uc124\uc815\nsudo chmod 600 /swapfile\n\n# \ud30c\uc77c\uc744 Swap \ud3ec\ub9f7\uc73c\ub85c \ubcc0\uacbd \ud6c4 \uc2dc\uc2a4\ud15c\uc5d0 \ub4f1\ub85d\nsudo mkswap /swapfile\nsudo swapon /swapfile\n\n# Swap \uba54\ubaa8\ub9ac \ubd80\ud305\uc2dc \uc790\ub3d9\uc73c\ub85c \ub9c8\uc6b4\ud2b8\ud558\ub3c4\ub85d \uc801\uc6a9\n# \ucd5c\ud558\ub2e8\uc5d0 \ub2e4\uc74c \uad6c\ubb38 \uc124\uc815 -> /swapfile swap swap defaults 0 0\nsudo vim /etc/fstab\n"})}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-jenkins-\uc124\uce58",children:"[EC2 CLI] jenkins \uc124\uce58"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo wget -O /etc/yum.repos.d/jenkins.repo \\\n https://pkg.jenkins.io/redhat-stable/jenkins.repo\nsudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key\nsudo yum upgrade\nsudo yum install java-17-amazon-corretto-devel\nsudo yum install jenkins\nsudo systemctl daemon-reload\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos",children:"Jenkins \uacf5\uc2dd \ud648\ud398\uc774\uc9c0"})," \ub97c \ucc38\uace0\ud558\uc5ec \uc124\uce58\ud558\ub294 \uac8c \uc88b\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-jenkins-\uc2dc\uc791",children:"[EC2 CLI] Jenkins \uc2dc\uc791"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo systemctl enable jenkins\nsudo systemctl start jenkins\n"})}),"\n",(0,i.jsx)(n.p,{children:"enable\ub85c \uc124\uc815\ud558\uc5ec \ubd80\ud305\uc2dc \uc790\ub3d9\uc2dc\uc791 \ub418\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-nginx--git-\uc124\uce58",children:"[EC2 CLI] nginx & git \uc124\uce58"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo yum install nginx\nsudo systemctl enable nginx\nsudo systemctl start nginx\n\nsudo yum install git\n"})}),"\n",(0,i.jsx)(n.p,{children:"nginx\uc640 \ucf54\ub4dc\ub97c \ubd88\ub7ec\uc62c \ub54c \uc0ac\uc6a9\ud560 git\uc744 \uc124\uce58\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-nginx-\ub9ac\ubc84\uc2a4-\ud504\ub85d\uc2dc-\uc124\uc815",children:"[EC2 CLI] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:"\uc544\ub798 \uc124\uc815 \ud30c\uc77c\uc740 \uacf5\uc2dd \ud648\ud398\uc774\uc9c0\uc5d0\uc11c \uc548\ub0b4\ud55c \uae30\ubcf8\uc801\uc778 \uc124\uc815 \ud30c\uc77c\uc774\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'upstream jenkins {\n keepalive 32; # keepalive connections\n server 127.0.0.1:8080; # jenkins ip and port\n}\n\n# Required for Jenkins websocket agents\nmap $http_upgrade $connection_upgrade {\n default upgrade;\n \'\' close;\n}\n\nserver {\n listen 80; # Listen on port 80 for IPv4 requests\n\n server_name jenkins.example.com; # replace \'jenkins.example.com\' with your server domain name\n\n # this is the jenkins web root directory\n # (mentioned in the output of "systemctl cat jenkins")\n root /var/run/jenkins/war/;\n\n access_log /var/log/nginx/jenkins.access.log;\n error_log /var/log/nginx/jenkins.error.log;\n\n # pass through headers from Jenkins that Nginx considers invalid\n ignore_invalid_headers off;\n\n location ~ "^/static/[0-9a-fA-F]{8}\\/(.*)$" {\n # rewrite all static files into requests to the root\n # E.g /static/12345678/css/something.css will become /css/something.css\n rewrite "^/static/[0-9a-fA-F]{8}\\/(.*)" /$1 last;\n }\n\n location /userContent {\n # have nginx handle all the static requests to userContent folder\n # note : This is the $JENKINS_HOME dir\n root /var/lib/jenkins/;\n if (!-f $request_filename){\n # this file does not exist, might be a directory or a /**view** url\n rewrite (.*) /$1 last;\n break;\n }\n sendfile on;\n }\n\n location / {\n sendfile off;\n proxy_pass http://jenkins;\n proxy_redirect default;\n proxy_http_version 1.1;\n\n # Required for Jenkins websocket agents\n proxy_set_header Connection $connection_upgrade;\n proxy_set_header Upgrade $http_upgrade;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_max_temp_file_size 0;\n\n #this is the maximum upload size\n client_max_body_size 10m;\n client_body_buffer_size 128k;\n\n proxy_connect_timeout 90;\n proxy_send_timeout 90;\n proxy_read_timeout 90;\n proxy_buffering off;\n proxy_request_buffering off; # Required for HTTP CLI commands\n proxy_set_header Connection ""; # Clear for keepalive\n }\n\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Jenkins\ub294 8080 \ud3ec\ud2b8\ub85c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc\ub97c \uc124\uc815\ud574\uc900\ub2e4.",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.code,{children:"/etc/nginx/conf.d"}),"\xa0\uc544\ub798\xa0",(0,i.jsx)(n.code,{children:"default.conf"}),"\xa0\ud30c\uc77c\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uace0 \uc704\uc640 \uac19\uc774 \uc785\ub825\ud558\uace0 \uc800\uc7a5\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","nginx\uc758 \uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\uc5d0 \uc874\uc7ac\ud558\ub294\xa0",(0,i.jsx)(n.code,{children:"include /etc/nginx/conf.d/*.conf;"}),"\xa0\uc124\uc815 \ub54c\ubb38\uc5d0\xa0",(0,i.jsx)(n.code,{children:".conf"}),"\xa0\ub85c \ub05d\ub09c\ub2e4\uba74 \uc124\uc815\uc774 \uc801\uc6a9\ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc124\uc815 \ud6c4\xa0",(0,i.jsx)(n.code,{children:"sudo nginx -t"}),"\ub85c \uc124\uc815\ud30c\uc77c\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud558\uace0,\xa0",(0,i.jsx)(n.code,{children:"sudo systemctl restart nginx"}),"\xa0\uba85\ub839\uc5b4\ub85c nginx\ub97c \uc7ac\uc2dc\uc791\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-jenkins-\uc811\uc18d",children:"[Jenkins] Jenkins \uc811\uc18d"}),"\n",(0,i.jsxs)(n.p,{children:["Jenkins\ub97c \uc124\uce58\ud55c EC2 \uc778\uc2a4\ud134\uc2a4 \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc5d0 80\ubc88 \ud3ec\ud2b8\uac00 \uc5f4\ub824\uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","EC2\uc758 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \ub4e4\uc5b4\uac00\uba74 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-start",src:s(71399).Z+"",width:"2008",height:"1836"})}),"\n",(0,i.jsxs)(n.p,{children:["\ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud558\ub294\ub370 ",(0,i.jsx)(n.code,{children:"sudo cat /var/lib/jenkins/secrets/initialAdminPasswor"})," \ub97c \uc785\ub825\ud574 \ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc5bb\uc744 \uc218 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 \ud50c\ub7ec\uadf8\uc778 \uc124\uc815 \ucc3d\uc774 \ub098\uc62c\ud150\ub370 ",(0,i.jsx)(n.code,{children:"install suggested plugins"}),"\uc744 \ud074\ub9ad\ud558\uc5ec Jenkins\uac00 \ucd94\ucc9c\ud558\ub294 \uae30\ubcf8 \ud50c\ub7ec\uadf8\uc778\ub4e4\uc744 \uc124\uce58\ud558\uba74 \ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud50c\ub7ec\uadf8\uc778\uc744 \uc124\uce58\ud558\uba74 \uacc4\uc815 \ubc0f \uc8fc\uc18c \uc124\uc815\uc744 \ud574\uc57c\ud558\ub294\ub370 \uc774\uac74 \ud3b8\ud558\uac8c \uc124\uc815\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-jenkins-blue-ocean-\uc124\uce58",children:"[Jenkins] Jenkins Blue Ocean \uc124\uce58"}),"\n",(0,i.jsx)(n.p,{children:"Jenkins \uad00\ub9ac \u2192 Plugin Manager\uc5d0\uc11c Blue Ocean\uc744 \uac80\uc0c9\ud574 \uc124\uce58\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"aws-iam--ec2-iam\uc73c\ub85c-ec2-\uc778\uc2a4\ud134\uc2a4-\uad8c\ud55c-\uc124\uc815\ud558\uae30",children:"[AWS IAM & EC2] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30"}),"\n",(0,i.jsxs)(n.p,{children:["S3\uc640 Elastic Beanstalk\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub824\uba74 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk \ub450 \uac1c\uc758 \uc815\ucc45\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uc5ed\ud560\uc744 \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","IAM\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc774 \uc5ed\ud560\uc744 \ud558\ub098 \uc0c8\ub85c \uc0dd\uc131\ud55c\ub2e4."]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"\uc5d4\ud130\ud2f0 \uc120\ud0dd"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam1",src:s(30618).Z+"",width:"2282",height:"1028"})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsx)(n.li,{children:"\uad8c\ud55c \ucd94\uac00"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam2",src:s(56786).Z+"",width:"2300",height:"880"})}),"\n",(0,i.jsxs)(n.ol,{start:"3",children:["\n",(0,i.jsx)(n.li,{children:"\uc774\ub984 \uc9c0\uc815, \uac80\ud1a0 \ubc0f \uc0dd\uc131"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam3",src:s(63303).Z+"",width:"1872",height:"1724"})}),"\n",(0,i.jsxs)(n.ol,{start:"4",children:["\n",(0,i.jsx)(n.li,{children:"\uc0dd\uc131\ud55c IAM EC2 Jenkins \uc778\uc2a4\ud134\uc2a4\ub97c \uc120\ud0dd\ud558\uace0, \uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc744 \ub20c\ub7ec Role \uc124\uc815"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam4",src:s(82150).Z+"",width:"2264",height:"602"})}),"\n",(0,i.jsx)(n.h3,{id:"aws-s3-jar-\ud30c\uc77c\uc744-\uc5c5\ub85c\ub4dc-\ud560-s3-\ubc84\ud0b7-\uc0dd\uc131",children:"[AWS S3] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131"}),"\n",(0,i.jsx)(n.p,{children:"\ubc84\ud0b7\uc744 \uc0dd\uc131\ud560 \ub54c \ub2e4\uc74c \uc124\uc815\uc744 \uc81c\uc678\ud558\uace0 \ubaa8\ub450 \ucc28\ub2e8 \ud65c\uc131\ud654\ub97c \ud574\uc900\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"\uc0c8 ACL(\uc561\uc138\uc2a4 \uc81c\uc5b4 \ubaa9\ub85d)\uc744 \ud1b5\ud574 \ubd80\uc5ec\ub41c \ubc84\ud0b7 \ubc0f \uac1d\uccb4\uc5d0 \ub300\ud55c \ud37c\ube14\ub9ad \uc561\uc138\uc2a4 \ucc28\ub2e8"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-s3",src:s(36238).Z+"",width:"1636",height:"1258"})}),"\n",(0,i.jsx)(n.h3,{id:"github-blue-ocean\uc5d0\uc11c-\ud30c\uc774\ud504\ub77c\uc778-\uc0dd\uc131\uc5d0-\ud544\uc694\ud55c-github-token-\uc0dd\uc131",children:"[Github] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131"}),"\n",(0,i.jsxs)(n.p,{children:["repo, user",":email"," \uad8c\ud55c\uc774 \uc788\ub294 \ud1a0\ud070\uc774 \ud544\uc694\ud558\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-\ube14\ub8e8-\uc624\uc158-\uc2dc\uc791",children:"[Jenkins] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean1",src:s(29666).Z+"",width:"2390",height:"1372"})}),"\n",(0,i.jsxs)(n.p,{children:["\ube14\ub8e8 \uc624\uc158 \uc5f4\uae30\ub85c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc0dd\uc131\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud1a0\ud070 \uc785\ub825 \u2192 \uc870\uc9c1 \uc120\ud0dd \u2192 CI/CD \uc124\uc815\ud560 Repository \uc120\ud0dd\uc744 \ud558\uba74 \ud30c\uc774\ud504\ub77c\uc778 \ucc3d\uc73c\ub85c \ub118\uc5b4\uac04\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Jenkinsfile\uc744 \uc9c1\uc811 \uc791\uc131\ud558\uc5ec \uc124\uc815\ud558\uae30 \uc704\ud574 \uac04\ub2e8\ud558\uac8c print \ud558\ub098 \ucd9c\ub825\ud558\ub294 \uac83\uc73c\ub85c \uc124\uc815\ud588\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean2",src:s(49614).Z+"",width:"2076",height:"638"})}),"\n",(0,i.jsx)(n.p,{children:"\ud30c\uc774\ud504\ub77c\uc778\uc774 \uc2e4\ud589\ub420 \ud150\ub370 pipeline status\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ucd08\ub85d\ubd88\uc774 \ub728\uba74 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean3",src:s(71079).Z+"",width:"1084",height:"626"})}),"\n",(0,i.jsx)(n.h3,{id:"github-repsoitory-jenkinsfile-\uc124\uc815",children:"[Github Repsoitory] Jenkinsfile \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:"\ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\uc744 \ud1b5\ud574 \uc124\uc815\ud558\uba74 Jenkinsfile\uc774 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc9c0\uace0, \uc544\ub798\uc640 \uac19\uc774 \uc6d0\ud558\ub294 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc124\uc815\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"pipeline {\n agent any\n stages {\n stage('build and test') {\n steps {\n sh '/gradlew clean build'\n }\n }\n stage('zip') {\n steps {\n sh 'mv ./build/libs/woowachat.jar .'\n sh 'zip -r woowachat.zip .platform delivery.jar Procfile'\n }\n }\n stage('upload') {\n steps {\n sh 'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2'\n }\n }\n stage('deploy') {\n steps {\n sh 'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket=\"woowa-chat\",S3Key=\"woowachat.zip\"'\n sh 'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}'\n }\n }\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"github-webhooks-\uc124\uc815",children:"[Github] Webhooks \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"github-hook",src:s(36642).Z+"",width:"1428",height:"1148"})}),"\n",(0,i.jsxs)(n.p,{children:["push \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud560 \ub54c ",(0,i.jsx)(n.code,{children:"http://Jenkins\uc8fc\uc18c/github-webhook/"})," \ub85c post request\ub97c \ud558\ub3c4\ub85d \uc6f9\ud6c5\uc744 \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos",children:"Install Jenkins - CentOS, Jenkins"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/",children:"Nginx Reverse Proxy Configuration, Jenkins"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html",children:"Amazon Corretto 17 JDK Install, AWS"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/linux/al2023/release-notes/all-packages-al2023-20230419.html",children:"Amazon Linux 2023 packages, AWS"})]})]})}function h(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3905:(e,n,s)=>{s.d(n,{ah:()=>c});var i=s(67294);function t(e,n,s){return n in e?Object.defineProperty(e,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[n]=s,e}function a(e,n){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),s.push.apply(s,i)}return s}function r(e){for(var n=1;n=0||(t[s]=e[s]);return t}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,s)&&(t[s]=e[s])}return t}var o=i.createContext({}),c=function(e){var n=i.useContext(o),s=n;return e&&(s="function"==typeof e?e(n):r(r({},n),e)),s},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},h=i.forwardRef((function(e,n){var s=e.components,t=e.mdxType,a=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),p=c(s),u=t,j=p["".concat(o,".").concat(u)]||p[u]||d[u]||a;return s?i.createElement(j,r(r({ref:n},h),{},{components:s})):i.createElement(j,r({ref:n},h))}));h.displayName="MDXCreateElement"},30618:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam1-e6d63be6b9f41d63e91d604138e6b07c.png"},56786:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam2-557683fc91b1c22330d081d6050dfe82.png"},63303:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam3-94248e9194dd58bb16d0289af47a4260.png"},82150:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam4-54ccc5a4e64d31f7eeab89d39ebf772f.png"},36238:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-s3-757380d36e5492c962f75dae024994e5.png"},36642:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/github-hook-e9ebe0acb3ff0086ecebbd8c857ffe39.png"},29666:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean1-bd108d887d700ea081e4b0a3d83ad459.png"},49614:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean2-408c6c90e4a5371becc4d1013fba1212.png"},71079:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean3-4050a206b3efe95a3c9f39c3f7a47ad7.png"},71399:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-start-dce0d7051054c398d2a707c75c685234.png"}}]); \ No newline at end of file diff --git a/assets/js/ac3fdf5d.9c827f3a.js b/assets/js/ac3fdf5d.a14ec008.js similarity index 98% rename from assets/js/ac3fdf5d.9c827f3a.js rename to assets/js/ac3fdf5d.a14ec008.js index 012aecad9..6bdc9636d 100644 --- a/assets/js/ac3fdf5d.9c827f3a.js +++ b/assets/js/ac3fdf5d.a14ec008.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8548],{40911:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>a,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=n(85893),i=n(3905);const l={title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",slug:"web-application-evolution",tags:["web application"]},o=void 0,s={permalink:"/web-application-evolution",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",source:"@site/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",description:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",date:"2023-09-30T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 30\uc77c",tags:[{label:"web application",permalink:"/tags/web-application"}],readingTime:7.5,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",slug:"web-application-evolution",tags:["web application"]},unlisted:!1,prevItem:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",permalink:"/spring-test-isolation"},nextItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"}},a={authorsImageUrls:[]},c=[{value:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",level:3},{value:"WWW(1989)",id:"www1989",level:3},{value:"CGI(1993)",id:"cgi1993",level:3},{value:"Servlet(1996)",id:"servlet1996",level:3},{value:"JSP(1999)",id:"jsp1999",level:3},{value:"MVC(2000)",id:"mvc2000",level:3},{value:"Spring Framework(2003)",id:"spring-framework2003",level:3},{value:"WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)",id:"webflux-\uc774\uc804-servlet-302009-312013",level:3},{value:"Spring WebFlux(2017)",id:"spring-webflux2017",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const r={a:"a",blockquote:"blockquote",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",...(0,i.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h3,{id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",children:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815"}),"\n",(0,t.jsxs)(r.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6d0\ub798 \ud68c\uace0\uc5d0 \uc791\uc131\ud558\ub824\uace0 \ud588\uc9c0\ub9cc, \uc815\ub9ac\ud558\ub2e4 \ubcf4\ub2c8 \uc870\uae08 \uae38\uc5b4\uc838\uc11c \ub530\ub85c \ubd84\ub9ac\ud588\ub2e4."]}),"\n",(0,t.jsx)(r.mermaid,{value:"graph LR\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking"}),"\n",(0,t.jsx)(r.h3,{id:"www1989",children:"WWW(1989)"}),"\n",(0,t.jsx)(r.p,{children:"\uc815\uc801 \ud398\uc774\uc9c0\ub97c \uc81c\uacf5\ud558\ub294 \uc6f9 \uc11c\ubc84\ub97c \uc2dc\uc791\uc73c\ub85c \ub3d9\uc801 \ud398\uc774\uc9c0\uac00 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 CGI\uac00 \ub4f1\uc7a5\ud588\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"cgi1993",children:"CGI(1993)"}),"\n",(0,t.jsx)(r.p,{children:"CGI\ub294 \ub3d9\uc801 \ucf58\ud150\uce20\ub97c \uc81c\uacf5\ud558\uae30 \uc704\ud55c \uaddc\uc57d\uc73c\ub85c, \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc774\uc6a9\ud574\uc11c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ucf1c \uc815\ubcf4\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ub9ce\uc740 \ubd80\ud558\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc774\ub7ec\ud55c \ub2e8\uc810\uc744 \uadf9\ubcf5\ud558\uae30 \uc704\ud574 \ub098\uc628 \uac83\uc774 Servlet\uc774\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"servlet1996",children:"Servlet(1996)"}),"\n",(0,t.jsxs)(r.p,{children:["Servlet\uc740 \uc6f9 \uc11c\ubc84\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uc790\ubc14 \ud504\ub85c\uadf8\ub7a8\uc73c\ub85c HTTP\ub97c \uc774\uc6a9\ud558\uc5ec \uc6f9 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc744 \uc218\uc2e0\ud558\uace0 \uc751\ub2f5\ud55c\ub2e4. CGI\uc640 \ub2e4\ub974\uac8c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\uac00 \uc544\ub2cc \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uc5ec \uc751\ub2f5\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc View \uc601\uc5ed\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uae30 \uc704\ud574 Servlet\uc758 \uc18c\uc2a4 \ucf54\ub4dc\ub97c \uc54c\uc544\uc57c \ud558\ub294 \ub4f1 \ubcf5\uc7a1\ub3c4\uac00 \ub108\ubb34 \ub192\uc558\ub2e4. \ub530\ub77c\uc11c \ud574\ub2f9 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 JSP\uac00 \ub4f1\uc7a5\ud588\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"jsp1999",children:"JSP(1999)"}),"\n",(0,t.jsxs)(r.p,{children:["JSP\ub294 HTML\uc5d0 \uc790\ubc14 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ub3d9\uc801 \uc6f9 \ud398\uc774\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\uc220\ub85c, \uc720\uc0ac\ud55c \uae30\uc220\ub85c\ub294 ASP, PHP\uac00 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","JSP\ub9cc \uc0ac\uc6a9\ud558\uc5ec \ud504\ub85c\uadf8\ub798\ubc0d\ud55c\ub2e4\uba74 Model 1, \uc544\ub798 \uad6c\uc131\ub3c4\uc640 \uac19\uc774 JSP\uac00 View \uc601\uc5ed\ub9cc \ub2f4\ub2f9\ud55c\ub2e4\uba74 Model 2\ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.mermaid,{value:"---\ntitle: JSP Model 2\n---\ngraph LR\n Client -- Request --\x3e Servlet <-- JDBC --\x3e Database\n\tServlet --\x3e Bean\n\tServlet --\x3e JSP\n\tBean <--\x3e JSP\n\tJSP -- Response --\x3e Client"}),"\n",(0,t.jsx)(r.h3,{id:"mvc2000",children:"MVC(2000)"}),"\n",(0,t.jsx)(r.p,{children:"\uc704 JSP\uc758 \uad6c\uc131\ub3c4\ub97c \ubcf4\uba74 \ud604\uc7ac MVC\uc640 \ub9e4\uc6b0 \uc720\uc0ac\ud55c\ub370, Govind Seshadri\ub77c\ub294 \uc0ac\ub78c\uc774 JSP Model 2\ub97c MVC \ud328\ud134\uc73c\ub85c \uacf5\uc2dd\ud654\ub97c \uc81c\uc548\ud588\ub2e4."}),"\n",(0,t.jsxs)(r.blockquote,{children:["\n",(0,t.jsxs)(r.p,{children:["I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern.",(0,t.jsx)(r.br,{}),"\n","Govind Seshadri"]}),"\n"]}),"\n",(0,t.jsxs)(r.p,{children:["\uc774\ub54c MVC \ud328\ud134\uc774 \ucc98\uc74c \ud0c4\uc0dd\ud55c \uac83\uc740 \uc544\ub2c8\uace0, \uc11c\ubc84 \uce21 \uad6c\ud604\uc774\ub77c\uace0 \ud558\ub294 \uac83\uc744 \ubcf4\ub2c8 MVC\uac00 \ucc98\uc74c \ub4f1\uc7a5\ud55c \uac74 \uc544\ub2cc \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html",children:"\ud574\ub2f9 \ubb38\uc11c"}),"\ub97c \ubcf4\uba74 MVC\ub77c\ub294 \uc6a9\uc5b4\uc758 \ub4f1\uc7a5\uc740 1978\ub144\uc5d0 \ub4f1\uc7a5\ud55c \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"spring-framework2003",children:"Spring Framework(2003)"}),"\n",(0,t.jsxs)(r.p,{children:["Spring\uc740 \ubcf5\uc7a1\ud588\ub358 J2EE\uc744 \ub300\uccb4\ud558\uae30 \uc704\ud574 2003\ub144\uc5d0 \ub4f1\uc7a5\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","J2EE\ub294 \uc6f9 \uae30\ubc18\uc758 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\uae30 \uc704\ud55c \ud50c\ub7ab\ud3fc\uc73c\ub85c \uc704\uc5d0\uc11c \uc124\uba85\ud55c Servlet, JSP, EJB \ub4f1\uc758 \uae30\uc220\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \uc774\uc911 EJB\ub77c\ub294 \uae30\uc220\uc774 J2EE\uc758 \ud575\uc2ec \uae30\uc220\uc774\uc5c8\ub294\ub370, \ud574\ub2f9 \uae30\uc220\uc774 \ub9e4\uc6b0 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub9ce\uc558\ub2e4\uace0 \ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","2002\ub144\uc5d0 Rod Johnson\uc774 EJB\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 J2EE \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc800\uc220\ud55c ",(0,t.jsx)(r.code,{children:"Expert One-to-One J2EE Development"}),"\ub77c\ub294 \ucc45\uc744 \ubc1c\ud589\ud588\uace0, \ucd9c\uac04 \ud6c4 Juergen Hoeller, Yann Caroff\uac00 Rod Johnson\uc5d0\uac8c \uc624\ud508\uc18c\uc2a4 \uc81c\uc548\uc744 \ud558\uc5ec \uc2a4\ud504\ub9c1\uc774 \ud0c4\uc0dd\ud588\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\uc2a4\ud504\ub9c1\uc740 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc11c\ube44\uc2a4 \uae30\ub2a5\uc744 POJO\uc5d0 \uc81c\uacf5\ud558\uba70, \uc774 \ub355\ubd84\uc5d0 \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"webflux-\uc774\uc804-servlet-302009-312013",children:"WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)"}),"\n",(0,t.jsxs)(r.p,{children:["Tomcat\uc758 NIO \ub3d9\uc791 \ubc29\uc2dd\uc744 \ubcf4\uba74 Poller\uac00 \uc18c\ucf13 \ucee4\ub125\uc158\uc744 \ub4e4\uace0 \uc788\ub2e4\uac00 \ucc98\ub9ac\uac00 \uac00\ub2a5\ud560 \ub54c \uc2a4\ub808\ub4dc\ub97c \ud560\ub2f9\ud558\ub294 \uc2dd\uc73c\ub85c \ucc98\ub9ac\ub97c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ud560\ub2f9 \ud6c4 Servlet\uacfc \ud1b5\uc2e0\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \uc694\uccad\uc774 \ub05d\ub0a0 \ub54c\uae4c\uc9c0 \uc2a4\ub808\ub4dc\ub97c \uc810\uc720\ud558\uace0 \uc788\uc5c8\uace0, \uc2a4\ub808\ub4dc \uc810\uc720\ub85c \uc778\ud574 \uc694\uccad\uc774 max thread\uc5d0 \ub3c4\ub2ec\ud558\uba74 \uc694\uccad\uc744 \ucc98\ub9ac\ud560 \uc218 \uc5c6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\uc11c \ube44\ub3d9\uae30 \ubc29\uc2dd\uc758 Servlet\uc774 Servlet 3.0\uc5d0 \ub4f1\uc7a5\ud588\ub2e4. \ud558\uc9c0\ub9cc \uc804\ud1b5\uc801\uc778 I/O \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \ub3d9\uc791\ud588\ub2e4. Servlet 3.1\uc5d0\uc11c \ub17c\ube14\ub85c\ud0b9 I/O\uac00 \ucd94\uac00\ub418\uc5c8\uc9c0\ub9cc, \ub9ce\uc774 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc558\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"spring-webflux2017",children:"Spring WebFlux(2017)"}),"\n",(0,t.jsxs)(r.p,{children:["\uc801\uc740 \uc218\uc758 \uc2a4\ub808\ub4dc\ub85c \ub3d9\uc2dc\uc131\uc744 \ucc98\ub9ac\ud558\uace0, \uc801\uc740 \ub9ac\uc18c\uc2a4\ub85c \ud655\uc7a5\uc774 \uac00\ub2a5\ud55c \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd\uc758 \uc6f9 \uae30\uc220\uc774 \ud544\uc694\ud588\uace0, \uae30\uc874\uc758 Servlet\uc758 \uacbd\uc6b0 \ube44\ub3d9\uae30\ub97c \uc9c0\uc6d0\ud55c\ub2e4 \ud574\ub3c4 \ub3d9\uae30\uc2dd API\ub4e4\uc774 \ub9ce\uc774 \ub0a8\uc544\uc788\uc5c8\uae30 \ub54c\ubb38\uc5d0 \uc774\ub7ec\ud55c Servlet\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294 \uae30\uc220\uc774 \ud544\uc694\ud588\ub2e4. \ub610\ud55c \uae30\uc874\uc5d0 Netty\uc640 \uac19\uc774 \ube44\ub3d9\uae30, \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd \uc11c\ubc84\ub85c \uc790\ub9ac\ub97c \uc798 \uc7a1\uc740 \uc11c\ubc84\ub97c \uc704\ud574 Spring WebFlux\uac00 \ub4f1\uc7a5\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucd94\uac00\ub85c \ub370\uc774\ud130 \uc811\uadfc\uc744 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 JDBC\uc758 \uacbd\uc6b0 Blocking API\ub77c, Spring Webflux\uc5d0\uc11c\ub294 R2DBC\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,t.jsxs)(r.p,{children:["\ud574\ub2f9 \uc815\ub9ac \ub0b4\uc6a9\uc758 \uacbd\uc6b0 Async, Non Blocking \uad00\ub828\ub41c \ub0b4\uc6a9\uc744 \uae4a\uac8c \uacf5\ubd80\ud55c \uc801\uc774 \uc5c6\uc5b4\uc11c \uc815\ud655\ud558\uc9c0 \uc54a\uc744 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\ub3c4 \uae30\uc220\uc758 \ub4f1\uc7a5 \ubc30\uacbd\uc774\ub098 \uacfc\uc815\uc744 \uc54c\uace0 \uc788\ub2e4\uba74 \uc870\uae08 \ub354 \uae4a\uc774 \uc788\ub294 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(r.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815, \uad6c\uad6c \uac15\uc758",(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://httpd.apache.org/docs/trunk/en/howto/cgi.html",children:"Dynamic Content with CGI, Apache Tutorial"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://docs.spring.io/spring-framework/reference/overview.html#overview-history",children:"History of Spring and the Spring Framework, Spring"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.infoworld.com/article/2076557/understanding-javaserver-pages-model-2-architecture.html",children:"Understanding JavaServer Pages Model 2 architecture, Govind Seshadri"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html",children:"MVC, XEROX PARC"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.amazon.com/Expert-One-One-Development-without/dp/0764558315",children:"Expert One-to-One J2EE Development, Rod Johnson"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://techblog.woowahan.com/2667/",children:"\ubc30\ub2ec\uc758\ubbfc\uc871 \ucd5c\uc804\ubc29 \uc2dc\uc2a4\ud15c! \u2018\uac00\uac8c\ub178\ucd9c \uc2dc\uc2a4\ud15c\u2019\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4, \ubc30\ub2ec\uc758\ubbfc\uc871"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.infoworld.com/article/2077995/java-concurrency-asynchronous-processing-support-in-servlet-3-0.html",children:"Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu"}),"\n",(0,t.jsx)(r.a,{href:"https://docs.spring.io/spring-framework/reference/web/webflux/new-framework.html",children:"WebFlux Overview, Spring"}),"\n",(0,t.jsx)(r.a,{href:"https://d2.naver.com/helloworld/6080222",children:"Spring WebFlux\uc640 Armeria\ub97c \uc774\uc6a9\ud558\uc5ec Microservice\uc5d0 \ud544\uc694\ud55c Reactive + RPC \ub3d9\uc2dc\uc5d0 \uc7a1\uae30, Naver D2"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://tweety1121.tistory.com/entry/Spring-WebFlux-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C",children:"Spring WebFlux\ub780 \ubb34\uc5c7\uc77c\uae4c"})]})]})}function d(e={}){const{wrapper:r}={...(0,i.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>c});var t=n(67294);function i(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function l(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(i[n]=e[n]);return i}(e,r);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var a=t.createContext({}),c=function(e){var r=t.useContext(a),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},d=t.forwardRef((function(e,r){var n=e.components,i=e.mdxType,l=e.originalType,a=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),h=c(n),u=i,x=h["".concat(a,".").concat(u)]||h[u]||p[u]||l;return n?t.createElement(x,o(o({ref:r},d),{},{components:n})):t.createElement(x,o({ref:r},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8548],{40911:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>a,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=n(85893),i=n(3905);const l={title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",slug:"web-application-evolution",tags:["web application"]},o=void 0,s={permalink:"/web-application-evolution",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",source:"@site/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",description:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",date:"2023-09-30T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 30\uc77c",tags:[{label:"web application",permalink:"/tags/web-application"}],readingTime:7.5,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",slug:"web-application-evolution",tags:["web application"]},unlisted:!1,prevItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"},nextItem:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",permalink:"/spring-test-isolation"}},a={authorsImageUrls:[]},c=[{value:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",level:3},{value:"WWW(1989)",id:"www1989",level:3},{value:"CGI(1993)",id:"cgi1993",level:3},{value:"Servlet(1996)",id:"servlet1996",level:3},{value:"JSP(1999)",id:"jsp1999",level:3},{value:"MVC(2000)",id:"mvc2000",level:3},{value:"Spring Framework(2003)",id:"spring-framework2003",level:3},{value:"WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)",id:"webflux-\uc774\uc804-servlet-302009-312013",level:3},{value:"Spring WebFlux(2017)",id:"spring-webflux2017",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const r={a:"a",blockquote:"blockquote",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",...(0,i.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h3,{id:"\uc6f9-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ubc1c\uc804-\uacfc\uc815",children:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815"}),"\n",(0,t.jsxs)(r.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6d0\ub798 \ud68c\uace0\uc5d0 \uc791\uc131\ud558\ub824\uace0 \ud588\uc9c0\ub9cc, \uc815\ub9ac\ud558\ub2e4 \ubcf4\ub2c8 \uc870\uae08 \uae38\uc5b4\uc838\uc11c \ub530\ub85c \ubd84\ub9ac\ud588\ub2e4."]}),"\n",(0,t.jsx)(r.mermaid,{value:"graph LR\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking"}),"\n",(0,t.jsx)(r.h3,{id:"www1989",children:"WWW(1989)"}),"\n",(0,t.jsx)(r.p,{children:"\uc815\uc801 \ud398\uc774\uc9c0\ub97c \uc81c\uacf5\ud558\ub294 \uc6f9 \uc11c\ubc84\ub97c \uc2dc\uc791\uc73c\ub85c \ub3d9\uc801 \ud398\uc774\uc9c0\uac00 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 CGI\uac00 \ub4f1\uc7a5\ud588\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"cgi1993",children:"CGI(1993)"}),"\n",(0,t.jsx)(r.p,{children:"CGI\ub294 \ub3d9\uc801 \ucf58\ud150\uce20\ub97c \uc81c\uacf5\ud558\uae30 \uc704\ud55c \uaddc\uc57d\uc73c\ub85c, \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc774\uc6a9\ud574\uc11c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ucf1c \uc815\ubcf4\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ub9ce\uc740 \ubd80\ud558\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc774\ub7ec\ud55c \ub2e8\uc810\uc744 \uadf9\ubcf5\ud558\uae30 \uc704\ud574 \ub098\uc628 \uac83\uc774 Servlet\uc774\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"servlet1996",children:"Servlet(1996)"}),"\n",(0,t.jsxs)(r.p,{children:["Servlet\uc740 \uc6f9 \uc11c\ubc84\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uc790\ubc14 \ud504\ub85c\uadf8\ub7a8\uc73c\ub85c HTTP\ub97c \uc774\uc6a9\ud558\uc5ec \uc6f9 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc744 \uc218\uc2e0\ud558\uace0 \uc751\ub2f5\ud55c\ub2e4. CGI\uc640 \ub2e4\ub974\uac8c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\uac00 \uc544\ub2cc \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uc5ec \uc751\ub2f5\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc View \uc601\uc5ed\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uae30 \uc704\ud574 Servlet\uc758 \uc18c\uc2a4 \ucf54\ub4dc\ub97c \uc54c\uc544\uc57c \ud558\ub294 \ub4f1 \ubcf5\uc7a1\ub3c4\uac00 \ub108\ubb34 \ub192\uc558\ub2e4. \ub530\ub77c\uc11c \ud574\ub2f9 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 JSP\uac00 \ub4f1\uc7a5\ud588\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"jsp1999",children:"JSP(1999)"}),"\n",(0,t.jsxs)(r.p,{children:["JSP\ub294 HTML\uc5d0 \uc790\ubc14 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ub3d9\uc801 \uc6f9 \ud398\uc774\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\uc220\ub85c, \uc720\uc0ac\ud55c \uae30\uc220\ub85c\ub294 ASP, PHP\uac00 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","JSP\ub9cc \uc0ac\uc6a9\ud558\uc5ec \ud504\ub85c\uadf8\ub798\ubc0d\ud55c\ub2e4\uba74 Model 1, \uc544\ub798 \uad6c\uc131\ub3c4\uc640 \uac19\uc774 JSP\uac00 View \uc601\uc5ed\ub9cc \ub2f4\ub2f9\ud55c\ub2e4\uba74 Model 2\ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.mermaid,{value:"---\ntitle: JSP Model 2\n---\ngraph LR\n Client -- Request --\x3e Servlet <-- JDBC --\x3e Database\n\tServlet --\x3e Bean\n\tServlet --\x3e JSP\n\tBean <--\x3e JSP\n\tJSP -- Response --\x3e Client"}),"\n",(0,t.jsx)(r.h3,{id:"mvc2000",children:"MVC(2000)"}),"\n",(0,t.jsx)(r.p,{children:"\uc704 JSP\uc758 \uad6c\uc131\ub3c4\ub97c \ubcf4\uba74 \ud604\uc7ac MVC\uc640 \ub9e4\uc6b0 \uc720\uc0ac\ud55c\ub370, Govind Seshadri\ub77c\ub294 \uc0ac\ub78c\uc774 JSP Model 2\ub97c MVC \ud328\ud134\uc73c\ub85c \uacf5\uc2dd\ud654\ub97c \uc81c\uc548\ud588\ub2e4."}),"\n",(0,t.jsxs)(r.blockquote,{children:["\n",(0,t.jsxs)(r.p,{children:["I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern.",(0,t.jsx)(r.br,{}),"\n","Govind Seshadri"]}),"\n"]}),"\n",(0,t.jsxs)(r.p,{children:["\uc774\ub54c MVC \ud328\ud134\uc774 \ucc98\uc74c \ud0c4\uc0dd\ud55c \uac83\uc740 \uc544\ub2c8\uace0, \uc11c\ubc84 \uce21 \uad6c\ud604\uc774\ub77c\uace0 \ud558\ub294 \uac83\uc744 \ubcf4\ub2c8 MVC\uac00 \ucc98\uc74c \ub4f1\uc7a5\ud55c \uac74 \uc544\ub2cc \uac83 \uac19\ub2e4.",(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html",children:"\ud574\ub2f9 \ubb38\uc11c"}),"\ub97c \ubcf4\uba74 MVC\ub77c\ub294 \uc6a9\uc5b4\uc758 \ub4f1\uc7a5\uc740 1978\ub144\uc5d0 \ub4f1\uc7a5\ud55c \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"spring-framework2003",children:"Spring Framework(2003)"}),"\n",(0,t.jsxs)(r.p,{children:["Spring\uc740 \ubcf5\uc7a1\ud588\ub358 J2EE\uc744 \ub300\uccb4\ud558\uae30 \uc704\ud574 2003\ub144\uc5d0 \ub4f1\uc7a5\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","J2EE\ub294 \uc6f9 \uae30\ubc18\uc758 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\uae30 \uc704\ud55c \ud50c\ub7ab\ud3fc\uc73c\ub85c \uc704\uc5d0\uc11c \uc124\uba85\ud55c Servlet, JSP, EJB \ub4f1\uc758 \uae30\uc220\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud558\uc9c0\ub9cc \uc774\uc911 EJB\ub77c\ub294 \uae30\uc220\uc774 J2EE\uc758 \ud575\uc2ec \uae30\uc220\uc774\uc5c8\ub294\ub370, \ud574\ub2f9 \uae30\uc220\uc774 \ub9e4\uc6b0 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub9ce\uc558\ub2e4\uace0 \ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","2002\ub144\uc5d0 Rod Johnson\uc774 EJB\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 J2EE \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc800\uc220\ud55c ",(0,t.jsx)(r.code,{children:"Expert One-to-One J2EE Development"}),"\ub77c\ub294 \ucc45\uc744 \ubc1c\ud589\ud588\uace0, \ucd9c\uac04 \ud6c4 Juergen Hoeller, Yann Caroff\uac00 Rod Johnson\uc5d0\uac8c \uc624\ud508\uc18c\uc2a4 \uc81c\uc548\uc744 \ud558\uc5ec \uc2a4\ud504\ub9c1\uc774 \ud0c4\uc0dd\ud588\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:"\uc2a4\ud504\ub9c1\uc740 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc11c\ube44\uc2a4 \uae30\ub2a5\uc744 POJO\uc5d0 \uc81c\uacf5\ud558\uba70, \uc774 \ub355\ubd84\uc5d0 \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(r.h3,{id:"webflux-\uc774\uc804-servlet-302009-312013",children:"WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)"}),"\n",(0,t.jsxs)(r.p,{children:["Tomcat\uc758 NIO \ub3d9\uc791 \ubc29\uc2dd\uc744 \ubcf4\uba74 Poller\uac00 \uc18c\ucf13 \ucee4\ub125\uc158\uc744 \ub4e4\uace0 \uc788\ub2e4\uac00 \ucc98\ub9ac\uac00 \uac00\ub2a5\ud560 \ub54c \uc2a4\ub808\ub4dc\ub97c \ud560\ub2f9\ud558\ub294 \uc2dd\uc73c\ub85c \ucc98\ub9ac\ub97c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ud560\ub2f9 \ud6c4 Servlet\uacfc \ud1b5\uc2e0\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \uc694\uccad\uc774 \ub05d\ub0a0 \ub54c\uae4c\uc9c0 \uc2a4\ub808\ub4dc\ub97c \uc810\uc720\ud558\uace0 \uc788\uc5c8\uace0, \uc2a4\ub808\ub4dc \uc810\uc720\ub85c \uc778\ud574 \uc694\uccad\uc774 max thread\uc5d0 \ub3c4\ub2ec\ud558\uba74 \uc694\uccad\uc744 \ucc98\ub9ac\ud560 \uc218 \uc5c6\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\uc11c \ube44\ub3d9\uae30 \ubc29\uc2dd\uc758 Servlet\uc774 Servlet 3.0\uc5d0 \ub4f1\uc7a5\ud588\ub2e4. \ud558\uc9c0\ub9cc \uc804\ud1b5\uc801\uc778 I/O \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \ub3d9\uc791\ud588\ub2e4. Servlet 3.1\uc5d0\uc11c \ub17c\ube14\ub85c\ud0b9 I/O\uac00 \ucd94\uac00\ub418\uc5c8\uc9c0\ub9cc, \ub9ce\uc774 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc558\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"spring-webflux2017",children:"Spring WebFlux(2017)"}),"\n",(0,t.jsxs)(r.p,{children:["\uc801\uc740 \uc218\uc758 \uc2a4\ub808\ub4dc\ub85c \ub3d9\uc2dc\uc131\uc744 \ucc98\ub9ac\ud558\uace0, \uc801\uc740 \ub9ac\uc18c\uc2a4\ub85c \ud655\uc7a5\uc774 \uac00\ub2a5\ud55c \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd\uc758 \uc6f9 \uae30\uc220\uc774 \ud544\uc694\ud588\uace0, \uae30\uc874\uc758 Servlet\uc758 \uacbd\uc6b0 \ube44\ub3d9\uae30\ub97c \uc9c0\uc6d0\ud55c\ub2e4 \ud574\ub3c4 \ub3d9\uae30\uc2dd API\ub4e4\uc774 \ub9ce\uc774 \ub0a8\uc544\uc788\uc5c8\uae30 \ub54c\ubb38\uc5d0 \uc774\ub7ec\ud55c Servlet\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294 \uae30\uc220\uc774 \ud544\uc694\ud588\ub2e4. \ub610\ud55c \uae30\uc874\uc5d0 Netty\uc640 \uac19\uc774 \ube44\ub3d9\uae30, \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd \uc11c\ubc84\ub85c \uc790\ub9ac\ub97c \uc798 \uc7a1\uc740 \uc11c\ubc84\ub97c \uc704\ud574 Spring WebFlux\uac00 \ub4f1\uc7a5\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ucd94\uac00\ub85c \ub370\uc774\ud130 \uc811\uadfc\uc744 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 JDBC\uc758 \uacbd\uc6b0 Blocking API\ub77c, Spring Webflux\uc5d0\uc11c\ub294 R2DBC\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ub9c8\uce58\uba70",children:"\ub9c8\uce58\uba70"}),"\n",(0,t.jsxs)(r.p,{children:["\ud574\ub2f9 \uc815\ub9ac \ub0b4\uc6a9\uc758 \uacbd\uc6b0 Async, Non Blocking \uad00\ub828\ub41c \ub0b4\uc6a9\uc744 \uae4a\uac8c \uacf5\ubd80\ud55c \uc801\uc774 \uc5c6\uc5b4\uc11c \uc815\ud655\ud558\uc9c0 \uc54a\uc744 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\ub3c4 \uae30\uc220\uc758 \ub4f1\uc7a5 \ubc30\uacbd\uc774\ub098 \uacfc\uc815\uc744 \uc54c\uace0 \uc788\ub2e4\uba74 \uc870\uae08 \ub354 \uae4a\uc774 \uc788\ub294 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(r.p,{children:["\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815, \uad6c\uad6c \uac15\uc758",(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://httpd.apache.org/docs/trunk/en/howto/cgi.html",children:"Dynamic Content with CGI, Apache Tutorial"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://docs.spring.io/spring-framework/reference/overview.html#overview-history",children:"History of Spring and the Spring Framework, Spring"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.infoworld.com/article/2076557/understanding-javaserver-pages-model-2-architecture.html",children:"Understanding JavaServer Pages Model 2 architecture, Govind Seshadri"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html",children:"MVC, XEROX PARC"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.amazon.com/Expert-One-One-Development-without/dp/0764558315",children:"Expert One-to-One J2EE Development, Rod Johnson"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://techblog.woowahan.com/2667/",children:"\ubc30\ub2ec\uc758\ubbfc\uc871 \ucd5c\uc804\ubc29 \uc2dc\uc2a4\ud15c! \u2018\uac00\uac8c\ub178\ucd9c \uc2dc\uc2a4\ud15c\u2019\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4, \ubc30\ub2ec\uc758\ubbfc\uc871"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://www.infoworld.com/article/2077995/java-concurrency-asynchronous-processing-support-in-servlet-3-0.html",children:"Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu"}),"\n",(0,t.jsx)(r.a,{href:"https://docs.spring.io/spring-framework/reference/web/webflux/new-framework.html",children:"WebFlux Overview, Spring"}),"\n",(0,t.jsx)(r.a,{href:"https://d2.naver.com/helloworld/6080222",children:"Spring WebFlux\uc640 Armeria\ub97c \uc774\uc6a9\ud558\uc5ec Microservice\uc5d0 \ud544\uc694\ud55c Reactive + RPC \ub3d9\uc2dc\uc5d0 \uc7a1\uae30, Naver D2"}),(0,t.jsx)(r.br,{}),"\n",(0,t.jsx)(r.a,{href:"https://tweety1121.tistory.com/entry/Spring-WebFlux-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C",children:"Spring WebFlux\ub780 \ubb34\uc5c7\uc77c\uae4c"})]})]})}function d(e={}){const{wrapper:r}={...(0,i.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>c});var t=n(67294);function i(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function l(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(i[n]=e[n]);return i}(e,r);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var a=t.createContext({}),c=function(e){var r=t.useContext(a),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},d=t.forwardRef((function(e,r){var n=e.components,i=e.mdxType,l=e.originalType,a=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),h=c(n),u=i,x=h["".concat(a,".").concat(u)]||h[u]||p[u]||l;return n?t.createElement(x,o(o({ref:r},d),{},{components:n})):t.createElement(x,o({ref:r},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/ad3b7b62.f8707eac.js b/assets/js/ad3b7b62.16148c2a.js similarity index 97% rename from assets/js/ad3b7b62.f8707eac.js rename to assets/js/ad3b7b62.16148c2a.js index f6c42c2ef..d87689319 100644 --- a/assets/js/ad3b7b62.f8707eac.js +++ b/assets/js/ad3b7b62.16148c2a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[26],{76556:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var n=t(85893),s=t(3905);const o={title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",slug:"shopping-cart-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/shopping-cart-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-shopping-cart/pull/244",date:"2023-05-12T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 12\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.845,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",slug:"shopping-cart-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",permalink:"/accidental-duplication"},nextItem:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",permalink:"/web-racing-car-retrospective"}},a={authorsImageUrls:[]},l=[{value:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158",id:"\uc6f9-\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",h3:"h3",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,n.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-shopping-cart/pull/244",children:"https://github.com/woowacourse/jwp-shopping-cart/pull/244"}),(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-shopping-cart/pull/300",children:"https://github.com/woowacourse/jwp-shopping-cart/pull/300"})]})}),"\n",(0,n.jsx)(r.h3,{id:"\uc6f9-\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158",children:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc740 \ube14\ub799\ucea3\uc774\ub791 \uc9c4\ud589\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc694\uad6c\uc0ac\ud56d\uc774 \uc5c4\uccad \ubcf5\uc7a1\ud55c \ubbf8\uc158\uc740 \uc544\ub2c8\uc5c8\uace0, \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\ubcf8\uc801\uc778 CRUD\ub97c \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4\uc5d0\uc11c\ub294 Basic \uc778\uc99d\uc744 \ud1b5\ud574 \uc790\uc2e0\uc758 \uc7a5\ubc14\uad6c\ub2c8\uc5d0\ub9cc \uc0c1\ud488\uc744 \ub2f4\uace0, \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \uad6c\ud604\ud558\ub294 \uc694\uad6c\uc0ac\ud56d\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","Interceptor\ub098 Argument Resolver\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\uac00 \ub192\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc870\uae08 \ub354 \uc54c\uc544\uac04 \ub290\ub08c\uc774\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0 \uc2a4\ud504\ub9c1 \uc0ac\uc6a9\ud560 \ub54c\ub294 \uc544\ubb34 \uc0dd\uac01 \uc5c6\uc774 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub294\ub370, \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \ub54c \uadfc\uac70\uac00 \uc0dd\uae30\uace0 \uc788\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"DTO \uc6b0\ubc1c\uc801 \uc911\ubcf5"})}),"\n",(0,n.jsx)(r.p,{children:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.img,{alt:"dto1",src:t(33946).Z+"",width:"2028",height:"704"})}),"\n",(0,n.jsxs)(r.p,{children:["\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d \ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0 \uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\uc744 \ud588\uace0, \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec \uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4."]}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsx)(r.li,{children:"\uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,n.jsx)(r.li,{children:"\uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4."}),"\n"]}),"\n",(0,n.jsxs)(r.p,{children:["\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131 \uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \ub9ac\ubdf0\uc5b4 \uc6e8\uc9c0\uac00 \uc544\ub798\uc640 \uac19\uc774 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\uace0 \uc54c\ub824\uc8fc\uc168\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.img,{alt:"dto2",src:t(15907).Z+"",width:"1508",height:"896"})}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"Interceptor\uc5d0\uc11c \uc778\uc99d\ud55c \uac12 \uc7ac\uc0ac\uc6a9"})}),"\n",(0,n.jsxs)(r.p,{children:["\uc0ac\uc2e4 \uc870\ud68c\ub97c \ub450 \ubc88 \ud558\uae30 \uc2eb\uc5b4\uc11c \ub2e4\uc591\ud55c \ubc29\ubc95\uc744 \uc0dd\uac01\ud588\uc5c8\ub294\ub370 \uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 ThreadLocal\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc77c\ub2e8 Tomcat\uc740 \uc694\uccad\ub9c8\ub2e4 \ub2e4\ub978 \uc2a4\ub808\ub4dc\ub97c \uc0ac\uc6a9\ud558\uace0, Interceptor\uc5d0\uc11c \uc870\ud68c\ud574\uc11c \ub9cc\ub4e0 Credential\uc744 ThreadLocal\uc5d0 \ub123\uc5b4\ub450\uc5c8\ub2e4\uac00 ArgumentResolver\uc5d0\uc11c \uaebc\ub0b8 \ub2e4\uc74c ThreadLocal\uc744 clear \ud558\uba74 \ubb38\uc81c\uac00 \uc5c6\uc744 \uac70\ub77c \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub9ac\ubdf0\uc5b4\uc778 \uc6e8\uc9c0\uc5d0\uac8c\ub3c4 \uc5b4\ub5a4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560\uc9c0 \uad81\uae08\uc99d\uc744 \uc791\uc131\ud588\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc6e8\uc9c0\ub294 email\uc5d0 index\ub97c \uac78\uc5b4\ub450\uace0 dao \uc7ac\uc870\ud68c\ub97c \uc0ac\uc6a9\ud560 \uac83\uc774\ub77c\uace0 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc7ac\uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 db\uc5d0 \uc778\ub371\uc2a4\ub97c \uac78 \uc0dd\uac01\uc740 \ud558\uc9c0 \ubabb\ud588\ub294\ub370, \uc81c\uc77c \uc9c1\uad00\uc801\uc774\uace0 \uc88b\uc740 \ubc29\ubc95\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"\uae30\ub85d"})}),"\n",(0,n.jsxs)(r.p,{children:["\ube14\ub799\ucea3\uc740 \uae30\ub85d\uc744 \uad49\uc7a5\ud788 \uc798 \ud558\ub294 \ud06c\ub8e8\uc600\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub178\uc158\uc5d0 \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ud588\ub358 \ub0b4\uc6a9 + \uace0\ubbfc\ud588\ub358 \ubd80\ubd84 + \ud68c\uace0\ub97c \uaf3c\uaf3c\ud558\uac8c \uae30\ub85d\ud574\uc11c \uacf5\uc720\ud574 \uc8fc\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ucd94\uac00\uc801\uc73c\ub85c \uc774\ubaa8\uc9c0\ub97c \uc801\uadf9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uc5ec \ub354\uc6b1 \uc88b\uc558\ub2e4!"]}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"\uc758\uacac \uc77c\uce58\uc2dc\ud0a4\uae30"})}),"\n",(0,n.jsxs)(r.p,{children:["\ud398\uc5b4 \uc2dc\uac04\uc740 \ud55c\uc815\ub418\uc5b4 \uc788\uace0, \uae30\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574\uc57c \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \uc801\ub2f9\ud788 \ud0c0\ud611\uc744 \ubd10\uc11c \uc758\uacac\uc744 \ube60\ub974\uac8c \uc218\uc6a9\ud574 \ub370\ub4dc\ub77c\uc778\uc744 \ub9de\ucd94\ub294 \uac83\ub3c4 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ube14\ub799\ucea3\uc740 \ub0b4 \uc758\uacac\uc744 \uc798 \ub4e4\uc5b4\uc92c\uace0, \ub355\ubd84\uc5d0 \ub9c9\ud788\ub294 \ubd80\ubd84 \uc5c6\uc774 \ube60\ub974\uac8c \ubbf8\uc158\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ube68\ub9ac \uce5c\ud574\uc84c\uace0, \uc758\uc0ac\uc18c\ud1b5\uc774 \uc798 \ub3fc\uc11c \uc7ac\ubc0c\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uc5c8\ub2e4!"})]})}function h(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},h=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,o=e.originalType,a=e.parentName,h=i(e,["components","mdxType","originalType","parentName"]),d=l(t),u=s,j=d["".concat(a,".").concat(u)]||d[u]||p[u]||o;return t?n.createElement(j,c(c({ref:r},h),{},{components:t})):n.createElement(j,c({ref:r},h))}));h.displayName="MDXCreateElement"},33946:(e,r,t)=>{t.d(r,{Z:()=>n});const n=t.p+"assets/images/dto1-ccd4f91674b224578f2b295b3fccaf2c.png"},15907:(e,r,t)=>{t.d(r,{Z:()=>n});const n=t.p+"assets/images/dto2-15b381e0a024487f54608d438e5385f9.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[26],{76556:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var n=t(85893),s=t(3905);const o={title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",slug:"shopping-cart-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/shopping-cart-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-shopping-cart/pull/244",date:"2023-05-12T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 12\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.845,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",slug:"shopping-cart-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",permalink:"/web-racing-car-retrospective"},nextItem:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",permalink:"/accidental-duplication"}},a={authorsImageUrls:[]},l=[{value:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158",id:"\uc6f9-\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",h3:"h3",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,n.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-shopping-cart/pull/244",children:"https://github.com/woowacourse/jwp-shopping-cart/pull/244"}),(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,n.jsx)(r.a,{href:"https://github.com/woowacourse/jwp-shopping-cart/pull/300",children:"https://github.com/woowacourse/jwp-shopping-cart/pull/300"})]})}),"\n",(0,n.jsx)(r.h3,{id:"\uc6f9-\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158",children:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc740 \ube14\ub799\ucea3\uc774\ub791 \uc9c4\ud589\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc694\uad6c\uc0ac\ud56d\uc774 \uc5c4\uccad \ubcf5\uc7a1\ud55c \ubbf8\uc158\uc740 \uc544\ub2c8\uc5c8\uace0, \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\ubcf8\uc801\uc778 CRUD\ub97c \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","2\ub2e8\uacc4\uc5d0\uc11c\ub294 Basic \uc778\uc99d\uc744 \ud1b5\ud574 \uc790\uc2e0\uc758 \uc7a5\ubc14\uad6c\ub2c8\uc5d0\ub9cc \uc0c1\ud488\uc744 \ub2f4\uace0, \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \uad6c\ud604\ud558\ub294 \uc694\uad6c\uc0ac\ud56d\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","Interceptor\ub098 Argument Resolver\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\uac00 \ub192\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc870\uae08 \ub354 \uc54c\uc544\uac04 \ub290\ub08c\uc774\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0 \uc2a4\ud504\ub9c1 \uc0ac\uc6a9\ud560 \ub54c\ub294 \uc544\ubb34 \uc0dd\uac01 \uc5c6\uc774 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub294\ub370, \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \ub54c \uadfc\uac70\uac00 \uc0dd\uae30\uace0 \uc788\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"DTO \uc6b0\ubc1c\uc801 \uc911\ubcf5"})}),"\n",(0,n.jsx)(r.p,{children:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4."}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.img,{alt:"dto1",src:t(33946).Z+"",width:"2028",height:"704"})}),"\n",(0,n.jsxs)(r.p,{children:["\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d \ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0 \uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\uc744 \ud588\uace0, \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec \uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4."]}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsx)(r.li,{children:"\uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,n.jsx)(r.li,{children:"\uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4."}),"\n"]}),"\n",(0,n.jsxs)(r.p,{children:["\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131 \uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \ub9ac\ubdf0\uc5b4 \uc6e8\uc9c0\uac00 \uc544\ub798\uc640 \uac19\uc774 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\uace0 \uc54c\ub824\uc8fc\uc168\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.img,{alt:"dto2",src:t(15907).Z+"",width:"1508",height:"896"})}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"Interceptor\uc5d0\uc11c \uc778\uc99d\ud55c \uac12 \uc7ac\uc0ac\uc6a9"})}),"\n",(0,n.jsxs)(r.p,{children:["\uc0ac\uc2e4 \uc870\ud68c\ub97c \ub450 \ubc88 \ud558\uae30 \uc2eb\uc5b4\uc11c \ub2e4\uc591\ud55c \ubc29\ubc95\uc744 \uc0dd\uac01\ud588\uc5c8\ub294\ub370 \uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 ThreadLocal\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc77c\ub2e8 Tomcat\uc740 \uc694\uccad\ub9c8\ub2e4 \ub2e4\ub978 \uc2a4\ub808\ub4dc\ub97c \uc0ac\uc6a9\ud558\uace0, Interceptor\uc5d0\uc11c \uc870\ud68c\ud574\uc11c \ub9cc\ub4e0 Credential\uc744 ThreadLocal\uc5d0 \ub123\uc5b4\ub450\uc5c8\ub2e4\uac00 ArgumentResolver\uc5d0\uc11c \uaebc\ub0b8 \ub2e4\uc74c ThreadLocal\uc744 clear \ud558\uba74 \ubb38\uc81c\uac00 \uc5c6\uc744 \uac70\ub77c \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ub9ac\ubdf0\uc5b4\uc778 \uc6e8\uc9c0\uc5d0\uac8c\ub3c4 \uc5b4\ub5a4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560\uc9c0 \uad81\uae08\uc99d\uc744 \uc791\uc131\ud588\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc6e8\uc9c0\ub294 email\uc5d0 index\ub97c \uac78\uc5b4\ub450\uace0 dao \uc7ac\uc870\ud68c\ub97c \uc0ac\uc6a9\ud560 \uac83\uc774\ub77c\uace0 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc7ac\uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 db\uc5d0 \uc778\ub371\uc2a4\ub97c \uac78 \uc0dd\uac01\uc740 \ud558\uc9c0 \ubabb\ud588\ub294\ub370, \uc81c\uc77c \uc9c1\uad00\uc801\uc774\uace0 \uc88b\uc740 \ubc29\ubc95\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"\uae30\ub85d"})}),"\n",(0,n.jsxs)(r.p,{children:["\ube14\ub799\ucea3\uc740 \uae30\ub85d\uc744 \uad49\uc7a5\ud788 \uc798 \ud558\ub294 \ud06c\ub8e8\uc600\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub178\uc158\uc5d0 \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ud588\ub358 \ub0b4\uc6a9 + \uace0\ubbfc\ud588\ub358 \ubd80\ubd84 + \ud68c\uace0\ub97c \uaf3c\uaf3c\ud558\uac8c \uae30\ub85d\ud574\uc11c \uacf5\uc720\ud574 \uc8fc\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ucd94\uac00\uc801\uc73c\ub85c \uc774\ubaa8\uc9c0\ub97c \uc801\uadf9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uc5ec \ub354\uc6b1 \uc88b\uc558\ub2e4!"]}),"\n",(0,n.jsx)(r.p,{children:(0,n.jsx)(r.strong,{children:"\uc758\uacac \uc77c\uce58\uc2dc\ud0a4\uae30"})}),"\n",(0,n.jsxs)(r.p,{children:["\ud398\uc5b4 \uc2dc\uac04\uc740 \ud55c\uc815\ub418\uc5b4 \uc788\uace0, \uae30\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574\uc57c \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \uc801\ub2f9\ud788 \ud0c0\ud611\uc744 \ubd10\uc11c \uc758\uacac\uc744 \ube60\ub974\uac8c \uc218\uc6a9\ud574 \ub370\ub4dc\ub77c\uc778\uc744 \ub9de\ucd94\ub294 \uac83\ub3c4 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ube14\ub799\ucea3\uc740 \ub0b4 \uc758\uacac\uc744 \uc798 \ub4e4\uc5b4\uc92c\uace0, \ub355\ubd84\uc5d0 \ub9c9\ud788\ub294 \ubd80\ubd84 \uc5c6\uc774 \ube60\ub974\uac8c \ubbf8\uc158\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ube68\ub9ac \uce5c\ud574\uc84c\uace0, \uc758\uc0ac\uc18c\ud1b5\uc774 \uc798 \ub3fc\uc11c \uc7ac\ubc0c\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uc5c8\ub2e4!"})]})}function h(e={}){const{wrapper:r}={...(0,s.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function s(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(s[t]=e[t]);return s}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},h=n.forwardRef((function(e,r){var t=e.components,s=e.mdxType,o=e.originalType,a=e.parentName,h=i(e,["components","mdxType","originalType","parentName"]),d=l(t),u=s,j=d["".concat(a,".").concat(u)]||d[u]||p[u]||o;return t?n.createElement(j,c(c({ref:r},h),{},{components:t})):n.createElement(j,c({ref:r},h))}));h.displayName="MDXCreateElement"},33946:(e,r,t)=>{t.d(r,{Z:()=>n});const n=t.p+"assets/images/dto1-ccd4f91674b224578f2b295b3fccaf2c.png"},15907:(e,r,t)=>{t.d(r,{Z:()=>n});const n=t.p+"assets/images/dto2-15b381e0a024487f54608d438e5385f9.png"}}]); \ No newline at end of file diff --git a/assets/js/ae82353f.77430c26.js b/assets/js/ae82353f.0d3e2a97.js similarity index 97% rename from assets/js/ae82353f.77430c26.js rename to assets/js/ae82353f.0d3e2a97.js index 0048430d8..c960ecb48 100644 --- a/assets/js/ae82353f.77430c26.js +++ b/assets/js/ae82353f.0d3e2a97.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6420],{96046:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var r=n(85893),s=n(3905);const i={title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",slug:"spring-test-isolation",tags:["test"]},a=void 0,o={permalink:"/spring-test-isolation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",source:"@site/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",description:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac",date:"2023-10-03T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 3\uc77c",tags:[{label:"test",permalink:"/tags/test"}],readingTime:4.315,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",slug:"spring-test-isolation",tags:["test"]},unlisted:!1,prevItem:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/mvc-retrospective"},nextItem:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",permalink:"/web-application-evolution"}},c={authorsImageUrls:[]},l=[{value:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac",id:"\ud14c\uc2a4\ud2b8-\uaca9\ub9ac",level:3},{value:"TestExecutionListener",id:"testexecutionlistener",level:3},{value:"AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604",id:"abstracttestexecutionlistener-\uc0c1\uc18d\ud558\uc5ec-\uad6c\ud604",level:3},{value:"Listener \ub4f1\ub85d",id:"listener-\ub4f1\ub85d",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\ud14c\uc2a4\ud2b8-\uaca9\ub9ac",children:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac"}),"\n",(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8\uc758 \uc21c\uc11c\uc5d0 \ub530\ub77c \uc131\uacf5 \uc2e4\ud328 \uc5ec\ubd80\uac00 \uacb0\uc815\ub418\ub294 \ube44\uacb0\uc815\uc801\uc778(non-determinism) \ud14c\uc2a4\ud2b8\uac00 \ub418\uc5b4\uc11c\ub294 \uc548\ub418\uace0, \ud14c\uc2a4\ud2b8\ub294 \ud56d\uc0c1 \uc21c\uc11c\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc218\ud589\ub418\ub3c4\ub85d \ubcf4\uc7a5\ub418\uc5b4\uc57c \ud55c\ub2e4. \uc77c\ubc18\uc801\uc73c\ub85c \uc790\uc6d0\uc758 \uacf5\uc720, \uc678\ubd80 API, \uc2dc\uac04 \ub4f1\uc73c\ub85c \ube44\uacb0\uc815\uc801\uc778 \ud14c\uc2a4\ud2b8\uac00 \ub41c\ub2e4. \uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \uc0ac\uc6a9\ud558\uac70\ub098, \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc7ac\uc2e4\ud589\ud558\ub294 ",(0,r.jsx)(t.code,{children:"@DirtiesContext"}),", \uc790\uc6d0\uc744 \ucd08\uae30\ud654\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uc774\ud6c4\uc5d0 \ud14c\uc774\ube14\uc744 \ub864\ubc31 \ud558\ub294 ",(0,r.jsx)(t.code,{children:"@Transactional"}),"\ub4f1 \ub2e4\uc591\ud55c \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud574\ub2f9 \uae00\uc5d0\uc11c\ub294 \uc2a4\ud504\ub9c1\uc5d0\uc11c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc790\uc6d0\uc758 \uacf5\uc720\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc218\ud589\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc124\uba85\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"Independent - FIRST",type:"note",children:(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8\ub07c\ub9ac \uc11c\ub85c \uc758\uc874\ud558\uba74 \uc548 \ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc11c\ub85c \uc758\uc874\ud558\uac8c \ub41c\ub2e4\uba74 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \ub54c, \ub610 \ub2e4\ub978 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud14c\uc2a4\ud2b8\uac00 \uc88b\uc740 \ud14c\uc2a4\ud2b8\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"testexecutionlistener",children:"TestExecutionListener"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 TextExecutionListner\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 \ud14c\uc2a4\ud2b8 \uc2e4\ud589 \ub2e8\uacc4\uc5d0\uc11c \uc774\ubca4\ud2b8\ub97c \uc218\uc2e0\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub97c \uc774\uc6a9\ud558\uba74 JUnit\uc758 @BeforeEach\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uacfc \uc720\uc0ac\ud558\uac8c, \ud14c\uc2a4\ud2b8\uc758 \uc0dd\uba85\uc8fc\uae30 \uc774\uc804 \ub610\ub294 \uc774\ud6c4\uc5d0 \ud544\uc694\ud55c \uc791\uc5c5\uc744 \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=TextExecutionListner",children:"public interface TestExecutionListener {\n default void beforeTestClass(TestContext testContext) throws Exception {}\n default void prepareTestInstance(TestContext testContext) throws Exception {}\n default void beforeTestMethod(TestContext testContext) throws Exception {}\n default void beforeTestExecution(TestContext testContext) throws Exception {}\n default void afterTestExecution(TestContext testContext) throws Exception {}\n default void afterTestMethod(TestContext testContext) throws Exception {}\n default void afterTestClass(TestContext testContext) throws Exception {}\n}\n"})}),"\n",(0,r.jsx)(t.h3,{id:"abstracttestexecutionlistener-\uc0c1\uc18d\ud558\uc5ec-\uad6c\ud604",children:"AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604"}),"\n",(0,r.jsxs)(t.p,{children:["AbstractTestExecutionListener\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac \ud658\uacbd\uc744 \ub9cc\ub4e4\uc5b4\uc8fc\ub294 \ud074\ub798\uc2a4\ub85c, \uc778\ud130\ud398\uc774\uc2a4\uc778 TextExecutionListner\uc640 \ub2ec\ub9ac Ordered\uac00 \uad6c\ud604\ub418\uc5b4 \uc788\uc5b4 \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ubc1b\uc544 \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub294 \ud504\ub808\uc784\uc6cc\ud06c\uac00 \uc81c\uacf5\ud558\ub294 \ub9ac\uc2a4\ub108 \ub2e4\uc74c\uc5d0 \uc2e4\ud589\uc2dc\ud0a4\ub3c4\ub85d \ud574\uc900\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\uc74c\uacfc \uac19\uc774 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac01\uac01\uc758 \ud14c\uc774\ube14\uc5d0 \ud574\ub2f9\ud558\ub294 Truncate \ucffc\ub9ac\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc870\ud68c\ud558\uace0, Test \uba54\uc11c\ub4dc\uac00 \ub05d\ub0a0\ub54c \ub9c8\ub2e4 \ud574\ub2f9 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uc5ec \ud14c\uc774\ube14\uc744 \ucd08\uae30\ud654\uc2dc\ud0a4\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=DatabaseCleaner",children:'\npublic class DatabaseCleaner extends AbstractTestExecutionListener {\n\n private static final String TRUNCATE_TABLE_QUERY = """\n SELECT Concat(\'TRUNCATE TABLE \', TABLE_NAME, \';\') \n FROM INFORMATION_SCHEMA.TABLES\n WHERE TABLE_SCHEMA = \'PUBLIC\'\n """;\n\n @Override\n public void afterTestMethod(TestContext testContext) {\n JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);\n List truncateTableQueries = getTruncateTableQueries(jdbcTemplate);\n truncateTables(jdbcTemplate, truncateTableQueries);\n }\n\n private JdbcTemplate getJdbcTemplate(TestContext testContext) {\n return testContext.getApplicationContext().getBean(JdbcTemplate.class);\n }\n\n private List getTruncateTableQueries(JdbcTemplate jdbcTemplate) {\n return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);\n }\n\n private void truncateTables(JdbcTemplate jdbcTemplate, List truncateTableQueries) {\n jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");\n truncateTableQueries.forEach(jdbcTemplate::execute);\n jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");\n }\n}\n\n'})}),"\n",(0,r.jsx)(t.h3,{id:"listener-\ub4f1\ub85d",children:"Listener \ub4f1\ub85d"}),"\n",(0,r.jsxs)(t.p,{children:["@TestExecutionListeners\ub97c \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790 \uc815\uc758 \ub9ac\uc2a4\ub108\ub97c \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","mergeMode\uc758 \uae30\ubcf8\uac12\uc740 REPLACE_DEFAULTS\ub85c \ub9ac\uc2a4\ub108\uac00 \uc774\ubbf8 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \ub4f1\ub85d\ub41c \ub9ac\uc2a4\ub108\ub85c \ubcc0\uacbd\ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","MERGE_WITH_DEFAULTS\ub85c \uc124\uc815\ud55c\ub2e4\uba74 Ordered \uae30\uc900\uc73c\ub85c \uc21c\uc11c\uac00 \uacb0\uc815\ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ud6c4 \uaca9\ub9ac\uac00 \ud544\uc694\ud55c \ud14c\uc2a4\ud2b8\ub4e4\uc740 \ub2e4\uc74c\uc758 \ucd94\uc0c1 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ud558\uc5ec \uc0ac\uc6a9\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=AcceptanceTest",children:"\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\n@TestExecutionListeners(\n value = DatabaseCleaner.class,\n mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS\n)\npublic abstract class AcceptanceTest {\n\n @LocalServerPort\n private int port;\n\n @BeforeEach\n public void setUp() {\n RestAssured.port = port;\n }\n}\n\n"})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://www.baeldung.com/spring-testexecutionlistener",children:"The Spring TestExecutionListener, Baeldung"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://tecoble.techcourse.co.kr/post/2020-09-15-test-isolation/",children:"\uc778\uc218\ud14c\uc2a4\ud2b8\uc5d0\uc11c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ud558\uae30, \ud14c\ucf54\ube14"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://martinfowler.com/articles/nonDeterminism.html",children:"Eradicating Non-Determinism in Tests, martin fowler"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://mangkyu.tistory.com/264",children:"@SpringBootTest\uc758 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\uc2dc\ud0a4\uae30, MangKyu"})]})]})}function p(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>l});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},p=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),u=l(n),T=s,x=u["".concat(c,".").concat(T)]||u[T]||d[T]||i;return n?r.createElement(x,a(a({ref:t},p),{},{components:n})):r.createElement(x,a({ref:t},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6420],{96046:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var r=n(85893),s=n(3905);const i={title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",slug:"spring-test-isolation",tags:["test"]},a=void 0,o={permalink:"/spring-test-isolation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",source:"@site/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",description:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac",date:"2023-10-03T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 3\uc77c",tags:[{label:"test",permalink:"/tags/test"}],readingTime:4.315,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac",slug:"spring-test-isolation",tags:["test"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",permalink:"/web-application-evolution"},nextItem:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/mvc-retrospective"}},c={authorsImageUrls:[]},l=[{value:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac",id:"\ud14c\uc2a4\ud2b8-\uaca9\ub9ac",level:3},{value:"TestExecutionListener",id:"testexecutionlistener",level:3},{value:"AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604",id:"abstracttestexecutionlistener-\uc0c1\uc18d\ud558\uc5ec-\uad6c\ud604",level:3},{value:"Listener \ub4f1\ub85d",id:"listener-\ub4f1\ub85d",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\ud14c\uc2a4\ud2b8-\uaca9\ub9ac",children:"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac"}),"\n",(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8\uc758 \uc21c\uc11c\uc5d0 \ub530\ub77c \uc131\uacf5 \uc2e4\ud328 \uc5ec\ubd80\uac00 \uacb0\uc815\ub418\ub294 \ube44\uacb0\uc815\uc801\uc778(non-determinism) \ud14c\uc2a4\ud2b8\uac00 \ub418\uc5b4\uc11c\ub294 \uc548\ub418\uace0, \ud14c\uc2a4\ud2b8\ub294 \ud56d\uc0c1 \uc21c\uc11c\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc218\ud589\ub418\ub3c4\ub85d \ubcf4\uc7a5\ub418\uc5b4\uc57c \ud55c\ub2e4. \uc77c\ubc18\uc801\uc73c\ub85c \uc790\uc6d0\uc758 \uacf5\uc720, \uc678\ubd80 API, \uc2dc\uac04 \ub4f1\uc73c\ub85c \ube44\uacb0\uc815\uc801\uc778 \ud14c\uc2a4\ud2b8\uac00 \ub41c\ub2e4. \uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \uc0ac\uc6a9\ud558\uac70\ub098, \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc7ac\uc2e4\ud589\ud558\ub294 ",(0,r.jsx)(t.code,{children:"@DirtiesContext"}),", \uc790\uc6d0\uc744 \ucd08\uae30\ud654\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uc774\ud6c4\uc5d0 \ud14c\uc774\ube14\uc744 \ub864\ubc31 \ud558\ub294 ",(0,r.jsx)(t.code,{children:"@Transactional"}),"\ub4f1 \ub2e4\uc591\ud55c \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud574\ub2f9 \uae00\uc5d0\uc11c\ub294 \uc2a4\ud504\ub9c1\uc5d0\uc11c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc790\uc6d0\uc758 \uacf5\uc720\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc218\ud589\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc124\uba85\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"Independent - FIRST",type:"note",children:(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8\ub07c\ub9ac \uc11c\ub85c \uc758\uc874\ud558\uba74 \uc548 \ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc11c\ub85c \uc758\uc874\ud558\uac8c \ub41c\ub2e4\uba74 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \ub54c, \ub610 \ub2e4\ub978 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud14c\uc2a4\ud2b8\uac00 \uc88b\uc740 \ud14c\uc2a4\ud2b8\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"testexecutionlistener",children:"TestExecutionListener"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 TextExecutionListner\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 \ud14c\uc2a4\ud2b8 \uc2e4\ud589 \ub2e8\uacc4\uc5d0\uc11c \uc774\ubca4\ud2b8\ub97c \uc218\uc2e0\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub97c \uc774\uc6a9\ud558\uba74 JUnit\uc758 @BeforeEach\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uacfc \uc720\uc0ac\ud558\uac8c, \ud14c\uc2a4\ud2b8\uc758 \uc0dd\uba85\uc8fc\uae30 \uc774\uc804 \ub610\ub294 \uc774\ud6c4\uc5d0 \ud544\uc694\ud55c \uc791\uc5c5\uc744 \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=TextExecutionListner",children:"public interface TestExecutionListener {\n default void beforeTestClass(TestContext testContext) throws Exception {}\n default void prepareTestInstance(TestContext testContext) throws Exception {}\n default void beforeTestMethod(TestContext testContext) throws Exception {}\n default void beforeTestExecution(TestContext testContext) throws Exception {}\n default void afterTestExecution(TestContext testContext) throws Exception {}\n default void afterTestMethod(TestContext testContext) throws Exception {}\n default void afterTestClass(TestContext testContext) throws Exception {}\n}\n"})}),"\n",(0,r.jsx)(t.h3,{id:"abstracttestexecutionlistener-\uc0c1\uc18d\ud558\uc5ec-\uad6c\ud604",children:"AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604"}),"\n",(0,r.jsxs)(t.p,{children:["AbstractTestExecutionListener\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac \ud658\uacbd\uc744 \ub9cc\ub4e4\uc5b4\uc8fc\ub294 \ud074\ub798\uc2a4\ub85c, \uc778\ud130\ud398\uc774\uc2a4\uc778 TextExecutionListner\uc640 \ub2ec\ub9ac Ordered\uac00 \uad6c\ud604\ub418\uc5b4 \uc788\uc5b4 \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ubc1b\uc544 \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub294 \ud504\ub808\uc784\uc6cc\ud06c\uac00 \uc81c\uacf5\ud558\ub294 \ub9ac\uc2a4\ub108 \ub2e4\uc74c\uc5d0 \uc2e4\ud589\uc2dc\ud0a4\ub3c4\ub85d \ud574\uc900\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub2e4\uc74c\uacfc \uac19\uc774 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac01\uac01\uc758 \ud14c\uc774\ube14\uc5d0 \ud574\ub2f9\ud558\ub294 Truncate \ucffc\ub9ac\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc870\ud68c\ud558\uace0, Test \uba54\uc11c\ub4dc\uac00 \ub05d\ub0a0\ub54c \ub9c8\ub2e4 \ud574\ub2f9 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uc5ec \ud14c\uc774\ube14\uc744 \ucd08\uae30\ud654\uc2dc\ud0a4\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=DatabaseCleaner",children:'\npublic class DatabaseCleaner extends AbstractTestExecutionListener {\n\n private static final String TRUNCATE_TABLE_QUERY = """\n SELECT Concat(\'TRUNCATE TABLE \', TABLE_NAME, \';\') \n FROM INFORMATION_SCHEMA.TABLES\n WHERE TABLE_SCHEMA = \'PUBLIC\'\n """;\n\n @Override\n public void afterTestMethod(TestContext testContext) {\n JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);\n List truncateTableQueries = getTruncateTableQueries(jdbcTemplate);\n truncateTables(jdbcTemplate, truncateTableQueries);\n }\n\n private JdbcTemplate getJdbcTemplate(TestContext testContext) {\n return testContext.getApplicationContext().getBean(JdbcTemplate.class);\n }\n\n private List getTruncateTableQueries(JdbcTemplate jdbcTemplate) {\n return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);\n }\n\n private void truncateTables(JdbcTemplate jdbcTemplate, List truncateTableQueries) {\n jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");\n truncateTableQueries.forEach(jdbcTemplate::execute);\n jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");\n }\n}\n\n'})}),"\n",(0,r.jsx)(t.h3,{id:"listener-\ub4f1\ub85d",children:"Listener \ub4f1\ub85d"}),"\n",(0,r.jsxs)(t.p,{children:["@TestExecutionListeners\ub97c \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790 \uc815\uc758 \ub9ac\uc2a4\ub108\ub97c \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","mergeMode\uc758 \uae30\ubcf8\uac12\uc740 REPLACE_DEFAULTS\ub85c \ub9ac\uc2a4\ub108\uac00 \uc774\ubbf8 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \ub4f1\ub85d\ub41c \ub9ac\uc2a4\ub108\ub85c \ubcc0\uacbd\ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","MERGE_WITH_DEFAULTS\ub85c \uc124\uc815\ud55c\ub2e4\uba74 Ordered \uae30\uc900\uc73c\ub85c \uc21c\uc11c\uac00 \uacb0\uc815\ub41c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ud6c4 \uaca9\ub9ac\uac00 \ud544\uc694\ud55c \ud14c\uc2a4\ud2b8\ub4e4\uc740 \ub2e4\uc74c\uc758 \ucd94\uc0c1 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ud558\uc5ec \uc0ac\uc6a9\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",metastring:"title=AcceptanceTest",children:"\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\n@TestExecutionListeners(\n value = DatabaseCleaner.class,\n mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS\n)\npublic abstract class AcceptanceTest {\n\n @LocalServerPort\n private int port;\n\n @BeforeEach\n public void setUp() {\n RestAssured.port = port;\n }\n}\n\n"})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://www.baeldung.com/spring-testexecutionlistener",children:"The Spring TestExecutionListener, Baeldung"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://tecoble.techcourse.co.kr/post/2020-09-15-test-isolation/",children:"\uc778\uc218\ud14c\uc2a4\ud2b8\uc5d0\uc11c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ud558\uae30, \ud14c\ucf54\ube14"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://martinfowler.com/articles/nonDeterminism.html",children:"Eradicating Non-Determinism in Tests, martin fowler"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://mangkyu.tistory.com/264",children:"@SpringBootTest\uc758 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\uc2dc\ud0a4\uae30, MangKyu"})]})]})}function p(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>l});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},p=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),u=l(n),T=s,x=u["".concat(c,".").concat(T)]||u[T]||d[T]||i;return n?r.createElement(x,a(a({ref:t},p),{},{components:n})):r.createElement(x,a({ref:t},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/b2b675dd.09e8d7a6.js b/assets/js/b2b675dd.09e8d7a6.js new file mode 100644 index 000000000..4c64b7615 --- /dev/null +++ b/assets/js/b2b675dd.09e8d7a6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[533],{28017:n=>{n.exports=JSON.parse('{"blogPosts":[{"id":"book-writer","metadata":{"permalink":"/book-writer","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx","source":"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx","title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","description":"\ucc45 \uc815\ubcf4","date":"2023-01-01T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 1\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":4.425,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","slug":"book-writer","tags":["Book"]},"unlisted":false,"nextItem":{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \\n> \ubc15\uc194\ubbf8 \\n>\\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\uc800\uc790\uc758 \uacbd\ud5d8\uacfc \ud568\uaed8 \uae00\uc4f0\uae30\uc5d0 \ub300\ud55c \uac00\ubcbc\uc6b4 \uc870\uc5b8\uc774 \ub2f4\uaca8\uc788\uc5b4 \uac00\ubccd\uac8c \uc77d\uae30 \uc88b\uc558\ub2e4. \\n\uae00\uc744 \uc798 \uc791\uc131\ud574 \ubcf4\uace0 \uc2f6\uc744 \ub54c \uc801\uc6a9\ud574 \ubcfc \uc218 \uc788\ub294 \uc815\ubcf4\uac00 \ub9ce\uc544\uc11c \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub2e4. \\n\\n\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\uc758 \ud504\ub9ac\ucf54\uc2a4\ub97c \uc9c4\ud589\ud560 \ub54c \ud6c4\uae30\ub97c \uc791\uc131\ud558\uace0 \ub098\uba74 \ud56d\uc0c1 \uae00\uc774 \ub531\ub531\ud558\ub2e4\ub294 \ub290\ub08c\uc744 \ubc1b\uc558\ub2e4. \\n\ub2e4\ub978 \uc9c0\uc6d0\uc790\ub4e4\uc758 \uc77d\uae30 \ud3b8\ud558\uace0, \ubc1d\uc740 \ub290\ub08c\uc744 \uc8fc\ub294 \uae00\uc744 \ubcf4\uba74 \ubd80\ub7ec\uc6b4 \ub9c8\uc74c\uc744 \uac00\uc9c0\uae30\ub3c4 \ud588\ub2e4. \\n\uc774 \ucc45\uc744 \uc77d\uc5c8\uc73c\ub2c8 2023\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae00\uc744 \uc798 \uc801\uc5b4\ubcf4\ub824\uace0 \ud55c\ub2e4.\\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \ubb38\uc7a5\uc774 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74\\n\ub0b4\uc6a9\uc744 \uc77c\ubaa9\uc694\uc5f0\ud558\uac8c \uc815\ub9ac\ud588\uace0, \uae00\uc758 \uc758\ub3c4\ub3c4 \uc090\ub6a4\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub3c4 \uc801\uc808\ud55c \uac83\uc73c\ub85c \uace8\ub790\ub294\ub370\u2026 \uadf8\ub7f0\ub370\ub3c4 \uc5b4\ub518\uac00\uac00 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74? \ucd95\ucd95 \ucc98\uc9c0\uace0 \ub530\ubd84\ud558\ub2e4\uba74? \ub9d0\uaf2c\ub9ac\ub97c \ubaa8\uc870\ub9ac \u2018~\ub2e4\u2019\ub85c \ud1b5\uc77c\ud55c \uac74 \uc544\ub2cc\uc9c0 \uc810\uac80\ud574 \ubcf4\uc138\uc694.\\n> \\n\\n> \ub9d0\uaf2c\ub9ac\ub97c \uc798 \uac16\uace0 \ub180\uc544\uc57c \ud569\ub2c8\ub2e4. \ubb38\uc7a5\uc758 \ub9c8\uc9c0\ub9c9 \uae00\uc790\ub97c \ub9e4\ubc88 \ub2e4\ub974\uac8c \uace0\uccd0\uc4f0\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uae00\uc5d0 \ud65c\uae30\ub97c \ub354\ud560 \uc218 \uc788\uc8e0. \ub54c\ub860 \ubb38\uc7a5\uc744 \ub2e4 \ub9c8\uce58\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub85c\ub9cc \ub05d\ub9fa\ub294 \uac83\ub3c4 \ubc29\ubc95. \ubb38\uc7a5\uacfc \ubb38\uc7a5 \uc0ac\uc774\uc5d0 \uc27c\ud45c\uac00 \ub4e4\uc5b4\uc11c\uba70 \uae00 \uc804\uccb4\uc5d0 \ud65c\uae30\uac00 \ub3cc\uac8c \ub3fc\uc694. \ubb38\uc7a5\uc758 \uae38\uc774\ub3c4 \ub2e4\ucc44\ub85c\uc6cc\uc9c0\ub294 \ub355\ubd84\uc5d0 \ub364\uc73c\ub85c \uc5bb\uac8c \ub418\ub294 \uac83\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ubc14\ub85c, \uae00\uc758 \ub9ac\ub4ec.\\n> \\n\\n> \uc774\uc804 \ubb38\uc7a5\uc5d0\uc11c \ub05d\ub09c \uae00\uc790\ub85c, \ub2e4\uc74c \ubb38\uc7a5\uc744 \ub05d\ub9fa\uc9c0 \uc54a\uae30. \ud55c\ub450 \ubb38\ub2e8\ub9c8\ub2e4 \ub2e8\uc5b4 \uc218\uc900\uc758 \uc544\uc8fc \uc9e7\uc740 \ubb38\uc7a5 \ubc30\uce58\ud558\uae30.\\n> \\n\\n> \uae00\uc758 \uc9c4\uc9dc \uc774\uc720, \uae00\uc758 \uc9c4\uc9dc \ubaa9\uc801, \uae00\uc758 \uc9c4\uc9dc \ub300\uc0c1\uc744 \ucc3e\uc73c\ub824\uace0 \uc560\uc37c\uc2b5\ub2c8\ub2e4. \uc9c0\uae08\ucc98\ub7fc \ud2c0\uc744 \ub5a0\uc62c\ub9b0\ub2e4\uac70\ub098, \ub208\uce58\ub97c \ubcf8\ub2e4\uac70\ub098, \uc815\uce58\uc801\uc778 \uc148\ub3c4 \ud558\uc9c0 \uc54a\uc558\uc5b4\uc694.\\n> \\n\\n> \uc81c\ubaa9\uc740 \uc9e7\uac8c, \ubcf4\uae30 \uc27d\uac8c, \uc77d\uae30 \uc27d\uac8c, \ubc1c\uc74c\uc774 \ube44\uc2b7\ud558\uac8c, \uc21c\uc11c\ub97c \ubc14\uafd4\uc11c\\n> \\n\\n> \uae00\uc744 \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ub2e4\ub4ec\uc744 \ub54c, \ub178\ub798\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubd05\ub2c8\ub2e4. \uac10\ud788 \uac00 \ub2ff\uc744 \uc218 \uc5c6\ub294 \ubaa9\ud45c\uc774\uaca0\uc9c0\ub9cc, \ud560 \uc218 \uc788\ub294 \ucd5c\uc18c\ud55c\uc758 \ub9ac\ub4ec\uc774\ub77c\ub3c4 \ubd99\uc5ec\uc8fc\uace0 \uc2f6\uc5b4\uc694.\\n> \\n\\n> \uc5ec\ub294 \ub9d0\uacfc \ub9c8\uc9c0\ub9c9 \ub9d0\uc5d0 \uc791\uc815\ud558\uace0 \ub9c8\uc74c\uc744 \ub2f4\ub294 \uc5f0\uc2b5\uc744 \ud574\ubd05\uc2dc\ub2e4. \uae00\uc758 \uc5b4\ub290 \uad6c\uc11d\uc774\ub77c\ub3c4 \ubed4\ud55c \uae00\uc790\ub294 \ub0a8\uae30\uc9c0 \uc54a\uaca0\ub178\ub77c \ub2e4\uc9d0\ud558\uba70 \uc368\ubcf4\ub294 \uac81\ub2c8\ub2e4. \ub098\ub9cc\uc774 \uac00\uc9c4 \uc720\uc77c\ud55c \uba54\uc2dc\uc9c0\uc5d0 \uc9d1\uc911\ud558\uba74\uc11c\uc694. \uadf8\ub7fc \uc0dd\uac01\uc774 \ub2ec\ub77c\uc9c0\uace0, \uace0\ub974\ub294 \ub2e8\uc5b4\ub3c4 \ub2ec\ub77c\uc9c0\uace0, \ub0a8\uae34 \ubb38\uc7a5\ub3c4 \ub2ec\ub77c\uc838\uc694. \uacb0\uad6d\uc5d0\ub294 \uae00\uc744 \uc4f4 \uc0ac\ub78c\uc778 \ub098 \uc790\uc2e0\ub3c4 \ub0a8\ub2ec\ub77c\uc9c8 \uac81\ub2c8\ub2e4.\\n> \\n\\n> \ub9de\ucda4\ubc95\uc740 \uc911\uc694\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub9de\ucda4\ubc95\ubcf4\ub2e4 \ub354 \uc911\uc694\ud55c \uac74 \uac70\uae30\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc785\ub2c8\ub2e4. \ub0b4 \ub9c8\uc74c\uc744 \uae00\uc5d0 \ub2f4\uc544 \uc2e4\uc5b4 \ubcf4\ub0b4\uae30 \uc804, \ub9de\ucda4\ubc95\uc744 \uc810\uac80\ud558\ub294 \uc774\uc720 \uc5ed\uc2dc \uadf8\uac81\ub2c8\ub2e4. \uc624\uc9c1 \ub0b4 \ub9c8\uc74c\uc774 \ub0a8\uc5d0\uac8c \uc77d\ud788\ub294 \ub3d9\uc548 \ubc29\ud574\uac00 \ub418\uc9c0 \uc54a\uae30\ub97c \ubc14\ub77c\uae30 \ub54c\ubb38\uc774\uc8e0. \ub0b4\uac00 \uc4f4 \uae00\ub3c4, \ub0a8\uc774 \uc4f4 \uae00\ub3c4. \uc5b8\uc81c\ub098 \uadf8 \uc548\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc774 \uba3c\uc800\uc785\ub2c8\ub2e4.\\n> \\n\\n> \uae00\uc744 \uc4f4\ub2e4\uace0 \uae00\uc774 \uc644\uc131\ub418\ub294 \uac8c \uc544\ub2c8\uc5d0\uc694. \uae00\uacfc \ub2ee\uc740 \ubaa8\uc2b5\uc73c\ub85c \uc0b4 \ub54c, \uae00\uc740 \ube44\ub85c\uc18c \uc644\uc131\ub429\ub2c8\ub2e4.\\n>"},{"id":"2022-retrospective","metadata":{"permalink":"/2022-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx","title":"2022\ub144 \ud68c\uace0","description":"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70","date":"2023-01-02T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 2\uc77c","tags":[{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.705,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"2022\ub144 \ud68c\uace0","slug":"2022-retrospective","tags":["Retrospective"]},"unlisted":false,"prevItem":{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","permalink":"/book-writer"},"nextItem":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation"}},"content":"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70 \\n\\n### \uc804\uc5ed\\n\\n\uc57d 1\ub144 6\uac1c\uc6d4\uac04\uc758 \uacf5\uad70 \uc815\ubcf4\ubcf4\ud638\ubcd1 \uc0dd\ud65c\uc744 \ub9c8\uce58\uace0 \uc804\uc5ed\uc744 \ud588\ub2e4. \\n\uc870\uae30 \uc804\uc5ed \ub54c\ubb38\uc5d0 2021\ub144 12\uc6d4\uc5d0 \ub098\uc654\uc9c0\ub9cc, \uc2e4\uc81c \uc804\uc5ed \ub0a0\uc9dc\ub294 2022\ub144\uc774\ub2c8 \ud68c\uace0\uc5d0 \uc801\uc5b4\ub3c4 \uc0c1\uad00\uc5c6\uaca0\uc9c0. \\n\\n\uc870\uae08 \ub354 \ubbf8\ub798\uc5d0 \ub300\ud55c \uc0dd\uac01\uc744 \ud574\ubcfc\uac78 \uadf8\ub7ac\ub2e4. \\n\uc804\uc5ed\uc744 \ud588\uc9c0\ub9cc \ubb50 \ud558\ub098 \uc81c\ub300\ub85c \ud560 \uc904 \uc544\ub294 \uac83\ub3c4 \uc5c6\uc73c\ub2c8 \ub113\uc740 \ubc14\ub2f7\uc18d\uc5d0 \ub369\uadf8\ub7ec\ub2c8 \ub193\uc544\uc9c4 \uae30\ubd84\uc774 \uad1c\ud788 \ub4e4\uc5c8\uc5c8\ub2e4. \\n\uc77c\ucc0d \uc0dd\uac01\uc744 \uc815\ub9ac\ud558\uc5ec \ubc29\ud5a5\uc744 \uc7a1\uc9c0 \ubabb\ud588\uae30\uc5d0 \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub0a8\uc558\ub2e4. \\n\\n### \uc790\ubc14\\n\\n\uc804\uc5ed\uc744 \ud558\uace0 \uc9c4\ub85c\ub97c \uace0\ubbfc\ud558\ub2e4 \ud5a5\ub85c\ub2d8\uc758 [\uc790\ubc14 \uacf5\ud654\uad6d](https://jojoldu.tistory.com/609) \ud3ec\uc2a4\ud305\uc744 \uc77d\uace0 \ub098\uc11c \uc790\ubc14 \uacf5\ubd80\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\uc720\uba85\ud55c \uc778\ud504\ub7f0\uc758 \uae40\uc601\ud55c\ub2d8\uc758 \uc2a4\ud504\ub9c1 \uac15\uc758\ub3c4 \uc788\uace0, \uc88b\uc740 \uc790\ubc14 \uac1c\ubc1c \uc11c\uc801\uc774 \ub9ce\uc544\uc11c \ub3c5\ud559\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4. \\n\ud558\ub2e4 \ubcf4\ub2c8 \uc790\ubc14\uc640 \uc2a4\ud504\ub9c1\uc744 \uacf5\ubd80\ud558\uba74\uc11c \u201c\uc65c \uc9c4\uc791\ud558\uc9c0 \uc54a\uc558\uc9c0\u201d\ub77c\ub294 \uc0dd\uac01\ub3c4 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\uc591\uc9c8\uc758 \uc790\ub8cc\ub3c4 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0, \uc608\uc804\uc5d0 \ub178\ub4dc\ub85c \uac1c\ubc1c\ud588\uc744 \ub54c \ud480\uc9c0 \ubabb\ud588\ub358 \ub2f5\ub2f5\ud568\uc744 \ub9ce\uc774 \ud574\uc18c\ud588\ub358 \uac83 \uac19\ub2e4.\\n\\n23\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae4a\uac8c \uc790\ubc14\ub97c \uacf5\ubd80\ud574\ubcfc \uc0dd\uac01\uc774\ub2e4. \\n\uc5b8\uc5b4\ub97c \ud558\ub098 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ub9ce\uc740 \ub3c4\uc6c0\uc774 \ub418\ub294 \uac83 \uac19\ub2e4.\\n\\n### \uc2a4\ud130\ub514\\n\\n\uae40\uc601\ud55c\ub2d8\uc758 \uac15\uc758\ub97c \uac70\uc758 \ub2e4 \ub4e4\uc5c8\uc744 \ub54c\ucbe4, \ud56d\uc0c1 \uac15\uc758\uc5d0\uc11c \uc5b8\uae09\ub418\ub294 \ud1a0\ube44\uc758 \uc2a4\ud504\ub9c1\uc744 \uc77d\uc5b4\ubcf4\uace0 \uc2f6\uc5b4\uc84c\uace0 \\n\ud63c\uc790 \uacf5\ubd80\ud558\uae30\uc5d0\ub294 \ub3d9\uae30\ubd80\uc5ec\ub3c4 \ubd80\uc871\ud588\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud130\ub514\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\uc744 \ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uacf5\ubd80\ub97c \ud560 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\uc9c0\ub9cc \ub098\uc5d0\uac8c\ub294 \ub0b4\uc6a9\uc774 \uaf64\ub098 \uc5b4\ub824\uc6cc\uc11c \uc2dc\uac04\uc744 \ub9ce\uc774 \uc18c\ube44\ud588\ub2e4. \\n\uac19\uc774 \uc2a4\ud130\ub514\ud558\uc2dc\ub294 \ubd84\uacfc 7\uac1c\uc6d4 \ub3d9\uc548 \uc2a4\ud130\ub514\ub97c \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00 \ucd1d 3\uad8c\uc758 \ucc45\uc744 \uc77d\uc744 \uc218 \uc788\uc5c8\ub2e4.\\n\\n### \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\\n\\n\uad70 \ubcf5\ubb34 \uc911\uc77c \ub54c \uc9c0\uc6d0\ud588\ub2e4 \ub5a8\uc5b4\uc9c4 \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ub2e4\uc2dc \uc9c0\uc6d0\ud588\ub2e4. \\n\uc774\ubc88 \uc5f0\ub3c4\uc5d0 \ucde8\uc5c5\uc744 \ud558\ub294 \uac8c \ubaa9\ud45c\uc600\uc9c0\ub9cc \ub0b4\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud2b9\ubcc4\ud55c \ubb34\uae30\uac00 \uc5c6\ub2e4\ub294 \uac78 \uae68\ub2ec\uc558\ub2e4. \\n\uc801\uc9c0 \uc54a\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574 \uc900\ube44\ub97c \ud588\uace0, \uac10\uc0ac\ud558\uac8c\ub3c4 \uc774\ubc88\uc5d0\ub294 \ucd5c\uc885 \ud569\uaca9\uc744 \ud588\ub2e4. \\n\\n\ub09c \uc0ac\ub78c\ub4e4\uacfc \uc18c\ud1b5\ud558\uace0, \ud611\uc5c5\ud558\ub294 \ub2a5\ub825\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ud1b5\ud574 \uadf8 \ube48 \ubd80\ubd84\uc744 \ucc44\uc6b0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### 2023\ub144\uc5d0\ub294\\n\\n\ub9c8\uc74c\uc758 \uc5ec\uc720\uac00 \uc5c6\uc5c8\ub358 2022\ub144\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ud558\uace0 \uc2f6\uc740 \uac74 \ub9ce\uc9c0\ub9cc, \uc774\ubc88\uc5d0\ub294 \uc5ec\uc720\ub97c \uac00\uc9c0\uace0 \ud560 \uc218 \uc788\ub294 \uac83\uc5d0 \ucd5c\uc120\uc744 \ub2e4\ud574\uc57c\uaca0\ub2e4."},{"id":"the-essence-of-object-orientation","metadata":{"permalink":"/the-essence-of-object-orientation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx","source":"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx","title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","description":"\ucc45 \uc815\ubcf4","date":"2023-01-07T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 7\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":5.415,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","slug":"the-essence-of-object-orientation","tags":["Book"]},"unlisted":false,"prevItem":{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective"},"nextItem":{"title":"JSR-310","permalink":"/jsr-310"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574 \\n> \uc870\uc601\ud638\\n> \\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\uc870\uc601\ud638\ub2d8\uc758 \uc624\ube0c\uc81d\ud2b8\ub97c \uc77d\uace0 \ub098\uc11c \ub2e4\uc2dc \ud55c \ubc88 \uc77d\uc5b4\ubcf4\uc558\ub2e4. \\n\uc544\uc9c1 \uc774\ud574\uac00 \uc548\ub418\ub294 \ubd80\ubd84\uc774 \ub9ce\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ud56d\uc0c1 \uc0c8\ub85c\uc6c0\uc744 \ub290\ub080\ub2e4. \\n\ub354\ud560 \ub098\uc704 \uc5c6\uc774 \ud73c\ub96d\ud55c \uac1d\uccb4\uc9c0\ud5a5 \ucc45\uc774\uace0, \uc870\uae08 \ub354 \uacf5\ubd80\ud558\uace0 \ub2e4\uc2dc \uc77d\uc5b4\ubd10\uc57c\ub420 \uac83 \uac19\ub2e4. \\n\\n\ucee4\ud53c \uc804\ubb38\uc810, \uc9c0\ud558\ucca0 \ub178\uc120\ub3c4, \uc774\uc0c1\ud55c \ub098\ub77c\uc758 \uc5d8\ub9ac\uc2a4\ub97c \uc608\uc2dc\ub85c \ub4e0 \uc124\uba85\uc774 \ub108\ubb34 \uc88b\uc558\uace0 \\n\uc88b\uc740 \ub0b4\uc6a9\uc744 \ub2f4\uace0 \uc788\uc9c0\ub9cc \uadf8\ub807\ub2e4\uace0 \ub108\ubb34 \ubb34\uac81\uc9c0 \uc54a\uc544 \uac00\ubccd\uac8c \uc77d\uae30\ub3c4 \uc88b\uc740 \uac83 \uac19\ub2e4.\\n\\n### \ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173\\n\\n\ud611\ub825\uc744 \ub2e8\uc21c\ud558\uac8c \ub9cc\ub4e0\ub2e4.\\n\\n- \uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604 \u2192 \ud611\ub825\uc758 \ubcf5\uc7a1\ud568 \uc800\ud558\\n- \ucc45\uc784\uc758 \ucd94\uc0c1\ud654\\n\\n\uc678\ubd80\uc640 \ub0b4\ubd80\ub97c \uba85\ud655\ud558\uac8c \ubd84\ub9ac\ud55c\ub2e4.\\n\\n- \uc694\uccad\ud558\ub294 \uac1d\uccb4\uac00 \ubab0\ub77c\ub3c4 \ub418\ub294 \ubd80\ubd84\uc774 \ucea1\uc290\ud654\ub428\uc73c\ub85c \uc778\ud130\ud398\uc774\uc2a4\uc640 \uad6c\ud604\uc758 \ubd84\ub9ac\\n\\n\ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub0b4\ubd80\uc801\uc778 \ubc29\ubc95\uc744 \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 \uc678\ubd80\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub294\ub2e4.\\n\\n- \ubcc0\uacbd\uc758 \ud30c\uae09\ud6a8\uacfc\ub97c \uac1d\uccb4 \ub0b4\ubd80\ub85c \ucea1\uc290\ud654 \u2192 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \uac1d\uccb4\uc640\uc758 \uacb0\ud569\ub3c4 \uc800\ud558\\n\\n\ud611\ub825\uc758 \ub300\uc0c1\uc744 \ub2e4\uc591\ud558\uac8c \uc120\ud0dd\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\uc131\uc744 \uc81c\uacf5\ud55c\ub2e4.\\n\\n- \uc720\uc5f0\ud55c \uc124\uacc4 \u2192 \uc7ac\uc0ac\uc6a9\uc131 \uc99d\uac00\\n\\n\uac1d\uccb4\uc758 \uc5ed\ud560\uc744 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc9c4\ub2e4.\\n\\n- \uc751\uc9d1\ub3c4\ub97c \ub192\uc740 \uc0c1\ud0dc\ub85c \uc720\uc9c0\\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc758 \ubaa9\ud45c\ub294 \uc2e4\uc138\uacc4\ub97c \ubaa8\ubc29\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\\n\uc624\ud788\ub824 \uc0c8\ub85c\uc6b4 \uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc790\uc758 \uc5ed\ud560\uc740 \ub2e8\uc21c\ud788 \uc2e4\uc138\uacc4\ub97c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc548\uc73c\ub85c \uc62e\uaca8 \ub2f4\ub294 \uac83\uc774 \uc544\ub2c8\ub77c \uace0\uac1d\uacfc \uc0ac\uc6a9\uc790\ub97c \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\ub294 \uc2e0\uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\\np.21\\n> \\n\\n> \uacfc\uac70\uc758 \uc804\ud1b5\uc801\uc778 \uac1c\ubc1c \ubc29\ubc95\uc740 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uc5c4\uaca9\ud558\uac8c \uad6c\ubd84\ud55c\ub2e4.\\n\uc774\uc5d0 \ubc18\ud574 \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c\ub294 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uac1d\uccb4\ub77c\ub294 \ud558\ub098\uc758 \ud2c0 \uc548\uc5d0 \ud568\uaed8 \ubb36\uc5b4 \ub193\uc74c\uc73c\ub85c\uc368 \uac1d\uccb4\uc758 \uc790\uc728\uc131\uc744 \ubcf4\uc7a5\ud55c\ub2e4.\\n\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub85c \uad6c\uc131\ub41c \uacf5\ub3d9\uccb4\ub294 \uc720\uc9c0 \ubcf4\uc218\uac00 \uc27d\uace0 \uc7ac\uc0ac\uc6a9\uc774 \uc6a9\uc774\ud55c \uc2dc\uc2a4\ud15c\uc744 \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uac00\ub2a5\uc131\uc744 \uc81c\uc2dc\ud55c\ub2e4.\\np.33\\n> \\n\\n> **\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubcf8\uc9c8**\\n> \\n> \\n> \uc2dc\uc2a4\ud15c\uc744 \uc0c1\ud638\uc791\uc6a9\ud558\ub294 \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub4e4\uc758 \uacf5\ub3d9\uccb4\ub85c \ubc14\ub77c\ubcf4\uace0 \uac1d\uccb4\ub97c \uc774\uc6a9\ud574 \uc2dc\uc2a4\ud15c\uc744 \ubd84\ud560\ud558\ub294 \ubc29\ubc95\\n> \\n> \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub780 \uc0c1\ud0dc\uc640 \ud589\uc704\ub97c \ud568\uaed8 \uc9c0\ub2c8\uba70 \uc2a4\uc2a4\ub85c \uc790\uae30 \uc790\uc2e0\uc744 \ucc45\uc784\uc9c0\ub294 \uac1d\uccb4\ub97c \uc758\ubbf8\ud55c\ub2e4.\\n> \\n> \uac1d\uccb4\ub294 \uc2dc\uc2a4\ud15c\uc758 \ud589\uc704\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud55c\ub2e4. \uac01 \uac1d\uccb4\ub294 \ud611\ub825 \ub0b4\uc5d0\uc11c \uc815\ud574\uc9c4 \uc5ed\ud560\uc744 \uc218\ud589\ud558\uba70 \uc5ed\ud560\uc740 \uad00\ub828\ub41c \ucc45\uc784\uc758 \uc9d1\ud569\uc774\ub2e4.\\n> \\n> \uac1d\uccb4\ub294 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud558\uae30 \uc704\ud574 \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\uace0, \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c \uac1d\uccb4\ub294 \uba54\uc2dc\uc9c0\ub97c \ucc98\ub9ac\ud558\ub294 \ub370 \uc801\ud569\ud55c \uba54\uc11c\ub4dc\ub97c \uc790\uc728\uc801\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.\\n> p.35\\n> \\n\\n> \ud074\ub798\uc2a4\uc758 \uad6c\uc870\uc640 \uba54\uc11c\ub4dc\uac00 \uc544\ub2c8\ub77c \uac1d\uccb4\uc758 \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc5d0 \uc9d1\uc911\ud558\ub77c.\\n\uac1d\uccb4\uc9c0\ud5a5\uc740 \uac1d\uccb4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774\uc9c0 \ud074\ub798\uc2a4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\\np.38\\n> \\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub3d9\uc801\uc73c\ub85c \ubcc0\ud558\ub294 \uac1d\uccb4\uc758 \u2018\uc0c1\ud0dc\u2019\uc640 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \u2018\ud589\uc704\u2019\ub2e4.\\n\ud074\ub798\uc2a4\ub294 \ud0c0\uc785\uc744 \uad6c\ud604\ud558\uae30 \uc704\ud574 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uad6c\ud604 \uba54\ucee4\ub2c8\uc998\uc774\ub77c\ub294 \uc0ac\uc2e4\uc744 \uae30\uc5b5\ud558\ub77c.\\np.105\\n> \\n\\n> \ucc45\uc784 \uc8fc\ub3c4 \uc124\uacc4\uc758 \ud575\uc2ec\uc740 \uc5b4\ub5a4 \ud589\uc704\uac00 \ud544\uc694\ud55c\uc9c0\ub97c \uba3c\uc800 \uacb0\uc815\ud55c \ud6c4\uc5d0 \uc774 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac1d\uccb4\ub97c \uacb0\uc815\ud558\ub294 \uac83\uc774\ub2e4.\\n\uc774 \uacfc\uc815\uc744 \ud754\ud788 What/Who \uc0ac\uc774\ud074\uc774\ub77c\uace0 \ud55c\ub2e4.\\n\u2019\uc5b4\ub5a4 \ud589\uc704(What)\u2019\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud55c \ud6c4 \u2018\ub204\uac00(who)\u2019 \uadf8 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud574\uc57c \ud55c\ub2e4.\\n\uc5ec\uae30\uc11c \u2018\uc5b4\ub5a4 \ud589\uc704\u2019\uac00 \ubc14\ub85c \uba54\uc2dc\uc9c0\ub2e4.\\np.158\\n>"},{"id":"jsr-310","metadata":{"permalink":"/jsr-310","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-08-JSR-310.mdx","source":"@site/blog/2023-1/2023-01-08-JSR-310.mdx","title":"JSR-310","description":"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API","date":"2023-01-08T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 8\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Time","permalink":"/tags/time"}],"readingTime":1.685,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"JSR-310","slug":"jsr-310","tags":["Java","Time"]},"unlisted":false,"prevItem":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation"},"nextItem":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null"}},"content":"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API \\nISO-8601\uc744 \uae30\ubc18\uc73c\ub85c \uc791\uc131 \\n\uc124\uacc4 \ubaa9\ud45c \u2192 \ubd88\ubcc0, Fluent API, \uba85\ud655\ud558\uace0 \uba85\uc2dc\uc801, \ud655\uc7a5 \uac00\ub2a5\uc131\\n\\n:::note ISO-8601\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc5d0 \uad00\ub828\ub41c \ub370\uc774\ud130\ub97c \ub2e4\ub8e8\ub294 \uad6d\uc81c \ud45c\uc900\\n\\n:::\\n\\n### LocalDate, LocalTime, LocalDateTime\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4\\n\\n### Instant\\n\\n\uc720\ub2c9\uc2a4 \uc2dc\uac04(1970-01-01, 00:00:00 UTC) \uae30\uc900\uc73c\ub85c \ud2b9\uc815 \uc9c0\uc810\uae4c\uc9c0\uc758 \uc2dc\uac04\uc744 \ucd08\ub85c \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4 \\n\uae30\uacc4\uc758 \uad00\uc810\uc5d0\uc11c \uc2dc\uac04 \ud45c\ud604\\n\\n### Duration, Period\\n\\n\uac04\uaca9\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4\\n\\n### TemporalAdjusters\\n\\n\ubcf5\uc7a1\ud55c \ub0a0\uc9dc \uc870\uc815\uc774 \ud544\uc694\ud560 \ub54c \uc0ac\uc6a9 \\n\ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uc5ec \ucee4\uc2a4\ud140 TemporalAdjuster\ub97c \uad6c\ud604 \uac00\ub2a5\\n\\n```java\\n@FunctionalInterface\\npublic interface TemporalAdjuster {\\n Temporal adjustInto(Temporal temporal);\\n}\\n```\\n\\n### DateTimeFormatter\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04 \ud3ec\ub9f7 \ud074\ub798\uc2a4 \\n\ud2b9\uc815 \ub0a0\uc9dc \ud328\ud134\uc774\ub098, DateTimeFormatterBuilder\ub97c \uc774\uc6a9\ud574\uc11c \ucee4\uc2a4\ud140\ud55c \ud3ec\ub9f7\uc744 \uc0dd\uc131 \uac00\ub2a5\\n\\n### ZoneId, ZoneOffset\\n\\nZoneId\ub294 \uc9c0\uc5ed ID\ub294 `\u2018\uc9c0\uc5ed/\ub3c4\uc2dc\u2019` \ud615\uc2dd, ZoneOffset\uc740 \uc2dc\ucc28 UTC \uae30\uc900 \uace0\uc815\ub41c \uc2dc\uac04 \ucc28\uc774 \uc774\uc6a9 \\nZoneId\uc758 \uacbd\uc6b0 IANA Time Zone Database\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc9c0\uc5ed \uc9d1\ud569 \uc815\ubcf4 \uc0ac\uc6a9\\n\\n```java\\nInstant instant = Instant.now();\\nLocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n- [\ubaa8\ub358 \uc790\ubc14 \uc778 \uc561\uc158](https://product.kyobobook.co.kr/detail/S000001810171)\\n- [Java\uc758 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API](https://d2.naver.com/helloworld/645609)\\n- [ISO-8601](https://www.w3.org/TR/NOTE-datetime)\\n- [JSR-310 Spec](https://download.oracle.com/otn-pub/jcp/date_time-0.2-edr-oth-JSpec/date_time-0_2-edr-spec.pdf?AuthParam=1673171124_74a718be92efe4911c6977c02965aff4)\\n- [Temporal Adjuster](https://www.baeldung.com/java-temporal-adjuster)\\n- [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)"},{"id":"kotlin-null","metadata":{"permalink":"/kotlin-null","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx","source":"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx","title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","description":"nullable \ud0c0\uc785","date":"2023-01-16T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 16\uc77c","tags":[{"label":"Kotlin","permalink":"/tags/kotlin"}],"readingTime":4.225,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","slug":"kotlin-null","tags":["Kotlin"]},"unlisted":false,"prevItem":{"title":"JSR-310","permalink":"/jsr-310"},"nextItem":{"title":"IntelliJ \uc124\uc815","permalink":"/intellij-settings"}},"content":"import Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n### nullable \ud0c0\uc785\\n\\n\ucf54\ud2c0\ub9b0\uc740 `NullPointerException` \uc608\uc678\ub97c \ucd5c\ub300\ud55c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 \ud0c0\uc785 \uc2dc\uc2a4\ud15c\uc774 \uc124\uacc4\ub418\uc5b4 \uc788\ub2e4. \\n\uc774\ub294 \uc2e4\ud589 \uc2dc\uc810\uc774 \uc544\ub2cc \ucef4\ud30c\uc77c \uc2dc \ubbf8\ub9ac \uc624\ub958\uac00 \ubc1c\uc0dd\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub294 \ubd80\ubd84\uc744 \ubbf8\ub9ac \uac10\uc9c0\ud558\uc5ec NPE \ubc1c\uc0dd\uc758 \uac00\ub2a5\uc131\uc744 \uc904\uc5ec\uc900\ub2e4.\\n\\n\ucf54\ud2c0\ub9b0\uc758 \uacbd\uc6b0 nullable \ud0c0\uc785\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4.\\n\\n```kotlin\\nval number: Int?\\n```\\n\\n\ud0c0\uc785 \ub4a4\uc5d0 `?`\ub97c \ubd99\uc5ec \ud574\ub2f9 \uac12\uc774 null\uc774 \ub420 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4. \\n\ub9cc\uc57d `?`\ub97c \ubd99\uc774\uc9c0 \uc54a\uc744 \ub54c null\uc744 \ubc1b\ub294 \uacbd\uc6b0 \ucef4\ud30c\uc77c \uc2dc \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4.\\n\\n### `?.` Safe Calls \uc5f0\uc0b0\uc790\\n\\n\uc790\ubc14\uc5d0\uc11c NPE\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 null\uc744 \ucc98\ub9ac\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c\ub294 \ubd84\uae30\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.\\n\\n\ucf54\ud2c0\ub9b0\uc740 \uc548\uc804\ud55c \ud638\ucd9c \uc5f0\uc0b0\uc790\uc778 `?.` \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ucc38\uc870 \uac12\uc774 null\uc774 \uc544\ub2d0 \uacbd\uc6b0\uc5d0\ub9cc \uba54\uc11c\ub4dc \ud638\ucd9c\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\ucc38\uc870 \uac12\uc774 null\uc778 \uacbd\uc6b0 \uba54\uc11c\ub4dc \ud638\ucd9c\uc774 \ubb34\uc2dc\ub418\uace0, null\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\\n\\n\\n\\n```java\\npublic String repeat(String word) {\\n if (word == null) {\\n return null;\\n }\\n return word.repeat(2);\\n}\\n```\\n\\n\\n\\n\\n```kotlin\\nfun repeat(word: String?): String? {\\n return word?.repeat(2)\\n}\\n```\\n\\n\\n\\n\\n### `?:` \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\\n\\n\ucc38\uc870\ud558\ub824\ub294 \uac12\uc774 null\uc77c \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud558\uace0 \uc2f6\uc744 \ub54c\ub294 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c? \\n\ucf54\ud2c0\ub9b0\uc740 null\uc774 \uc544\ub2cc \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \ub54c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4.\\n\\n\\n\\n\\n```java\\npublic String stringSafe(String word) {\\n if (word == null) {\\n return \\"\\";\\n }\\n return word;\\n}\\n```\\n\\n\\n\\n\\n```kotlin\\nfun stringSafe(word: String?): String {\\n return word ?: \\"\\"\\n}\\n```\\n\\n\\n\\n\\n\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 throw\ub3c4 \uc2dd\uc774\uae30 \ub54c\ubb38\uc5d0 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 \uc0ac\uc6a9\uc790 \uc815\ubcf4\uac00 \uc788\ub294 \uc800\uc7a5\uc18c\uc5d0 \ucc3e\ub294 \uc0ac\uc6a9\uc790\uac00 \uc5c6\ub294 \uacbd\uc6b0 \uc544\ub798\uc640 \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n```kotlin\\nuserRepository.findByName(name) ?: throw IllegalArgumentException()\\n```\\n\\n### `!!` \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790\\n\\n!! \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud55c\ub2e4\uba74 \uac15\uc81c\ub85c \uc5b4\ub5a4 \uac12\uc774\ub4e0 non-nullable \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc null\uc778 \uac12\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4\uba74 NPE\uac00 \ubc1c\uc0dd\ud558\uac8c \ub41c\ub2e4. \\n\uc77c\ubc18\uc801\uc778 \uacbd\uc6b0\uc5d0\ub294 !! \uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc704\ud5d8\ud558\ub2e4. \\n\uc0ac\uc6a9\ud558\uae30 \uc27d\uc9c0\ub9cc, \ub9ac\uc2a4\ud06c\uac00 \ud06c\uace0 \ud639\uc2dc\ub098 \ud574\ub2f9 \uac12\uc774 \ucd94\ud6c4\uc5d0\ub294 null\uc774 \ub420 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc591\ud574\uc57c \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.\\n\\n```kotlin\\nval length: Int = word!!.length\\n```\\n\\n### `as?` \uc548\uc804\ud55c \uce90\uc2a4\ud305\\n\\n\ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \ub54c \uc9c0\uc815\ud55c \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc5c6\ub2e4\uba74 `ClassCastException`\uc774 \ubc1c\uc0dd\ud55c\ub2e4. \\n\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 as \ub4a4\uc5d0 ?\ub97c \ubd99\uc5ec \uc548\uc804\ud558\uac8c \ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ubbf8\ub9ac \ubcc0\ud658 \uac00\ub2a5\ud55c \ud0c0\uc785\uc778\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uace0, \uc548\uc804\ud558\uac8c \ud0c0\uc785\uc744 \ubcc0\ud658 \ud560 \uc218 \uc788\ub2e4. \\n\\n\ud0c0\uc785 \ubcc0\ud658\uc774 \ubd88\uac00\ub2a5 \ud560 \uacbd\uc6b0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uace0 null\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n```kotlin\\nval value: Int? = something as? Int\\n```\\n\\n### List\uc5d0\uc11c\uc758 null \ucc98\ub9ac\\n\\nList\uc5d0\ub294 null\uc774 \uc544\ub2cc \uac12\ub9cc \ubc18\ud658\ud558\ub294 `filterNotNull` \uc720\ud2f8\ub9ac\ud2f0 \uba54\uc11c\ub4dc\ub97c \uc81c\uacf5\ud55c\ub2e4.\\n\\n```kotlin\\nval foodsWithNull: List = listOf(\\"Pizza\\", \\"Cheese\\", null, \\"Potato\\")\\nval foods = foodsWithNull.filterNotNull()\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n- [Kotlin in Action](https://product.kyobobook.co.kr/detail/S000001804588)\\n- [Effective Kotlin Item 8](https://product.kyobobook.co.kr/detail/S000001033129)\\n- [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin/null-safety)\\n- [Kotlin NullSafety](https://kotlinlang.org/docs/null-safety.html)"},{"id":"intellij-settings","metadata":{"permalink":"/intellij-settings","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx","source":"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx","title":"IntelliJ \uc124\uc815","description":"Import \uc790\ub3d9 \uc801\uc6a9","date":"2023-01-30T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 30\uc77c","tags":[{"label":"IntelliJ","permalink":"/tags/intelli-j"}],"readingTime":0.465,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"IntelliJ \uc124\uc815","slug":"intellij-settings","tags":["IntelliJ"]},"unlisted":false,"prevItem":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null"},"nextItem":{"title":"Parameterized Tests","permalink":"/parameterized-tests"}},"content":"### Import \uc790\ub3d9 \uc801\uc6a9\\n\\nPrefrences > Editor > General > Auto Import > Add unambiguous imports on the fly\\n\\n![auto-import](./auto-import.png)\\n\\n### \uc800\uc7a5\uc2dc \ub3d9\uc791\\n\\nPrefrences > Tools > Actions on Save\\n\\n![actions-on-save](./actions-on-save.png)\\n\\nReformat Code: Code Reformmating\\n\\nOptimize imports: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 Import \uc81c\uac70\\n\\nRearrange: Code Style > Arrangement \uc124\uc815 \uae30\ubc18 \ucf54\ub4dc \uc7ac\uc815\ub82c\\n\\n### \uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9\\n\\nPrefrences > Editor > Code Style > Java > Code Generation > Final Modifier\\n\\n![final-modifier](./final-modifier.png)"},{"id":"parameterized-tests","metadata":{"permalink":"/parameterized-tests","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-12-Parameterized Tests.mdx","source":"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx","title":"Parameterized Tests","description":"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.","date":"2023-02-12T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 12\uc77c","tags":[{"label":"Java","permalink":"/tags/java"}],"readingTime":3.17,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Parameterized Tests","slug":"parameterized-tests","tags":["Java"]},"unlisted":false,"prevItem":{"title":"IntelliJ \uc124\uc815","permalink":"/intellij-settings"},"nextItem":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","permalink":"/racing-car-retrospective"}},"content":"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4. \\n\uc774 \ub54c `@ParameterizedTest`\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e8\uc77c \ud14c\uc2a4\ud2b8\ub97c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \ubc88 \ubc18\ubcf5\ud560 \uc218 \uc788\ub2e4.\\n\\n## Argument Sources\\n\\n`@ParameterizedTest`\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 Source \uc560\ub178\ud14c\uc774\uc158\uc774 \ud544\uc694\ud558\ub2e4. \\nJUnit\uc774 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c Source\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0, \ud14c\uc2a4\ud2b8\uc5d0 \ub9de\ucdb0 \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### Value Source\\n\\n\uac12\uc744 \uc774\uc6a9\ud558\uc5ec \uc81c\uacf5\ud558\ub294 \ud615\ud0dc\ub85c, \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4. \\n- short, int, long, float, double\\n- byte, char, boolean, String, Class \\n\\n```java\\n@ParameterizedTest\\n@ValueSource(ints = {1, 100, Integer.MAX_VALUE})\\nvoid valueTest(final int value) {\\n Assertions.assertThat(value).isPositive();\\n}\\n```\\n\\n### Null & Empty Source\\n\\nnull \uac12, \ube48 \uac12\uc744 \uc81c\uacf5\ud55c\ub2e4. \\nEmpty Source\uc758 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc5d0 \ud55c\ud574 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n- String\\n- java.util.List, java.util.Set, java.util.Map\\n- primitive arrays \u2014 ex) int[]\\n- object arrays \u2014 ex) String[]\\n\\n```java\\n@ParameterizedTest\\n@NullAndEmptySource\\nvoid nullAndEmptyTest(final String value) {\\n Assertions.assertThat(value).isNullOrEmpty();\\n}\\n```\\n\\n### Enum Source\\n\\nEnumSource\ub97c \uc774\uc6a9\ud558\uc5ec Enum \ub610\ud55c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\nenum Day {\\n MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\\n}\\n\\n@ParameterizedTest\\n@EnumSource(Day.class)\\nvoid enumTest(final Day day) {\\n assertThat(day).isInstanceOf(Day.class);\\n}\\n```\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 mode \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b9\uc9d5 Enum\uc744 \uc81c\uc678\ud558\uac70\ub098, \ud3ec\ud568\uc2dc\ud0ac \uc218 \uc788\ub2e4. (default: Mode.Include)\\n\\n```java\\n@ParameterizedTest\\n@EnumSource(value = Day.class, names = {\\"SATURDAY\\", \\"SUNDAY\\"}, mode = Mode.EXCLUDE)\\nvoid enumTest(final Day day) {\\n // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\\n assertThat(day).isInstanceOf(Day.class);\\n}\\n```\\n\\n### CSV Source\\n\\ncsv \ud615\uc2dd\uc758 \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud55c\ub2e4. \\n\uad6c\ubd84\uc790\uc758 \uae30\ubcf8\uac12\uc740 \uc27c\ud45c(,)\ub85c \uad6c\ubd84\uc790\ub97c \ubcc0\uacbd\ud558\uace0 \uc2f6\uc744 \ub550 delimeter \uac12\uc744 \ub530\ub85c \uc804\ub2ec\ud558\uc5ec \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\uac1c\uc778\uc801\uc73c\ub85c 2\uac1c \uc815\ub3c4\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ud558\ub294 \uacbd\uc6b0 CsvSource\ub97c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n```java\\n@ParameterizedTest\\n@CsvSource({\\"1,1\\", \\"2,4\\", \\"3,9\\", \\"4,16\\"})\\nvoid csvTest(final int number, final int result) {\\n assertThat(number * number).isEqualTo(result);\\n}\\n```\\n\\n### Method Source\\n\\n\ubcf5\uc7a1\ud55c \ud0c0\uc785\uc758 \uac12\uc744 \uc804\ub2ec\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\n\uba54\uc11c\ub4dc\uba85\uc744 \uc785\ub825\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4. \\n\uba54\uc11c\ub4dc\uba85\uc744 \ub530\ub85c \uc785\ub825\ud558\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uba85\uacfc \ub3d9\uc77c\ud55c static \uba54\uc11c\ub4dc\uac00 \uc9c0\uc815\ub41c\ub2e4.\\n\\n```java\\n@ParameterizedTest\\n@MethodSource\\nvoid methodTest(final List numbers, final int count) {\\n assertThat(numbers).hasSize(count);\\n}\\n\\nprivate static Stream methodTest() {\\n return Stream.of(\\n Arguments.of(List.of(1), 1),\\n Arguments.of(List.of(1, 2), 2),\\n Arguments.of(List.of(1, 2, 3), 3)\\n );\\n}\\n```\\n\\n### ETC.\\n\\n\uc704\uc5d0\uc11c \uc5b8\uae09\ud55c \ubc29\ubc95 \uc774\uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ubc29\ubc95\uc73c\ub85c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n- CSV \ud30c\uc77c\uc744 \uc774\uc6a9\ud55c CsvFileSource\\n- ArgumentsProvider \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \uc774\uc6a9\ud558\ub294 ArgumentsSource\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n- [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5)"},{"id":"racing-car-retrospective","metadata":{"permalink":"/racing-car-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/java-racingcar/pull/510","date":"2023-02-14T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 14\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.625,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","slug":"racing-car-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"Parameterized Tests","permalink":"/parameterized-tests"},"nextItem":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","permalink":"/ladder-retrospective"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/java-racingcar/pull/510 \\n2\ub2e8\uacc4: https://github.com/woowacourse/java-racingcar/pull/538 \\n:::\\n\\n### \uc790\ub3d9\ucc28 \uacbd\uc8fc\\n\\n\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158\uc5d0\uc11c\ub294 \ub2e4\uc990\uacfc \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc6b0\ud14c\ucf54 \ub4e4\uc5b4\uc640\uc11c \uccab \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\uc774\ub77c \ub9ce\uc774 \ub5a8\ub838\uc9c0\ub9cc, \ub2e4\uc990\uc774 \ub300\ud654\ub97c \uc798 \uc774\ub04c\uc5b4\uc918 \ub108\ubb34 \uc990\uac70\uc6e0\ub2e4. \\n\\n\uccab\ub0a0\uc740 \uac04\ub2e8\ud788 \ucee8\ubca4\uc158\uacfc \ud658\uacbd\uc744 \uc124\uc815\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc84c\uace0 \ub2e4\uc74c \ub0a0\ubd80\ud130 \uc790\ub3d9\ucc28 \uacbd\uc8fc\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\uc2dc\uc791\uc740 \uac04\ub2e8\ud558\uac8c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud558\uace0, \uc5b4\ub5bb\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud560\uc9c0 \uac19\uc774 \uace0\ubbfc\ud588\ub2e4. \\n\\n\uc2dc\uc791\ud558\uae30 \uc804 \uc544\ub798\uc640 \uac19\uc774 mermaid\ub97c \uc774\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc5d0 \ub300\ud574\uc11c \uac04\ub2e8\ud55c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \ub9cc\ub4e4\uace0 \uc2dc\uc791\ud588\ub2e4. \\nmermaid\ub294 \ucf54\ub4dc\ub85c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \uc0dd\uc131 \ud574\uc8fc\ub294 \ub3c4\uad6c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc774 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.\\n\\n- \ucf54\ub4dc \uae30\ubc18\uc774\ub77c \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \uc0dd\uac01\ud55c \uac83\uc744 \uc2dc\uac01\ud654\ud560 \uc218 \uc788\ub2e4. \\n- github\uc5d0\uc11c mermaid\ub97c \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \ucf54\ub4dc\ub97c \uc774\ud574\ud560 \uc218 \uc788\ub294 \ubd80\uac00\uc801\uc778 \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n```mermaid\\n---\\ntitle: \uc790\ub3d9\ucc28 \uacbd\uc8fc \uccab \ub9ac\ubdf0 \uc694\uccad\uc2dc \uad6c\uc870\\n---\\ngraph TD\\n Cars --\x3e Car\\n Car --\x3e Name\\n Car --\x3e Position\\n RacingGame --\x3e Count\\n RacingGame --\x3e NumberGenerator\\n RacingGame --\x3e Cars\\n RacingCarController --\x3e RacingGame\\n RandomNumberGenerator -.-> NumberGenerator\\n RacingCarController --\x3e InputView\\n InputView --\x3e InputValidator\\n RacingCarController --\x3e OutputView\\n```\\n\\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \ub370 \ud070 \uc5b4\ub824\uc6c0\uc774 \uc788\uc9c0\ub294 \uc54a\uc558\uace0, \ud398\uc5b4\ub97c \ub9c8\uce58\uae30 \uc804 \uc11c\ub85c \uace0\ubbfc\ub418\ub294 \ubd80\ubd84\uc744 \uc815\ub9ac\ud588\uc744 \ub54c \uc88b\uc558\ub2e4.\\n\\n\ud398\uc5b4\ud558\uba74\uc11c \uc798\ud588\ub2e4\uace0 \uc0dd\uac01\ud588\ub358 \uc810\uc740 \uc11c\ub85c\uc758 \uc0dd\uac01\uacfc \ub9ac\ubdf0 \ubc1b\uc740 \uac83\uc744 \uacf5\uc720\ud55c \uac83\uc774\ub2e4. \\n\ub9ac\ud329\ud130\ub9c1\uc744 \uc5b4\ub5bb\uac8c \ud588\ub294\uc9c0? \uc774\ub7f0 \ub9ac\ubdf0\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \uc0dd\uac01\ud558\ub294\uc9c0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c8 \uc218 \uc788\uc5c8\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ub9ac\ud329\ud130\ub9c1\uc774 \ub05d\ub09c \ud6c4 \uba54\uc11c\ub4dc\uba85, \ud14c\uc2a4\ud2b8\uc2dc \ucd9c\ub825\ud558\ub294 \uba54\uc2dc\uc9c0\uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\uac00 \ub9ce\uc774 \ub2ec\ub838\ub2e4. \\n\uac1d\uccb4\uac00 \uc5b4\ub5a4 \ucc45\uc784\uacfc \uc5ed\ud560\uc744 \uac00\uc9c0\ub294\uc9c0 \uc0dd\uac01\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uba85\ud655\ud55c \uba54\uc11c\ub4dc\uba85\uc744 \uc791\uc131\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n\ud3c9\uc18c\uc5d0 \ud504\ub85c\uadf8\ub798\ubc0d \uc774\uc57c\uae30\uac00 \uc544\ub2cc \ub2e4\ub978 \uc8fc\uc81c\ub85c \uc774\uc57c\uae30\ud558\uba74 \uc798 \ub4e4\uc73c\ub824\uace0 \ud558\ub294 \ud3b8\uc774\uc9c0\ub9cc \\n\ub0b4\uac00 \uc88b\uc544\ud558\ub294 \uc8fc\uc81c, \uad00\uc2ec\uac00\ub294 \uc8fc\uc81c\uc778 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub97c \ud560 \ub550 \ub9d0\uc774 \ub9ce\uc544\uc9c4\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130\ub294 \ub354 \ub9ce\uc740 \uc2dc\uac04\uc744 \ud398\uc5b4\uc758 \uc758\uacac\uacfc \uc774\uc57c\uae30\ub97c \ub4e3\ub294 \uacf3\uc5d0 \uc0ac\uc6a9\ud574\uc57c\uaca0\ub2e4.\\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**Assertions extracting**\\n\\n\uacb0\uacfc \ub0b4\ubd80\uc5d0 \uc788\ub294 \uac12\uc744 \ud655\uc778\ud558\uace0 \uc2f6\uc744 \ub54c extracting \ud0a4\uc6cc\ub4dc\ub97c \uc774\uc6a9\ud574\uc11c \ub0b4\ubd80\uc758 \uac12\uc744 \uac80\uc99d\ud560 \uc218 \uc788\ub2e4. \\n\uc774\uc804\uc5d0\ub294 \ud544\uc694\uc5d0 \ub530\ub77c stream\uc744 \uc774\uc6a9\ud558\uc5ec \uac80\uc99d\ud560 \uac12\uc744 \uc0dd\uc131\ud588\uc9c0\ub9cc, \ud574\ub2f9 \ubc29\ubc95\uc744 \uc774\uc6a9\ud574\uc11c \uc808\ucc28\ub97c \uc904\uc77c \uc218 \uc788\uc5c8\ub2e4.\\n\\n```java\\n@Test\\nvoid extracting() {\\n final Cars cars = new Cars(List.of(\\"car1\\", \\"car2\\"));\\n\\n assertThat(cars.getCars())\\n .extracting(Car::getName)\\n .containsExactly(\\"car1\\", \\"car2\\");\\n}\\n```\\n\\n---\\n\\n\uc544\ub798\ub294 \ub9ac\ubdf0\uc5b4\ub2d8\uacfc \ub300\ud654\ub97c \ub098\ub204\uba74\uc11c \uc5bb\uc740 \ub2f5\ubcc0 + \ub098\uc758 \uc758\uacac\uc774\ub2e4.\\n\\n**\uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8**\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc0c1\uc774 \uac80\uc99d\ub41c \uac83\uc774\ub77c\uba74 \uc791\uc131\ud558\uc9c0 \uc54a\uac70\ub098, \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uc791\uc131\ud55c\ub2e4. \\n\uc774\uac74 \uac1c\uc778\uc801\uc778 \uc0dd\uac01\uc774\uc9c0\ub9cc \ub0b4\uac00 \uc548\uc815\uac10\uc774 \ub4e4 \uc218 \uc788\uc744 \uc815\ub3c4\ub85c \ucd9c\ub825 \ubc94\uc704 \ub0b4\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud558\ub294\uc9c0 \uc815\ub3c4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?\\n\\n**\ub2e8\uc21c \uc704\uc784\uc744 \ud558\ub294 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8**\\n\\n\uc704\uc784\uc774\ub77c\ub294 \uac83\uc740 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4. \\n\ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc99d\ud558\ub294 \uac83\ubcf4\ub2e4 \uacb0\uacfc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\ub2e8\uc21c\ud788 \uc704\uc784\ub9cc \ud558\ub294 \ud14c\uc2a4\ud2b8\uc758 \uacbd\uc6b0 \uacb0\uacfc\ub97c \uac80\uc99d\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc911\ubcf5\ub418\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \uc911\ubcf5\ub41c \ud14c\uc2a4\ud2b8\ub97c \uc904\uc774\uae30 \uc704\ud574 \ub0b4\ubd80\uc758 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0 \uac80\uc99d\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\ub294 \uac83\uc744 \uc54c\uac8c \ub418\uc5c8\uc9c0\ub9cc \\n\uc548\uc815\uc801\uc73c\ub85c \uacb0\uacfc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc778 \uac83 \uac19\ub2e4.\\n\\n**\ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c getter \uc0ac\uc6a9**\\n\\n\ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\ub85c \ub3c4\uba54\uc778\uc5d0 \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc740 \uc88b\uc9c0 \ubabb\ud558\ub2e4. \\n\ud544\uc694\uc758 \uacbd\uc6b0 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc9c0\ub9cc, \uae30\uc874\uc5d0 \uc788\ub294 \uba54\uc11c\ub4dc\ub4e4\uc744 \ud65c\uc6a9\ud574\ubcf4\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4. \\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub9e4\uc6b0 \ub3d9\uc758\ud558\uace0, \uc55e\uc73c\ub85c\ub3c4 \ucd5c\ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \ucf54\ub4dc\ub97c \ub3c4\uba54\uc778\uc5d0 \uc791\uc131\ud558\uc9c0 \uc54a\uc744 \uac83 \uac19\ub2e4.\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n\uc9c8\ubb38\uc774\ub098 \uc0dd\uac01\ud560 \uc810\uc774 \uc788\uc744 \ub54c \ub9e4\uc6b0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uac83 \uac19\uc558\ub2e4. \\n\uc0dd\uac01\uc744 \uc815\ub9ac\ud55c \ud6c4 \uc790\uc2e0\uc758 \uc758\uacac\uc744 \uba85\ub8cc\ud558\uac8c \uc804\ub2ec\ud574\uc8fc\uc5c8\ub2e4. \\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc2dd\uc744 \ud6a8\uc728\uc801\uc73c\ub85c \uc2b5\ub4dd\ud55c\ub2e4. \\n\ub09c \uc0dd\uac01\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc740 \ucc44\ub85c \ub0b4\ubc84\ub824 \ub454 \uc595\uc740 \uc9c0\uc2dd\uc774 \ub9ce\uc740 \uac83 \uac19\ub2e4. (\uc774\ub7f0 \uac83\ub3c4 \uc544\ub294 \uac83\uc774\ub77c\uace0 \ud560 \uc218 \uc788\uc744\uae4c?) \\n\uc55e\uc73c\ub85c \uc870\uae08 \ub354 \uba38\ub9bf\uc18d\uc5d0\uc11c \uc815\ub9ac\ud558\uace0, \ubb38\uc81c\uc5d0 \ub300\ud574 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \ub298\ub824\uc57c\uaca0\ub2e4.\\n\\n\uac1c\ubc1c\uc5d0 \uc5f4\uc815\uc744 \uac00\uc9c4 \uac8c \ub290\uaef4\uc9c4\ub2e4. \\n\ub098\ub3c4 \uac1c\ubc1c\uc744 \uc88b\uc544\ud558\uc9c0\ub9cc, \ucd5c\uadfc\uc5d0\ub294 \uc758\uc9c0\uac00 \uc57d\ud574\uc84c\uc5c8\ub2e4. \\n\uc5f4\uc815\uc774 \uac00\ub4dd\ud55c \uc0ac\ub78c\uc744 \ub9cc\ub098\ub2c8 \ub098\ub3c4 \uc5f4\uc815\uc801\uc778 \uc0ac\ub78c\uc774 \ub418\ub294 \uac83 \uac19\ub2e4.\\n\\n\uce6d\ucc2c\uc744 \ub9ce\uc774 \ud574\uc900\ub2e4. \ub2e8\uc21c\ud788 \ub9ce\uc774 \ud574\uc8fc\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc9c4\uc2ec\uc744 \ub2f4\uae34 \uce6d\ucc2c\uc744 \ud574\uc92c\ub2e4. \\n\uce6d\ucc2c\uc740 \uace0\ub798\ub3c4 \ucda4\ucd94\uac8c \ud558\ub358\uac00? \\n\uadf8\ub798\uc11c \uc990\uac70\uc6b4 \ub9c8\uc74c\uc73c\ub85c \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud588\uc5c8\ub358 \uac83 \uac19\ub2e4.\\n\\n\uc5b4\ub5a4 \uc774\uc720 \ub54c\ubb38\uc778\uc9c0 \ubaa8\ub974\uaca0\uc9c0\ub9cc \uac19\uc774 \ud398\uc5b4\ud558\ub294\ub370 \ud3b8\ud55c \ub9c8\uc74c\uc774 \ub4e4\uc5c8\ub2e4. \\n\uc774\uac74 \ubc14\ub85c \ubc30\uc6b8 \uc218 \uc5c6\uc9c0\ub9cc. \\n\ub098\ub3c4 \uac19\uc774 \uc77c\ud560 \ub54c \ud3b8\ud55c \uc0ac\ub78c, \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub418\uae30 \uc704\ud574 \uae4a\uc774 \uace0\ubbfc\ud574\ubd10\uc57c\uaca0\ub2e4."},{"id":"ladder-retrospective","metadata":{"permalink":"/ladder-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/java-ladder/pull/97","date":"2023-02-26T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 26\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":10.285,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","slug":"ladder-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","permalink":"/racing-car-retrospective"},"nextItem":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","permalink":"/blackjack-retrospective"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/java-ladder/pull/97 \\n2\ub2e8\uacc4: https://github.com/woowacourse/java-ladder/pull/234 \\n:::\\n\\n### \uc0ac\ub2e4\ub9ac \ud0c0\uae30\\n\\n\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc6b0\uac00\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc774\uc804 \ubbf8\uc158\uacfc \ub2ec\ub9ac TDD\ub85c \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ud544\uc218\uc600\uae30 \ub54c\ubb38\uc5d0 \uc775\uc219\ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, \uc6b0\uac00\uc640 \ubbf8\uc158\uc5d0 \uad00\ud55c \uc18c\ud1b5\uc774 \uc798 \ub418\uc5b4\uc11c \ud070 \ubb38\uc81c \uc5c6\uc774 \ubbf8\uc158\uc744 \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\uc6b0\uac00\uc640 \uc774\uc57c\uae30\uac00 \uc798 \ud1b5\ud574\uc11c \uadf8\ub7f0\uc9c0 1\ub2e8\uacc4\ub294 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub294\ub370, 2\ub2e8\uacc4\uc5d0\uc11c \ub9ce\uc774 \uace0\uc804\ud55c \uac83 \uac19\ub2e4.\\n\\n2\ub2e8\uacc4\uc5d0\uc11c\ub294 2\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ud574\ubd24\ub2e4.\\n\\n1. LadderGame\uc5d0\uc11c Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n2. Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c Ladder\uc5d0\uac8c Position\uc744 \ub118\uaca8\uc8fc\uba70 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95\\n\\n### Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n\\n\uc0ac\uc2e4\uc0c1 index\ub97c Ladder\uc5d0\uac8c \ub118\uaca8\uc8fc\uace0, \ud574\ub2f9 index\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc1b\ub294 \ubc29\ubc95\uacfc \uc720\uc0ac\ud588\ub2e4. \\n\uad6c\ud604\ud558\uace0 \ub098\ub2c8 \ub2e4\ub978 \ud074\ub798\uc2a4\ub4e4\uc774 Position\uc5d0 \ub300\ud55c \uc758\uc874\ub3c4\uac00 \ub108\ubb34 \ub192\uc740 \uac83 \uac19\uc558\ub2e4. \\n\ub610\ud55c Players\uac00 \ubcc4\ub2e4\ub978 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\ub2e4\uace0 \ub290\uaf08\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\n LadderGameController --\x3e LadderGame\\n LadderGame --\x3e Ladder\\n LadderGame --\x3e Players\\n LadderGame --\x3e Items\\n\\n Ladder --\x3e Line\\n Line --\x3e LineStatus\\n\\n LadderGame --\x3e Position\\n Ladder --\x3e Position\\n Items --\x3e Position\\n Line --\x3e Position\\n Players --\x3e Position\\n\\n LadderGame --\x3e LadderGameResult\\n\\n Items --\x3e Item\\n Players --\x3e Player\\n\\n LadderGameController --\x3e InputView\\n LadderGameController --\x3e OutputView\\n\\n```\\n\\n```java\\npublic LadderGameResult play() {\\n final Map result = new LinkedHashMap<>();\\n // \uc0ac\uc6a9\uc790 \uc218\ub9cc\ud07c Position\uc744 \uac00\uc838\uc640\uc11c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4.\\n for (Position position : Position.range(players.count())) {\\n final Position resultPosition = ladder.play(position);\\n result.put(players.get(position), items.get(resultPosition));\\n }\\n return new LadderGameResult(result);\\n}\\n```\\n\\n### Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n\\nPosition\uc5d0 \ub300\ud55c \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub294 Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c, Player\uac00 Ladder\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4. \\n\uc774 \ubc29\ubc95\uc774 \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc704\ud574\uc11c \uac1d\uccb4\ub4e4\uc774 \uae34\ubc00\ud558\uac8c \ud611\ub825\ud558\uace0, \uc870\uae08 \ub354 \ucc45\uc784\uc758 \ubd84\ubc30\uac00 \uc798 \ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\uc774 \ub418\uc5c8\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\n LadderGameController --\x3e LadderGame\\n LadderGame --\x3e Ladder\\n LadderGame --\x3e Players\\n LadderGame --\x3e Items\\n\\n Ladder --\x3e Line\\n Line --\x3e LineStatus\\n Line --\x3e Position\\n\\n Players --\x3e Ladder\\n Player --\x3e Ladder\\n\\n Item --\x3e Position\\n Player --\x3e Position\\n\\n\\n LadderGame --\x3e LadderGameResult\\n\\n Items --\x3e Item --\x3e ItemName\\n Players --\x3e Player --\x3e PlayerName\\n\\n LadderGameController --\x3e InputView\\n LadderGameController --\x3e OutputView\\n\\n OutputView --\x3e LadderMessageGenerator\\n```\\n\\n```java\\npublic LadderGameResult play() {\\n // \ucc38\uac00\uc790\ub4e4\uc5d0\uac8c \uc0ac\ub2e4\ub9ac\ub97c \uc804\ub2ec\ud574\uc11c \uc0ac\ub2e4\ub9ac\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud55c\ub2e4.\\n final Map playResult = players.play(ladder);\\n\\n final Map result = new LinkedHashMap<>();\\n for (Player player : playResult.keySet()) {\\n result.put(player, toItem(playResult.get(player)));\\n }\\n return new LadderGameResult(result);\\n}\\n```\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\uc5d0 \uc2dc\uac04\uc744 \ub4e4\uc774\uae30** \\n\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc815\ud558\ub294\ub370 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ub4e4\uc5ec\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc0ac\ub2e4\ub9ac \ud0c0\uae30\uc758 \uc2e4\ud589 \uacb0\uacfc\ub97c Item\uc73c\ub85c \uc9d3\ub2e4\ub2c8.. \ubb54\uac00 \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\ub2e4. \\n\uc774\uc804 \ubbf8\uc158\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c, \uba85\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \ubd80\uc871\ud568\uc744 \ub9ce\uc774 \ub290\uaf08\ub2e4. \\n\\n**\ud398\uc5b4\uc640 \uc870\uae08 \ub354 \uce5c\ud574\uc9c0\uae30** \\n\uccab\ub0a0\uc740 \ud398\uc5b4\uc640 \uce5c\ud574\uc9c0\ub294 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \uac00\uc838\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc6b0\uac00\ub791 \ud68c\uace0\ud560 \ub54c \ub0b4\uac00 \uc2dc\uc791\ud558\uc790\ub9c8\uc790 \ucee8\ubca4\uc158 \uc815\ud558\uc790\uace0 \ud574\uc11c \ub9ce\uc774 \ub2f9\ud669\uc2a4\ub7ec\uc6e0\ub2e4\uace0 \ud55c\ub2e4. \uc6b0\uac00 \ubbf8\uc548.. \ud83e\udd72\\n\\n**README\ub97c \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c** \\n\uc774\uc0c1\ud558\uac8c \ucf54\ub529\uc5d0 \uc9d1\uc911\ud558\uba74 README\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uba74\uc11c \uac19\uc774 \ucee4\ubc0b \ud558\ub294 \uac78 \ud56d\uc0c1 \uae4c\uba39\ub294\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\uc5d0\ub294 \uc870\uae08 \ub354 \uc2e0\uacbd \uc368\uc57c\uaca0\ub2e4.\\n\\n**\uc88b\uc740 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud558\uae30** \\n\uccab PR\ub54c \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \uc9c8\ubb38\uc744 \ub0a8\uae30\uc9c0 \ubabb\ud588\ub2e4. \\n\ub9ac\ubdf0\uc5b4\uc640\uc758 \uc2dc\uac04\uc774 \uc18c\uc911\ud55c \uc2dc\uac04\uc774\ub77c\ub294 \uac83\uc744 \uae4c\uba39\uc9c0 \ub9d0\uace0, \ub098\uc758 \uc131\uc7a5\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud574\uc57c\uaca0\ub2e4. \\n\\n**PR \ud6c4\uc5d0\ub3c4 \uaf3c\uaf3c\ud558\uac8c \ud655\uc778\ud558\uae30** \\n\ubd84\uba85 \uc54c\uace0 \uc788\ub294 \ubd80\ubd84\uc774\uc9c0\ub9cc, \ub193\uce5c \ubd80\ubd84\uc774 \ub9ce\uc740 \uac83 \uac19\uc558\ub2e4. \\nPR \ud558\uae30 \uc804\uc5d0\ub3c4 \uacc4\uc18d \ud655\uc778\uc744 \ud588\uc9c0\ub9cc, \uc544\ubb34\ub798\ub3c4 IntelliJ\uc5d0\uc11c \ubcf4\ub2c8 \ucf54\ub4dc\uc5d0 \uc775\uc219\ud574\uc838\uc11c \uadf8\ub7f0\uc9c0 \ubcc0\uacbd\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc798 \uc548\ubcf4\uc600\ub2e4. \\ngithub pr\uc5d0\uc11c\ub294 \uc804\uccb4 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\ub2c8 PR \ud6c4\uc5d0\ub3c4 \uaf2d \ud655\uc778\ud574\uc57c\uaca0\ub2e4.\\n\\n**\uc801\uadf9\uc801\uc73c\ub85c \ub098\uc758 \uc758\uacac\uc744 \ub9d0\ud558\uae30** \\n\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ud398\uc5b4\uc758 \uc758\uacac\uc774 \uad1c\ucc2e\ub2e4\uace0 \uc0dd\uac01\ud558\uba74 \uc218\uc6a9 \ud6c4 \uac1c\uc120\uc744 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\uc5c8\ub294\ub370, \uc870\uae08 \ub354 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ud5a5\uc774 \uc788\ub2e4\uba74 \ub098\ub3c4 \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub9d0\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\ub098\ub3c4 \uc124\ub4dd\ud558\ub294 \ud798\uc744 \uae30\ub974\uace0, \ud398\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc744 \uc54c \uc218 \uc788\uace0, \uacb0\uacfc\ubb3c\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub098\uc624\uc9c0 \uc54a\uc744\uae4c? (\uace0\ubbfc \ub4e4\uc5b4\uc8fc\uc2e0 \ub9ac\ubdf0\uc5b4 \ud130\ud2c0\ud83d\udc22 \uac10\uc0ac\ud569\ub2c8\ub2e4.)\\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784** \\nPlayers\uac00 Position\uc744 \uc0dd\uc131\ud558\uace0 Player\uc758 \uc0dd\uc131\uc790\uc5d0 \ub123\uc5b4\uc8fc\uc5c8\ub2e4. \ud558\uc9c0\ub9cc \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ub828\ub41c \ucf54\uba58\ud2b8\uac00 \ub2ec\ub838\ub2e4.\\n\uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uc0dd\uac01\ud574 \ubcf4\ub2c8 Position\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uac74 Player\uae30 \ub54c\ubb38\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 Player\uac00 \ub2f4\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4. \\n\\n\uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud55c \ud328\ud134\uc73c\ub85c GRASP\uc758 Creator \ud328\ud134\uc774 \uc788\ub294\ub370 \ub2e4\uc74c\uc758 \uc694\uc18c\ub97c \ucd5c\ub300\ud55c \ub9cc\uc871\ud558\ub294 \ud074\ub798\uc2a4\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n- B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4.\\n- B\uac00 A\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4.\\n- B\uac00 A\uc758 \ucd08\uae43\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4. \\n\\n\uc2e4\uc81c\ub85c \uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud574\uc11c \uae4a\uc774 \uc0dd\uac01\ud558\uba74\uc11c \ucf54\ub529\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc2dc\uc57c\uac00 \ub113\uc5b4\uc9c4 \uac83 \uac19\ub2e4.\\n\\n**\ud328\ud0a4\uc9c0 \ubd84\ub9ac \uae30\uc900** \\n\ud328\ud0a4\uc9c0 \ubd84\ub9ac\uc5d0 \ub300\ud55c \ub098\ub9cc\uc758 \uae30\uc900\uc774 \uc544\uc9c1 \uba85\ud655\ud558\uc9c0 \uc54a\uc544 \uc9c8\ubb38\uc774 \ub4e4\uc5b4\uc640\ub3c4 \uba85\ud655\ud558\uac8c \ub2f5\ubcc0\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ub9c8\uc9c0\ub9c9 \uc81c\ucd9c \uc804\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub97c \ubd84\ub9ac\ud574 \ubd24\ub294\ub370, \uae30\uc900\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \uc88b\uc9c0 \uc54a\uc740 \uc120\ud0dd\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.\\n\ud604\uc7ac \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ud06c\uae30\uac00 \uadf8\ub807\uac8c \ud06c\uc9c0 \uc54a\uc73c\ub2c8, domain \ud328\ud0a4\uc9c0\uc5d0\uc11c \uc138\ubd80 \ud328\ud0a4\uc9c0\ub85c \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub420 \uac83 \uac19\ub2e4. \\n\\n**\uc0ac\uc6a9\ud558\ub294 \ucabd\uc5d0\uc11c \uc0dd\uac01\ud558\uae30 & \uc608\uce21\uac00\ub2a5\ud55c \ucf54\ub4dc \uc791\uc131\ud558\uae30** \\nPosition\uc5d0\uc11c \ub2e4\uc74c \uc704\uce58\ub098 \uc774\uc804 \uc704\uce58\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud5c8\uc6a9 \ubc94\uc704(0~19)\uac00 \ubc97\uc5b4\ub09c\ub2e4\uba74, \uc758\ubbf8 \uc5c6\ub294 \uac12\uc774 \ub4e4\uc5b4\uac04 Position\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\uc774\uac74 Position\uc744 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc744 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \ucf54\ub529\uc774\uc5c8\ub294\ub370, \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 0~19\uc758 \uac12\uc774 \ubcf4\uc7a5\ub418\uc5b4 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uac83\uc774\uae30 \ub54c\ubb38\uc774\ub2e4. \\n\ub530\ub77c\uc11c hasNext, hasPrevious\ub77c\ub294 \uc774\uc804 \uac12, \uc774\ud6c4 \uac12\uc774 \ubc94\uc704 \ub0b4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud558\uace0, \uae30\uc874\uc758 \uac12\uc744 \uac00\uc838\uc624\ub294 \uba54\uc11c\ub4dc\ub294 \ubc94\uc704\uac00 \ubc97\uc5b4\ub098\uba74 \uc608\uc678\ub97c \ub358\uc9c0\ub294 \ubc29\ud5a5\uc73c\ub85c \ud574\uacb0\ud558\uc600\ub2e4. \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n\ubc1d\uc740 \uae30\uc6b4\uc744 \uac00\uc9c0\uace0 \uc788\uace0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \uce5c\ud654\ub825\uc774 \uc88b\uc740 \uac83 \uac19\uc558\ub2e4. \\n\uc774\ubc88\uc5d0 \ud398\uc5b4 \ud560 \ub54c \ucee8\ub514\uc158 \uad00\ub9ac\ub97c \uc81c\ub300\ub85c \ubabb\ud574\uc11c \ub9ce\uc774 \ubbf8\uc548\ud588\ub2e4. \ub2e4\uc74c\uc5d0\ub294 \ucd5c\uc0c1\uc758 \ucee8\ub514\uc158\uc73c\ub85c \ud398\uc5b4\ub97c \uc900\ube44\ud574 \ubd10\uc57c\uaca0\ub2e4. \\n\uadf8\ub9ac\uace0 \uc6b0\uac00\ub791 \ud398\uc5b4\ub97c \ud558\uace0 \ub098\uc11c, \ub098\ub3c4 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \ub354 \uc798 \uc9c0\ub0b4\ubd10\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5b4 \uc870\uae08 \ub354 \uc6a9\uae30\ub97c \ub0b4 \uc7a1\ub2f4 \uc911\uc774\ub2e4! \\n\\n\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589\uc774 \uc798 \ub418\uc5c8\ub2e4. \\n\ub610\ud55c \ud398\uc5b4 \uc9c4\ud589\uc774 \ub290\ub9b0 \uac83 \uac19\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c \uc548\uc815\uc801\uc73c\ub85c \uc2dc\uac04 \uc548\uc5d0 \ubbf8\uc158\uc744 \uc644\ub8cc\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589 \uc18d\ub3c4\uc5d0 \ub300\ud574 \uc870\uae08 \ub354 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4!\\n\\n\ud56d\uc0c1 \uc9c0\ub098\uac08 \ub54c\ub9c8\ub2e4 \uc6c3\uc5b4\uc8fc\ub294\ub370, \ub098\ub3c4 \uc790\uc8fc \uc6c3\uc5b4\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc6c3\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uc0ac\ub78c\uc774 \ubc1d\uc544 \ubcf4\uc5ec\uc11c \ub108\ubb34 \uc88b\uc740 \uac83 \uac19\ub2e4!"},{"id":"blackjack-retrospective","metadata":{"permalink":"/blackjack-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/java-blackjack/pull/427","date":"2023-03-14T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 14\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.17,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","slug":"blackjack-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","permalink":"/ladder-retrospective"},"nextItem":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","permalink":"/grasp"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/java-blackjack/pull/427 \\n2\ub2e8\uacc4: https://github.com/woowacourse/java-blackjack/pull/537 \\n:::\\n\\n### \ube14\ub799\uc7ad\\n\\n\ube14\ub799\uc7ad \ubbf8\uc158\uc5d0\uc11c\ub294 \ud6c4\ucd94\uc640 \ud398\uc5b4(\uc870\ubbf8\ub8cc \ub4c0\uc624?)\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \uc2e4\uc218\ud558\uc9c0 \uc54a\uace0, \ubc14\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uc9c0 \uc54a\uace0 \uce5c\ud574\uc9c0\uae30 \ubd80\ud130 \uc2dc\uc791\ud588\ub2e4. \\n\\n\ube14\ub799\uc7ad\uc740 \uad6c\ud604\ud574\uc57c \ub420 \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud560 \uac83 \uac19\uc558\uc9c0\ub9cc \\n\ud6c4\ucd94\uc640 \ud568\uaed8 \uc804\ub7b5\uc801(\uc0bc\uc77c\uc808\uc5d0 \ubbf8\uc158 \uc774\uc57c\uae30 \ub098\ub204\uae30)\uc73c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud574 \uc2dc\uac04 \ub0b4\uc5d0 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\ubbf8\uc158\uc744 \ub05d\ub098\uace0 \ud68c\uace0\ub97c \ud588\uc744 \ub54c \ud6c4\ucd94\uac00 \uace0\ubbfc\uac70\ub9ac\ub97c \ud558\ub098 \ub0b4\uc92c\ub2e4. \\n\\"\ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \uc555\ubc15\uac10\uc744 \ub290\ub07c\ub294 \ud398\uc5b4\uac00 \uc788\ub2e4\uba74 \ud5c8\ube0c\uac00 \ud574\uc904 \uc218 \uc788\ub294\uac8c \ubb50\uac00 \uc788\uc744\uae4c?\\" \\n\\n\uacf0\uacf0\ud788 \uc0dd\uac01\ud574\ubd24\uc9c0\ub9cc \uc27d\uac8c \ub2f5\uc744 \ub0b4\ub9b4 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uc911\uac04 \uc911\uac04 \ud68c\uace0\ub97c \ud558\uace0, \ub098\uc758 \uc18c\ud504\ud2b8\uc2a4\ud0ac\uc744 \ub192\ud788\ub294\uac8c \ub2f5\uc77c\uae4c? \\n\ubd80\ub2f4\uac10\uc744 \ub290\ub07c\uc9c0 \uc54a\uace0 \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub420 \uc218 \uc788\ub3c4\ub85d \uacc4\uc18d \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4. \\n\\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc0dd\uac01\uc774 \ub9ce\uc544\uc838\uc11c \uc804 \ub9ac\ubdf0\uc5b4\uc778 \ud130\ud2c0\ud83d\udc22\uacfc\ub3c4 \ub300\ud654\ub97c \ub098\ub204\uc5c8\ub2e4. \\n\ud130\ud2c0\uc740 \uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84(\uad81\uadf9\uc801\uc778 \ubaa9\ud45c\uc778 \uc88b\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uac83)\uc5d0 \uc9d1\uc911\ud574\ubcf4\ub77c\uace0 \ud558\uc168\ub2e4. \\n\\n\uc88b\uc740 \ucf54\ub4dc, \uc88b\uc740 \ud398\uc5b4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc77c\ub2e8 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\ud398\uc5b4 \uc2e0\uacbd\uc4f0\uae30** \\n\uc774\ubc88 \ud398\uc5b4\ud560 \ub54c \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub0b4\ubcf4\ub3c4\ub85d \ud588\ub2e4. \uadf8\ub807\uae30\uc5d0 \ub108\ubb34 \uc758\uacac\uc744 \uac15\ud558\uac8c \ubc00\uc5b4\ubd99\uc778 \ub290\ub08c\uc774 \ub4e4\uc5b4\uc11c \ubbf8\uc548\ud588\ub2e4. \\n\ud6c4\ucd94\uac00 \uc555\ubc15\uc744 \ub290\uaf08\uc744 \uc218\ub3c4 \uc788\uc744 \uac83 \uac19\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\uc911\uac04 \uc911\uac04 \uc791\uc740 \ud68c\uace0\ub97c \uc9c4\ud589\ud574\ubcf4\ub294 \uac83\uc774 \uc88b\uc744\uae4c?\\n\\n**\uccb4\ub825 \uad00\ub9ac** \\n\uc694\uc998 \uc798 \ubabb\uba39\ub294 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c \uc0b4 \ub0a0\uc774 \ub9ce\uc740\ub370 \uc798 \ucc59\uaca8\uba39\uace0, \ud798\ub0b4\uc57c\uaca0\ub2e4.\\n\\n**\uc911\uac04 \uc911\uac04 \ub3cc\uc544\ubcf4\uae30** \\n\uc774\ubc88 \ubbf8\uc158\uacfc \uad00\ub828\ub41c \ub0b4\uc6a9\uc740 \uc544\ub2c8\uc9c0\ub9cc \uc6b0\ud14c\ucf54\ub97c \uc798 \ud65c\uc6a9 \ud558\uace0 \uc788\ub294\uc9c0 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4. \\n\ub0b4\uac00 \uc6b0\ud14c\ucf54\uc5d0 \uc9c0\uc6d0\ud55c \uc774\uc720\ub97c \ud56d\uc0c1 \uc78a\uc9c0 \uc54a\uc544\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uc0c1\ud0dc \ud328\ud134** \\n\uac1d\uccb4\uc758 \ub0b4\ubd80 \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc2a4\uc2a4\ub85c \ud589\ub3d9\uc744 \ubcc0\uacbd\ud558\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc73c\ub85c if/else/switch\uc640 \uac19\uc740 \uc870\uac74\ubb38\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\ube14\ub799\uc7ad \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc0c1\ud0dc \ud328\ud134\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ucc98\uc74c \uc801\uc6a9\ud574\ubcf4\uc558\ub2e4. \\n\ucc98\uc74c \uc801\uc6a9\ud558\uae30 \uc804\uc5d0\ub294 \ubcc4\ub85c\ub77c\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc0dd\uac01\ubcf4\ub2e4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4. \\n\\n**\uc77c\uad00\uc131, \uac00\ub3c5\uc131, \ucd94\uc0c1\ud654** \\n\uc774\ubc88 \ub9ac\ubdf0\uc5b4\ub294 \uac80\ud504\ud83c\udf6b \uc600\ub2e4! \\n\uac80\ud504\uc758 \ub9ac\ubdf0\ub294 \uac04\uacb0\ud568\uc5d0 \uad00\ub828\ub41c \ub0b4\uc6a9\uc774 \ub9ce\uc558\ub2e4. \\n\uc77c\uad00\uc131\uc774 \uc788\ub294 \ucf54\ub4dc, \uac00\ub3c5\uc131\uc774 \uc88b\uc740 \ucf54\ub4dc, \ucd94\uc0c1\ud654\uac00 \uc798 \ub418\uc5b4\uc788\ub294 \ucf54\ub4dc \\n\uc77d\uae30 \uc88b\uace0, \uac04\uacb0\ud55c \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b4 \uac83 \uac19\ub2e4. \\n\ucf54\ub4dc\ub97c \ubc14\ub77c\ubcf4\ub294 \uc2dc\uc810\uc774 \ud558\ub098 \ub298\uc5b4\ub09c \uae30\ubd84\uc774\ub2e4!(\uc55e\uc73c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc740 \ub098\uc758 \ubaab\uc774\uc9c0\ub9cc) \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uc0dd\uac01 \uc815\ub9ac** \\n\uc911\uac04 \uc911\uac04 \ud604\uc7ac \uc0c1\ud669\uc5d0 \ub300\ud574 \uadf8\ub9bc\uc744 \uadf8\ub9ac\uac70\ub098, \uae00\uc744 \uc801\uc73c\uba74\uc11c \uc815\ub9ac\ud55c\ub2e4. \\n\ud398\uc5b4\uc640 \ub3d9\uc77c\ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\n\uc9c4\ud589\ud558\ub294\ub370 \ub9e4\uc6b0 \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ub098\ub3c4 \ub2e4\uc74c \ud398\uc5b4\ub54c\ubd80\ud130 \ud39c\uc774\ub791 \uc885\uc774\ub97c \uc900\ube44\ud574\uc57c\uaca0\ub2e4.\\n\\n**\uac00\uac10\uc5c6\uc774 \uc758\uacac\uc744 \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84** \\n\uc9c4\ud589 \uc0c1\ud669\uc5d0 \ub300\ud55c \ubd80\ubd84, \uc9c4\ud589 \uc18d\ub3c4, \uc9c0\uae08 \uc790\uc2e0\uc774 \uc774\ud574\ud558\uace0 \uc788\ub294 \ubd80\ubd84\uc744 \ub9d0\ud574\uc918\uc11c \ud3b8\ud588\ub2e4. \\n\ud68c\uace0\ub54c\ub3c4 \uc11c\ub85c \uc194\uc9c1\ud558\uac8c \uc758\uacac\uc744 \uc8fc\uace0 \ubc1b\uc544\uc11c \uc88b\uc558\ub2e4. \\n\\n**\ub3c4\uba54\uc778 \uc5b8\uc5b4\uc5d0 \uc2e0\uacbd\uc4f0\ub294 \ubd80\ubd84** \\n\ud074\ub798\uc2a4\uba85, \ubcc0\uc218\uba85\uacfc \uac19\uc740 \uc5b8\uc5b4\ub97c \uc138\uc2ec\ud558\uac8c \uc2e0\uacbd\uc4f4\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d \uc815\ub9ac\ub3c4 \uae54\ub054\ud558\uac8c \uc798\ud558\ub294 \uac83 \uac19\ub2e4. \\n\\n\ud6c4\ucd94 \ucd5c\uace0 \ud83d\udc4d"},{"id":"grasp","metadata":{"permalink":"/grasp","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-30-GRASP.mdx","source":"@site/blog/2023-1/2023-03-30-GRASP.mdx","title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","description":"GRASP(General Responsibility Assignment Software Pattern)","date":"2023-03-30T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 30\uc77c","tags":[{"label":"GRASP","permalink":"/tags/grasp"},{"label":"OOP","permalink":"/tags/oop"}],"readingTime":8.085,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","slug":"grasp","tags":["GRASP","OOP"]},"unlisted":false,"prevItem":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","permalink":"/blackjack-retrospective"},"nextItem":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","permalink":"/chess-retrospective"}},"content":"### GRASP(General Responsibility Assignment Software Pattern)\\n\\n\ud06c\ub808\uc774\uadf8 \ub77c\ub9cc\uc758 Applying UML and Patterns\uc774\ub77c\ub294 \ucc45\uc5d0\uc11c \ub098\uc628 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134\\n\\n\uac01 \ud328\ud134\ub9c8\ub2e4 Solution\uacfc Problem\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub2e4.\\n\\n### \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)\\n\\nQ: \uac1d\uccb4\uc5d0 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uae30\ubcf8 \uc6d0\uce59\uc740 \ubb34\uc5c7\uc778\uac00?\\n\\nA: \ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub370 \ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \ud074\ub798\uc2a4(\uc815\ubcf4 \uc804\ubb38\uac00)\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4.\\n\\n\uc815\ubcf4\uc640 \ud589\ub3d9\uc744 \uac00\uae4c\uc6b4 \uacf3\uc5d0 \uc704\uce58\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \ucea1\uc290\ud654\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4.\\n\\n\ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \uac1d\uccb4\ub4e4\ub85c \ucc45\uc784\uc774 \ubd84\uc0b0\ub41c\ub2e4.\\n\\n### \ucc3d\uc870\uc790 \ud328\ud134(Creator)\\n\\nQ: \ub204\uac00 \uac1d\uccb4 A\ub97c \uc0dd\uc131\ud558\ub294\uac00?\\n\\nA: \ub2e4\uc74c\uc758 \uc870\uac74\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\uc871\ud558\ub294 \uac1d\uccb4\uc5d0\uac8c \uac1d\uccb4 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n- B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\uc758 \ucd08\uae30\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4.\\n\\n\uc0dd\uc131 \uc608\uc815\uc778 \uac1d\uccb4\uc640 \uc5f0\uad00\ub418\uc5b4 \uc788\ub294 \uac1d\uccb4\uac00 \uc0dd\uc131 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac8c \ub41c\ub2e4\uba74, \uc774\ubbf8 \ud574\ub2f9 \uac1d\uccb4\uc640 \uacb0\ud569\ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\uac8c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)\\n\\nQ: \uc758\uc874\uc131\uc744 \ub0ae\ucd94\uace0 \ubcc0\ud654\uc758 \uc601\ud5a5\uc744 \uc904\uc774\uba70 \uc7ac\uc0ac\uc6a9\uc131\uc744 \uc99d\uac00\uc2dc\ud0a4\ub294 \ubc29\ubc95\uc740?\\n\\nA: \uc804\uccb4\uc801\uc778 \uacb0\ud569\uc774 \ub0ae\uac8c \uc720\uc9c0\ub418\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n> \uacb0\ud569\ub3c4(Coupling)\\n\uac1d\uccb4 \uc0ac\uc774\uc758 \uc758\uc874\uc131\uc774 \uacfc\ud55c \uacbd\uc6b0 \uacb0\ud569\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4.\\n- \uc624\ube0c\uc81d\ud2b8 p.17\\n> \\n\\n\uacb0\ud569\ub3c4\ub97c \ub0ae\ucd98\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4.\\n\\n- \ub2e4\ub978 \uad6c\uc131 \uc694\uc18c\uc758 \ubcc0\ud654\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294\ub2e4.\\n- \uc7ac\uc0ac\uc6a9\uc774 \ud3b8\ub9ac\ud574\uc9c4\ub2e4.\\n- \ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\uc758\uc874\ud558\ub294 \ud074\ub798\uc2a4\uac00 \uc801\uae30 \ub54c\ubb38\uc5d0)\\n\\n### \ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)\\n\\nQ. \uac1d\uccb4\ub97c \uad00\ub9ac\ud558\uae30 \uc27d\uac8c \ud558\ub824\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub192\uc740 \uc751\uc9d1\ub3c4\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n> \uc751\uc9d1\ub3c4(Cohesion)\\n\uc5f0\uad00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc5f0\uad00\uc131 \uc5c6\ub294 \uc791\uc5c5\uc740 \ub2e4\ub978 \uac1d\uccb4\uc5d0\uac8c \uc704\uc784\ud558\ub294 \uac1d\uccb4\ub97c \uac00\ub9ac\ucf1c \uc751\uc9d1\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4.\\n- \uc624\ube0c\uc81d\ud2b8 p.26\\n> \\n\\n\ubcc0\uacbd\uc758 \uc774\uc720\uc5d0 \ub530\ub77c \ud074\ub798\uc2a4\ub97c \ubd84\ub9ac\ud55c\ub2e4\uba74 \uc751\uc9d1\ub3c4\ub97c \ub192\uc77c \uc218 \uc788\uace0, \uc751\uc9d1\ub3c4\uac00 \ub192\uc544\uc9c4\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4.\\n\\n- \ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\ud560\ub2f9\ub41c \ucc45\uc784\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0)\\n- \uc720\uc9c0\ubcf4\uc218\uac00 \uc26c\uc6cc\uc9c4\ub2e4.\\n- \ub0ae\uc740 \uacb0\ud569\ub3c4 \ub610\ud55c \uc9c0\uc6d0\ud55c\ub2e4.\\n- \uc751\uc9d1\ub3c4\uac00 \ub192\uc740 \ud074\ub798\uc2a4\ub294 \ud2b9\uc815\ud55c \ubaa9\uc801\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc7ac\uc0ac\uc6a9\ud558\uae30 \uc88b\ub2e4.\\n\\n### \ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)\\n\\nQ. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uac83\uc740 \ub204\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294\uac00?\\n\\nA. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 Controller \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n\\n\uc5b4\ub5a4 \uc11c\ube0c\uc2dc\uc2a4\ud15c\uc774 \uc874\uc7ac\ud55c\ub2e4\uace0 \uac00\uc815\ud560 \ub54c\\n\\n- \uc9c1\uc811\uc801\uc73c\ub85c \uac1d\uccb4\uc5d0 \uc811\uadfc\ud558\uc5ec \ud504\ub85c\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uacb0\ud569\ub3c4\uac00 \uc0c1\uc2b9\ud55c\ub2e4.\\n- \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc5d0 \ub4e4\uc5b4\uc624\ub294 \uc694\uccad\uc744 \ucc98\ub9ac\ud574\uc8fc\ub294 \ucee8\ud2b8\ub864\ub7ec\uac00 \uc788\ub2e4\uba74 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 \ud574\ub2f9 \ucee8\ud2b8\ub864\ub7ec\ub9cc \uc54c\uba74 \ub41c\ub2e4.\\n- \ub9cc\uc57d \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc758 \ubcc0\uacbd\uc774 \uc0dd\uacbc\uc744 \ub54c \uc678\ubd80\uc5d0 \ubbf8\uce58\ub294 \uc601\ud5a5\ub3c4 \uc904\uc5b4\ub4e0\ub2e4.\\n\\n### \ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)\\n\\nQ. \uac1d\uccb4\uc758 \ud0c0\uc785\uc5d0 \ub530\ub77c \ud589\ub3d9\uc774 \ubc14\ub010\ub2e4\uba74 \ucc45\uc784\uc744 \uc5b4\ub5bb\uac8c \ud560\ub2f9\ud574\uc57c \ud560\uae4c?\\n\\nA. OOP\uac00 \uc9c0\uc6d0\ud558\ub294 \ub2e4\ud615\uc131\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ud65c\uc6a9\ud55c\ub2e4. (\uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0 \ud589\ub3d9\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uad6c\ud604)\\n\\n\uac1d\uccb4\uc758 \uc885\ub958\uc5d0 \ub530\ub77c \ubd84\uae30\ud558\ub294 \uc870\uac74\ubb38\uc774 \uc544\ub2cc \ub2e4\ud615\uc131\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4.\\n\\n\uc0c8\ub85c\uc6b4 \ud0c0\uc785\uc774 \ucd94\uac00\ub418\uc5c8\uc744 \ub54c \uc870\uac74\ubb38\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uae30\uc874\uc758 \uc870\uac74\ubb38\uc744 \uc218\uc815\ud574\uc57c \ud558\uc9c0\ub9cc \ub2e4\ud615\uc131\uc744 \ud65c\uc6a9\ud558\uba74 \uc27d\uac8c \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\\n\\nQ. \uc5b4\ub5bb\uac8c \ud558\uba74 \ubcc0\uacbd\uc774 \ub2e4\ub978 \uc694\uc18c\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud560 \uc218 \uc788\uc744\uae4c?\\n\\nA. \ubcc0\ud654\uac00 \uc608\uc0c1\ub418\ub294 \uc9c0\uc810\uc744 \uc2dd\ubcc4\ud558\uace0, \uc8fc\uc704\uc5d0 \uc548\uc815\ub41c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud615\uc131\ud558\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n### \uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)\\n\\nQ. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud558\uace0 \uc2f6\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ub2e4\ub978 \uac1d\uccb4\ub97c \ub450\uc5b4 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc911\uc7ac\uc790 \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ud558\ub098\uc758 \uac1d\uccb4\ub97c \ucd94\uac00\ud558\uc5ec \ubcf5\uc7a1\ud55c \uad00\uacc4\ub97c \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc911\uac04\uc5d0 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub454\ub2e4\uba74 \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\uc5d0 \ud574\ub2f9\ub41c\ub2e4.\\n\\n### \uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)\\n\\nQ. \ucc45\uc784\uc744 \ud560\ub2f9\ud55c \ub3c4\uba54\uc778 \uac1d\uccb4\uac00 Low Coupling, High Cohesion, \uc7ac\uc0ac\uc6a9\uc131 \ub4f1\uc758 \ubaa9\uc801\uc744 \uc704\ubc18\ud55c\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub3c4\uba54\uc778 \uac1c\ub150\uc744 \ud3ec\ud568\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uace0 \ub9e4\uc6b0 \uc751\uc9d1\ub41c \ucc45\uc784\uc744 \ud560\ub2f9\ud560 \uc218 \uc788\ub2e4.\\n\\n\ud589\ub3d9\uc744 \ucd94\uac00\ud560 \ub54c, \ud574\ub2f9 \ucc45\uc784\uc744 \uc218\ud589\ud560 \ub3c4\uba54\uc778 \uac1c\ub150\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \ub3c4\uba54\uc778\uacfc \ubb34\uad00\ud55c \uc778\uacf5\uc801\uc778 \uac1d\uccb4\ub97c \ub9cc\ub4e0\ub2e4\uc74c \ud574\ub2f9 \uac1d\uccb4\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4.\\n\\n\uac1d\uccb4\uac00 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud574\uc57c \ud560 \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4\uace0, \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134\uc744 \uc801\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud558\ub77c\ub294 \ucc45\uc784\uc744 \uac00\uc9c0\ub77c\uace0 \ud558\uc9c0 \uc54a\ub294\ub2e4.\\n\\n\uc608) \uc0c1\uc810\uacfc \uace0\uac1d \ud074\ub798\uc2a4\uac00 \uc788\uace0 \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uace0 \uac00\uc815\\n\\n- \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 \uac70\ub798\ub97c \ud558\ub824\uba74 \ud658\uc804\uc744 \ud574\uc57c\ud55c\ub2e4.\\n- \ub450 \ud074\ub798\uc2a4 \ub2e4 \ud658\uc804\uc5d0 \ub300\ud55c \ucc45\uc784\uc744 \ubd80\uc5ec\ud558\uae30 \uc560\ub9e4\ud558\ub2e4\uba74 \ud658\uc804\uc744 \ucc45\uc784\ud558\ub294 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud558\uace0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc624\ube0c\uc81d\ud2b8 5\uc7a5. \ucc45\uc784 \ud560\ub2f9\ud558\uae30, [\uc870\uc601\ud638](http://aeternum.egloos.com/)\\n\\nApplying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman\\n\\n[GRASP, \ud55c\ube5b \ub124\ud2b8\uc6cc\ud06c](https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS8586826397)"},{"id":"chess-retrospective","metadata":{"permalink":"/chess-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","description":"1, 2\ub2e8\uacc4//github.com/woowacourse/java-chess/pull/441","date":"2023-03-31T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 31\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.705,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","slug":"chess-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","permalink":"/grasp"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","permalink":"/woowacourse-level1-retrospective"}},"content":":::note PR \ub9c1\ud06c \\n1, 2\ub2e8\uacc4: https://github.com/woowacourse/java-chess/pull/441 \\n3, 4\ub2e8\uacc4: https://github.com/woowacourse/java-chess/pull/529 \\n:::\\n\\n### \uccb4\uc2a4\\n\uccb4\uc2a4 \ubbf8\uc158\uc5d0\ub294 \uac00\ube44\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4! \\n\uccb4\uc2a4\ub294 \uc774\uc804 \ubbf8\uc158\ub4e4\ubcf4\ub2e4 \ud6e8\uc52c \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778\uc774\uc5c8\ub2e4. \\n\ud558\uc9c0\ub9cc \uac00\ube44\uc640 \ub098\ub294 \uccb4\uc2a4 \ub3c4\uba54\uc778\uc774 \uc775\uc219\ud574\uc11c \ub354 \ud3b8\ud55c \ub9c8\uc74c\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc5b4\ub824\uc6e0\ub358 \ubd80\ubd84\uc740 \uae30\ubb3c\uc758 \uc774\ub3d9, \uc774\ub3d9\uc2dc \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4. \\n \\n\uac00\ube44\uac00 \uc9d1\uc5d0\uac00\uc11c\ub3c4 \uae30\ubb3c\uc758 \uc774\ub3d9 \uad00\ub828\ud574 \uc0dd\uac01 \uc815\ub9ac\ud55c \uae00\uc744 \ubcf4\ub0b4\uc918\uc11c \ub354\uc6b1 \ube68\ub9ac \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ucd5c\uc885\uc801\uc73c\ub85c \uacb0\uc815\ud55c \ubd80\ubd84\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n**\uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5\uc5ec\ubd80** \\nRank\uc640 File\uc740 \uac01\uac01 \uc704\uce58\uac12\uc744 \uac00\uc9c0\uace0 \uc788\uace0, \uac12\uc758 \ucc28\uc774\ub97c \uc774\uc6a9\ud574\uc11c \uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uacc4\uc0b0\ud588\ub2e4. \\n\uc9c1\uc120 \u2192 Rank\uc640 File \ucc28\uc774 \uc911 \ud558\ub098\uac00 0\uc774\uc5b4\uc57c \ud55c\ub2e4. \\n\ub300\uac01\uc120 \u2192 Rank\uc640 File \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \uac19\uc544\uc57c \ud55c\ub2e4. ex) abs(-2) == abs(2) \\n\ub098\uc774\ud2b8 \u2192 \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \ud558\ub098\ub294 2 \ub098\uba38\uc9c0 \ud558\ub098\ub294 1\uc774\uc5b4\uc57c \ud55c\ub2e4.\\n\\n**\ub3c4\ucc29 \uce78\uc758 \uae30\ubb3c \uc5ec\ubd80** \\n\uc544\uad70 \u2192 \uc774\ub3d9\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc801\uad70 \u2192 \uc774\ub3d9\uc774 \uac00\ub2a5\ud558\ub2e4. \uc801\uad70\uc744 \uc7a1\ub294\ub2e4. \\n\\n**\uc911\uac04\uc5d0 \uae30\ubb3c \uc874\uc7ac \uc5ec\ubd80** \\n\uc774\ub3d9 \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\uba74 \uc548\ub41c\ub2e4. \\n\\n**\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9** \\n\uccb4\uc2a4 \ubbf8\uc158\uc740 \ud2b9\ubcc4\ud558\uac8c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc5f0\uacb0\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5c8\ub2e4. \\n\uccb4\uc2a4 \uac8c\uc784\uc758 \uc0c1\ud0dc\ub97c \ub2e4\uc74c\uc758 \ub450\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uc815\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n- \uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95 \\n- \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\uace0 \uac8c\uc784\uc744 \ubd88\ub7ec\uc640 \uae30\ubcf4\ub300\ub85c \uc774\ub3d9\uc2dc\ud0a4\ub294 \ubc29\ubc95 \\n\\n\uae30\ubb3c\uc774 \uc774\ub3d9\ud560 \ub54c\ub9c8\ub2e4 \uac12\uc744 \uc800\uc7a5\ud558\uace0 \uc2f6\uc5c8\uace0, \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud588\ub2e4. \\n\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc774\uc720\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n- \ud134\uacfc \uac19\uc740 \ubd80\uac00\uc801\uc778 \uc694\uc18c\ub97c \uc800\uc7a5\ud574\uc57c \ud55c\ub2e4. \\n- \uc774\ub3d9\uc744 \ud560 \ub54c \uae30\ubb3c\uc774 \uc7a1\ud788\ub294 \uacbd\uc6b0 update \ucffc\ub9ac(\uc774\ub3d9 \uae30\ubb3c)\uc640 delete(\uc7a1\ud78c \uae30\ubb3c) 2\uac1c\uc758 \ucffc\ub9ac\ub97c \ub0a0\ub824\uc57c \ud55c\ub2e4. \\n- \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ub3c4\uba54\uc778\uc758 \ubcc0\uacbd\uc774 \ud06c\uac8c(\ucd08\uae30 \uc0c1\ud0dc\ub97c \uad6c\uc131\ud558\ub294 \ubd80\ubd84) \uc77c\uc5b4\ub098\uc57c \ud55c\ub2e4. \\n\\n\uc815\ub9ac\ud558\uc790\uba74 \uae30\ubb3c \uc804\uccb4 \uc800\uc7a5\uacfc \uae30\ubcf4 \uc800\uc7a5\uc740 \ub2e4\uc74c\uacfc \ucc28\uc774\uac00 \uc788\ub2e4. \\n\ubcf4\ub4dc\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc\uc5d0\uc11c 32\uac1c\uc758 Insert \ucffc\ub9ac(\uae30\ubb3c\uc758 \uc704\uce58) + \uae30\ubb3c \uc774\ub3d9 \uc2dc \uc6c0\uc9c1\uc784 \ubcc0\uacbd(\uc7a1\ud788\ub294 \uacbd\uc6b0 2\uac1c\uc758 \ucffc\ub9ac) \\n\uae30\ubcf4\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uad6c\uc131 + \uc800\uc7a5\ub41c \uae30\ubcf4\ub97c select \ucffc\ub9ac\ub85c \uc870\ud68c\ud574\uc11c \uc0ac\uc6a9(1\ud68c) + insert \ucffc\ub9ac(\uc774\ub3d9 \ub2f9 1\ud68c)\\n\\n\ucd94\uac00\ub85c \uae30\ubcf4\uc800\uc7a5\uc774 \uad6c\ud604\ub3c4 \ub354\uc6b1 \uac04\ub2e8\ud558\ub2e4. \ud83d\udc4d \\n\\n**\ubd80\uac00\uc801\uc778 \ubd80\ubd84**\\n\\n\ub9ac\ubdf0\uc5b4\uc778 \ucc30\ub9ac\ud83c\udf6b\uac00 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uac8c\uc784\uc774 \uc9c4\ud589\ub41c\ub2e4\uba74 \uc5b4\ub5a8\uc9c0? \uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ub2e4\uc591\ud55c \uc2dc\ub3c4\ub97c \ud574\ubd24\ub2e4. \\n- \ub204\ub204\uc758 \ub3c4\uc6c0\uc73c\ub85c ConnectionPool \uad6c\ud604 \\n- ThreadLocal \uc0ac\uc6a9\ud574\uc11c \uc4f0\ub808\ub4dc \ubcc4 \uc138\uc158 \uad00\ub9ac \\n- \uc2e4\uc81c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub0b4\uc5d0\uc11c \uccb4\uc2a4 \uac8c\uc784\uc774 \uc9c4\ud589\ub418\ub294 Board\ub97c ConcurrentHashMap\uc73c\ub85c \uc800\uc7a5(\uc0ac\uc2e4 \uc774 \ubd80\ubd84\uc740 \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ud544\uc694\uc5c6\uc9c0\ub9cc 2\uba85\uc774 \uc11c\ub85c \uac8c\uc784\ud558\ub294 \uacbd\uc6b0\ub97c \uc0dd\uac01\ud574\uc11c \ub123\uc5b4\ubcf4\uc558\ub2e4.) \\n\\n\ub450 \uba85\uc774 \uc11c\ub85c \uac19\uc740 \ubc29\uc5d0 \uc785\uc7a5\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4\uba74 \ucd9c\ub825\ud558\ub294 \ubd80\ubd84\uc774 \uae4c\ub2e4\ub85c\uc6cc\uc9c8 \uac83 \uac19\ub2e4\uace0 \uc608\uc0c1\ub418\uc5b4(Board\uc5d0 \uc635\uc800\ubc84 \ud328\ud134\uc744 \uc0ac\uc6a9\ud574\uc57c\ub418\ub098?) \ud574\ubcfc \uc5c4\ub450\uac00 \ub098\uc9c0 \uc54a\uc558\ub2e4. \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc9c0 \ubabb\ud55c \ubd80\ubd84** \\nDB \uad00\ub828 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0\ub9cc \uc9d1\uc911\ud558\ub2e4\ubcf4\ub2c8 \uc815\uc801 \uc911\uc694\ud55c DB\uc758 \ucf54\ub4dc\uc758 \uc608\uc678\ucc98\ub9ac, \ube48 \uac12\uc744 \ubc18\ud658 \ud558\ub294 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucc98\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \ucc30\ub9ac\uc758 \uaf3c\uaf3c\ud55c \ub9ac\ubdf0\ub85c DB\ubd80\ubd84\uacfc \ub098\ub9cc\uc758 JdbcTemplate\uc744 \uae54\ub054\ud558\uac8c \uad6c\ud604\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n**\uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ub2f4\uac10** \\n\ucd08\ubc18\uc5d0\ub294 \uc5ec\uc720\ub86d\uc9c0\ub9cc \uc81c\ucd9c \ub9c8\uac10\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \uc218\ub85d \uc0ac\ub78c\uc774 \uae09\ud574\uc9c0\ub294 \uac83 \uac19\ub2e4. \\n\ub2e4\uc74c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\ud560 \ub550 \uc18d\ub3c4\ub97c \uc870\uc808\ud558\uace0, \ub9c8\uc74c\uc5d0 \uc5ec\uc720\ub97c \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**DAO \uc911\ubcf5 \uc81c\uac70**\\n\\n\ud504\ub864\ub85c\uadf8\uc5d0 [\uae00](https://prolog.techcourse.co.kr/studylogs/2947)\uc744 \uc791\uc131\ud588\ub2e4. \\nDAO\ub97c \uc791\uc131\ud558\ub294\ub370 try-catch-resources\uc640 \uc5ec\ub7ec \ucf54\ub4dc\uac00 \uc911\ubcf5\ub418\uc11c \uc81c\uac70\ud558\uace0\uc2f6\uc5c8\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc73c\ub85c \uae54\ub054\ud558\uac8c \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\udc4d\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\ud398\uc5b4 \uc0dd\uac01\ud558\uae30** \\n\uac00\ube44\ub294 \ub204\uad6c\ubcf4\ub2e4 \ud398\uc5b4\ub97c \uc0dd\uac01\ud558\uace0, \ubc30\ub824\ud574\uc8fc\ub294 \ud398\uc5b4\uc600\ub2e4. \\n\uc911\uac04 \uc911\uac04 \ub2f9 \ub5a8\uc5b4\uc9c8\uae4c\ubd10 \uac71\uc815\ub3c4 \ud574\uc8fc\uace0, \ub098\uc758 \ucee8\ub514\uc158\ub3c4 \ud655\uc778\ud574\uc92c\ub2e4! \\n\\n**\ubbf8\uc158 \ubab0\uc785\ud558\uae30** \\n\ucd5c\uadfc\uc5d0 \ubbf8\uc158\uc5d0 \uc798 \ubab0\uc785\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\uac00\ube44\ub294 \ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \ubbf8\uc158\uc5d0 \ub300\ud55c \ubab0\uc785\ub3c4\uac00 \ub9e4\uc6b0 \uc88b\uc558\ub2e4. \\n\uc9d1\uc5d0\uac00\uc11c\ub3c4 \uccb4\uc2a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ub85c\uc9c1\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560 \uc9c0 \uc0dd\uac01\ud55c \ub4a4 \uaf3c\uaf3c\ud574\uc11c \uc815\ub9ac\ud574\uc11c \ub098\uc5d0\uac8c \ubcf4\ub0b4\uc8fc\uc5c8\ub2e4. \\n\ub355\ubd84\uc5d0 \ub098\ub3c4 \uac00\ube44\uc758 \uc0dd\uac01\uc744 \uc54c \uc218 \uc788\uc5b4\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294\ub370 \uac00\uc18d\ub3c4\uac00 \ubd99\uc740 \uac83 \uac19\ub2e4. \\n\ub610\ud55c \ubbf8\uc158\uc744 \uc798 \ub9c8\ubb34\ub9ac\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\uc774 \uc804\ub2ec\ub418\uc11c \uadf8\ub7f0\uc9c0 \ub098\ub3c4 \ub369\ub2ec\uc544 \uc5f4\uc2ec\ud788 \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\ude04 \\n\\n**\uc194\uc9c1\ud568** \\n\uba3c\uc800 \ud68c\uace0\ud558\uc790\uace0 \ub9d0 \uac78\uc5b4\uc918\uc11c \uc815\ub9d0 \uace0\ub9c8\uc6e0\ub2e4\uace0 \ud45c\ud604\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\ubaa8\ub974\ub294\uac8c \uc788\uc73c\uba74 \uc194\uc9c1\ud558\uac8c \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\ub098\uc758 \uc758\uacac\uc744 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud55c \uc0c1\ud0dc\ub85c \uc804\ub2ec\ud560 \ub54c \uc774\ud574\uac00 \uc548\ub418\uc5c8\ub2e4\uace0 \uc815\ud655\ud788 \uc804\ub2ec\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\uc194\uc9c1\ud568\uc740 \ud398\uc5b4\ud560 \ub54c \uc911\uc694\ud55c \ubd80\ubd84\uc778 \uac83 \uac19\ub2e4. \\n\\n\ub9c8\uc9c0\ub9c9\uc73c\ub85c \ucc30\ub9ac\ud83c\udf6b \uccb4\uc2a4 \ubbf8\uc158\ub54c \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0 \ub0a8\uaca8\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4!"},{"id":"woowacourse-level1-retrospective","metadata":{"permalink":"/woowacourse-level1-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","description":"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.","date":"2023-04-01T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 1\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.48,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","slug":"woowacourse-level1-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","permalink":"/chess-retrospective"},"nextItem":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","permalink":"/custom-jdbc-template"}},"content":"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4. \\n\uc6b0\ud14c\ucf54\ub97c \uc2dc\uc791\ud558\uae30 \uc804 \ub0b4\uac00 \uc815\ud574\ub450\uc5c8\ub358 \ubaa9\ud45c \uc774\uc0c1\uc73c\ub85c \ub2ec\uc131\ud588\uae30 \ub54c\ubb38\uc5d0 \ub9e4\uc6b0 \ub9cc\uc871\uc2a4\ub7fd\ub2e4. \\n\ud63c\uc790 \ub3c5\ud559\uc744 \ud560 \ub550 \uc774 \ubc29\ud5a5\uc73c\ub85c \uacf5\ubd80\ud558\ub294 \uac8c \ub9de\ub294\uc9c0 \uacc4\uc18d \ubc18\ucd94\ud558\ub2e4 \uacb0\uad6d \ubb34\uae30\ub825\ud568\uc5d0 \ube60\uc838\ub4e4\uc5c8\ub2e4. \\n\ud558\uc9c0\ub9cc \uc774\uc81c\ub294 \uac19\uc774 \uacf5\ubd80\ud560 \uc0ac\ub78c\ub3c4 \uc788\uace0, \uc774\uc57c\uae30\ud560 \uc0ac\ub78c\ub3c4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc990\uae30\ub294 \uc77c\ub9cc \ub0a8\uc740 \uac83 \uac19\ub2e4. \\n\\n### Keep\\n\\n**\ub098\ub9cc\uc758 \ub8e8\ud2f4 \ub9cc\ub4e4\uae30** \\n\\n\uc2a4\uc2a4\ub85c\uac00 \uc678\ubd80\uc758 \uc601\ud5a5\uc744 \ub9ce\uc774 \ubc1b\ub294\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ucd5c\ub300\ud55c \uafb8\uc900\ud788 \ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n\ub9e4\uc77c 8\uc2dc\uc5d0 \ub3c4\ucc29\ud558\uc5ec \uc544\uce68\uc5d0 \ud574\uc57c \ud560 \uc77c\uc744 \uc815\ub9ac\ud558\uac70\ub098, \uc6b0\uc120\uc21c\uc704\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud558\uace0 \\n\uc18c\ud654\ub2a5\ub825\uc774 \ubd80\uc871\ud558\uae30 \ub54c\ubb38\uc5d0 \uc810\uc2ec\uc740 \ub3c4\uc2dc\ub77d(\uadf8\ub798\ubd24\uc790 \uacc4\ub7802\uac1c)\uc744 \uc900\ube44\ud558\uace0 \\n\ud56d\uc0c1 \ub611\uac19\uc740 \ucee8\ub514\uc158\uc744 \uc720\uc9c0\ud558\uae30 \uc704\ud574 \ud56d\uc0c1 6\uc2dc\uc5d0 \uc9d1\uc5d0 \uac04\ub2e4. \\n\uc774\uc81c \ubc14\ube60\uc9c8 \ud14c\ub2c8 \uc77c\ucc0d \uc9d1\uc5d0 \uac00\ub294 \uc77c\uc740 \uc5b4\uca54 \uc218 \uc5c6\uc774 \uc904\uc5b4\ub4e4\uaca0\uc9c0\ub9cc\ud83d\ude22 \\n\\n\uc120\ud0dd\ub3c4 \ube44\uc6a9\uc774\ub2e4. \uc55e\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\uc774 \ud544\uc694 \uc5c6\ub294 \ubd80\ubd84\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\ub4e4\uc5b4\uc57c\uaca0\ub2e4. \\n\\n**\ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uae30** \\n\\n10\uba85 \uc815\ub3c4\uc758 \ud06c\ub8e8\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b0\uace0 \uce5c\ud558\uac8c \uc9c0\ub0b8\ub2e4\uba74 \uc131\uacf5\uc801\uc774\ub77c\uace0 \uc0dd\uac01\ud588\uc5c8\ub2e4. \\n\ud558\ub2e4 \ubcf4\ub2c8 \ub354 \ub9ce\uc740 \ud06c\ub8e8\ub4e4\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b4 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c\ub3c4 \ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uace0 \uc544\ubb34 \ub54c\ub098 \ub9d0\uc744 \uac78 \uc218 \uc788\ub294 \ud06c\ub8e8\uac00 \ub298\uc5b4\ub098\uae38 :) \\n\\n**\uae00\uc4f0\uae30** \\n\\n\uae00\uc744 \uc798 \uc4f0\ub294 \ud3b8\uc740 \uc544\ub2c8\uc9c0\ub9cc \uafb8\uc900\ud788 \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ub9e4 \ubbf8\uc158\ub9c8\ub2e4 \ud68c\uace0\ub97c \uc791\uc131\ud558\ub2c8 \uc0dd\uac01\ub3c4 \uc815\ub9ac\ub418\uace0 \uac1c\uc120\uc810\ub3c4 \ucc3e\uc744 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\ub2e4. \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc5d0\ub294 \ub808\ubca8\ub9c8\ub2e4 \uae00\uc4f0\uae30\ub97c \uc9c4\ud589\ud558\ub294\ub370, \uc6b4\uc774 \uc88b\uac8c \uae00\uc4f0\uae30 \uc0c1\uc744 \ubc1b\uc558\ub2e4. \\n\uc0ac\uc2e4 \uac89\uc73c\ub85c \ub4dc\ub7ec\ub0b4\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uaf2d \ubc1b\uc544\ubcf4\uace0 \uc2f6\uc5c8\ub2e4. \\n\uae00\uc4f0\uae30 \uc870\uc6d0, \ud22c\ud45c\ud574 \uc900 \ud06c\ub8e8\ub4e4\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4. \\n\\n**\ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514** \\n\\n\ub204\ub204, \uc8fc\ub178, \ub2e4\uc990, \ub9d0\ub791, \ubc15\uc2a4\ud130, \uc624\uc789, \uae43\uc9f1\uc640 \ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\uacfc\uc5f0 \ub3c4\uc6c0\uc774 \ub420\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud558\uba74\uc11c \uc131\uc7a5\uc744 \ub9ce\uc774 \ud55c \uac83 \uac19\ub2e4. \\n\ud22c\uc790\ud55c \uc2dc\uac04 \ub300\ube44 \uac00\uc131\ube44\uac00 \uc88b\uc740 \ud65c\ub3d9\uc774\uc5c8\ub2e4. \\n\ub204\ub204\uac00 \uc2a4\ud130\ub514\uc7a5\uc778\ub370 \uacfc\uc5f0 \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00\ub824\ub098? \\n\\n**\ub808\ubca8 \uc778\ud130\ubdf0**\\n\\n\uc778\ud130\ubdf0\ud560 \ub54c \ub9ce\uc774 \ub5a8\uc9c0 \uc54a\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ub0a8\ub4e4 \uc55e\uc5d0\uc11c \uc774\uc57c\uae30\ub97c \ud558\uac70\ub098, \uba74\uc811\uc744 \ubcf4\uba74 \ud56d\uc0c1 \uc5c4\uccad \ub5a8\uc5b4\uc11c \uac71\uc815\ud588\ub294\ub370 \\n\uae30\uc220\uc801\uc778 \uc9c8\ubb38\uc744 \ubc1b\uc558\uc744 \ub54c \ub5a8\uc9c0 \uc54a\uace0 \uc798 \ub300\ub2f5\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \ub2e4\ub978 \ud06c\ub8e8\uac00 \uc9c8\ubb38\ud588\uc744 \ub54c, \ucd5c\ub300\ud55c \uc774\ud574\ud558\uae30 \uc27d\uac8c \uc124\uba85\ud558\ub824\uace0 \ud588\ub358 \uacbd\ud5d8\uc774 \ub3c4\uc6c0\uc774 \ub41c \uac83 \uac19\ub2e4. \\n\uc774\ud6c4 \ub808\ubca8 \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\ub2e4. \\n- \ub300\ub2f5\ud558\uba74\uc11c \uc9c8\ubb38\uc744 \uacc4\uc18d \uc0dd\uac01\ud558\uba70 \uc78a\uc5b4\ubc84\ub9ac\uc9c0 \ub9d0\uae30 \\n- \ub450\uad04\uc2dd \ud45c\ud604\\n- \uc124\uba85\ud558\ub2e4\uac00 \uc798\ubabb \uc124\uba85\ud55c \uac83 \uac19\uc73c\uba74 \ub2e4 \ub04a\uace0 \ub2e4\uc2dc \uc774\uc57c\uae30\ud574\ub3c4 \ub420\uc9c0 \ubb3c\uc5b4\ubcf4\uae30 \\n- \uc124\uba85\ud560 \uc218 \uc788\uc744\ub9cc\ud07c \uc2dc\uac04 \ucda9\ubd84\ud788 \uac00\uc9c0\uae30\\n- \uc778\ud130\ubdf0\uc5b4\uc758 \uc9c8\ubb38 \uc758\ub3c4\ub97c \uba85\ud655\ud788 \uc774\ud574\ud558\uc9c0 \ubabb\ud588\ub2e4\uba74 \uc758\ub3c4 \ub2e4\uc2dc \ubb3c\uc5b4\ubcf4\uae30\\n- \ub05d\ub9fa\ub294 \ubd80\ubd84 \uc5f0\uc2b5\ud558\uae30(\uc790\uc2e0\uac10 \uc788\uac8c)\\n- \uae30\uc220\uc801\uc778 \uc9d1\ucc29\uac00\uc9c0\uae30\\n- \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud788 \uc900\ube44\ud588\uc73c\uba74 \ud611\uc5c5 \uad00\ub828 \uc9c8\ubb38\ub3c4 \uc900\ube44\ud558\uae30\\n\\n### Problem\\n\\n**\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d** \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ud65c\ub3d9 \uc911 \ud558\ub098\ub77c\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ud398\uc5b4\ub294 \ub9e4\ubc88 \ubc14\ub00c\uace0, \ubbf8\uc158\uc758 \ubcf5\uc7a1\ub3c4\ub3c4 \uc99d\uac00\ud558\uae30 \ub54c\ubb38\uc778 \uac83 \uac19\ub2e4. \\n\uc18c\ud1b5 \ub2a5\ub825, \uc2dc\uac04\uad00\ub9ac\uac00 \ubd80\uc871\ud588\uace0, \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\uc558\ub2e4. \\n\ud558\uc9c0\ub9cc \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uace0, \ud68c\uace0\ub97c \ud558\ub2e4 \ubcf4\ub2c8 \ub098\ub9cc\uc758 \ub178\ud558\uc6b0\uac00 \uc313\uc774\ub294 \ub290\ub08c\uc774\ub2e4. \\n\ub808\ubca8 2\uc5d0\uc11c\ub294 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc120\ud558\uc5ec \ud568\uaed8\ud558\uace0 \uc2f6\uc740 \ud398\uc5b4\uac00 \ub418\uace0 \uc2f6\ub2e4. \\n\\n**\uc9d1\uc911\ud558\ub294 \uc2dc\uac04\u23f1\ufe0f \ubd80\uc871** \\n\\n\ub808\ubca8 1\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc9d1\uc911\ud558\ub294 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4. \\n\uc774\ub978 \uc544\uce68\uacfc \uc624\ud6c4\uc5d0 \uac1c\uc778\uc801\uc73c\ub85c \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \uacf5\uac04\uc744 \uc608\uc57d\ud574\uc11c \uc628\uc804\ud788 \ub098\ub9cc\uc758 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### Try\\n\\n**\ud5c8\ube0c\ud83c\udf3f\uc640\uc758 \ud2f0\ud0c0\uc784?** \\n\\n\uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc744 \ub298\ub9b4 \ubc29\ubc95\uc744 \uc0dd\uac01\ud558\ub2e4\uac00 \ub300\ud654\ub97c \ub098\ub204\uc9c0 \ubabb\ud55c \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \uae5c\uc9dd \ucee4\ud53c\ucc57\uc744 \ud558\uba74 \uc5b4\ub5a8\uae4c \uc0dd\uac01\ud588\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 \uc7a1\ub2f4\ubc29\uc5d0 `\uc800\uc640 \ucee4\ud53c\ucc57 \ud558\uc2e4 \ubd84 :)` \ud558\uba74\uc11c \uc62c\ub9b4 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ucc38\uc5ec\ud558\ub294 \uc0ac\ub78c\uc774 \uc788\uc744\uc9c0, \uc548 \uc88b\uac8c \ubcf4\ub294 \uac8c \uc544\ub2d0\uc9c0 \uac71\uc815\ub418\uc9c0\ub9cc \uadf8\ub798\ub3c4 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4. \\n\uc800\ub791 \ud5c8\ube0c\ud2f0 \ud55c\uc794 \ud558\uc2e4\ub798\uc694? \\n\\n**\uae30\uc220\uc801\uc778 \ubd80\ubd84** \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0 \uc870\uae08 \ub354 \ubb34\uac8c\ub97c \ub450\ub2e4 \ubcf4\ub2c8 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc774 \ubd80\uc871\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc2dc\uac04\uc758 \uc5ec\uc720\uac00 \ub420 \ub54c \ucc45\uc744 \uc870\uae08\uc529 \uc77d\uc5b4\uc57c\uaca0\ub2e4. \\n\ube14\ub85c\uadf8\uc5d0 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \ub9ce\uc774 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\ub294 \uc2dc\uac04\ub3c4 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### \ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70 \\n\\n\uc2dc\uac04\uc774 \ube60\ub974\uac8c \ud758\ub7ec\uac14\ub2e4. \\n\ud0c0\uc778\uc5d0\uac8c \uc88b\uc740 \uc601\ud5a5\uc744 \uc8fc\uae30\uc704\ud574, \ubc29\ud559\ub3d9\uc548 \ub098\ub97c \ucc59\uae30\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\ub610\ud55c \ud568\uaed8 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc744 \ubaa9\ud45c\ub85c \uc55e\uc73c\ub85c\ub3c4 \uafb8\uc900\ud788 \uc758\uc2dd\uc801 \ub178\ub825\uc744 \ud574\uc57c\uaca0\ub2e4."},{"id":"custom-jdbc-template","metadata":{"permalink":"/custom-jdbc-template","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx","source":"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx","title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","description":"\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.","date":"2023-04-02T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 2\uc77c","tags":[{"label":"JDBC","permalink":"/tags/jdbc"},{"label":"Java","permalink":"/tags/java"}],"readingTime":9.025,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","slug":"custom-jdbc-template","tags":["JDBC","Java"]},"unlisted":false,"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","permalink":"/woowacourse-level1-retrospective"},"nextItem":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","permalink":"/java-class-file"}},"content":"import Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\uc774 \ub54c JDBC\ub97c \uc0ac\uc6a9\ud560 \ub54c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ucee4\ub125\uc158\uc744 \uc5bb\uace0, try-with-resource\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc774 \ubc18\ubcf5\ub418\uc5c8\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc774\uc6a9\ud558\uc5ec \ub098\ub9cc\uc758 JdbcTemplate\uc744 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4. \\n\\n### \uae30\uc874 \ucf54\ub4dc\\n\\n\\n\\n\\n```java\\npublic class User {\\n private final int id;\\n private final String name;\\n\\n public User(final int id, final String name) {\\n this.id = id;\\n this.name = name;\\n }\\n\\n public int getId() {\\n return id;\\n }\\n\\n public String getName() {\\n return name;\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic class UserDao {\\n private final ConnectionPool connectionPool;\\n\\n public UserDao(final ConnectionPool connectionPool) {\\n this.connectionPool = connectionPool;\\n }\\n\\n public void insert(final String name) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setString(1, name);\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public void delete(final int userId) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"DELETE FROM user WHERE id = ?\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setInt(1, userId);\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public User findById(final int userId) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setInt(1, userId);\\n final ResultSet resultSet = preparedStatement.executeQuery();\\n if (resultSet.next()) {\\n return new User(\\n resultSet.getInt(\\"id\\"),\\n resultSet.getString(\\"name\\")\\n );\\n }\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n return null;\\n }\\n\\n public List findAll() {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"SELECT * FROM user\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n final ResultSet resultSet = preparedStatement.executeQuery();\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(new User(\\n resultSet.getInt(\\"id\\"),\\n resultSet.getString(\\"name\\")\\n ));\\n }\\n return result;\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic class ConnectionPool {\\n private static final String SERVER = \\"localhost:13306\\";\\n private static final String DATABASE = \\"chess\\";\\n private static final String OPTION = \\"?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true\\";\\n private static final String URL = \\"jdbc:mysql://\\" + SERVER + \\"/\\" + DATABASE + OPTION;\\n private static final String USERNAME = \\"root\\";\\n private static final String PASSWORD = \\"root\\";\\n\\n private final AtomicInteger index = new AtomicInteger();\\n private final List connections;\\n\\n public ConnectionPool(final int connectionCount) {\\n connections = generateConnections(connectionCount);\\n }\\n\\n private List generateConnections(final int connectionCount) {\\n return Stream.generate(this::generateConnection)\\n .limit(connectionCount)\\n .collect(toList());\\n }\\n\\n private Connection generateConnection() {\\n try {\\n return DriverManager.getConnection(URL, USERNAME, PASSWORD);\\n } catch (SQLException e) {\\n throw new IllegalStateException(\\"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\");\\n }\\n }\\n\\n public Connection getConnection() {\\n int currentIndex = index.getAndIncrement();\\n return connections.get(currentIndex % connections.size());\\n }\\n}\\n```\\n\\n\\n\\n\\n### SELECT, DELETE \uc911\ubcf5 \uc81c\uac70\\n\\n\ubcc0\ud558\uc9c0 \uc54a\ub294 \ubd80\ubd84: try-with-resource, preparedStatement\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84, executeUpdate\ub85c \uc2e4\ud589 \ub4f1\ub4f1 \\n\ubcc0\ud558\ub294 \ubd80\ubd84: SQL Query, \ub9e4\uac1c\ubcc0\uc218 \\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\ub294 \ubd80\ubd84\uc744 \ubd84\ub9ac\ud558\uace0 \uac00\ubcc0\uc778\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 SELECT\uc640 DELETE\uc758 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\\n```java\\npublic void insert(final String name) {\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n executeUpdate(query, name);\\n}\\n\\npublic void delete(final int userId) {\\n final String query = \\"DELETE FROM user WHERE user_id = ?\\";\\n executeUpdate(query, userId);\\n}\\n\\nprivate void executeUpdate(final String query, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758\\n\\n\uc870\ud68c\ub294 INSERT, DELETE\uc640 \ub2ec\ub9ac \uac12\uc744 \ubc18\ud658\ubc1b\uc544\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0 \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. \\n\uc774 \ub54c \ucf5c\ubc31\uc774\ub77c\ub294 \uac83\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \ucf5c\ubc31(Callback)\\n\\n\ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \ucf5c\ubc31\uc740 \ub2e4\ub978 \ucf54\ub4dc\uc758 \uc778\uc218\ub85c \ub118\uaca8\uc8fc\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ucf54\ub4dc\ub97c \ub73b\ud55c\ub2e4. \\n\uc790\ubc14\uc5d0\uc11c\ub294 \ub78c\ub2e4\ub098 \uc775\uba85 \ud074\ub798\uc2a4\ub97c \ub118\uaca8\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n```mermaid\\nflowchart LR\\n \ud074\ub77c\uc774\uc5b8\ud2b8 -- \ucf5c\ubc31\uc804\ub2ec --\x3e \uba54\uc11c\ub4dc\\n \uba54\uc11c\ub4dc -- \ub0b4\ubd80\ud638\ucd9c --\x3e \uc804\ub2ec\ubc1b\uc740\ucf5c\ubc31\\n```\\n\\n:::\\n\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uc870\ud68c\ud558\uace0, \ud574\ub2f9 \uac12\uc744 \uac1d\uccb4\ub85c \ub9e4\ud551\ud558\uc5ec \uac12\uc744 \ubc18\ud658\ud574\uc57c \ud55c\ub2e4. \\nexecuteQuery\ub85c \uc870\ud68c\ud55c \uac12\uc740 ResultSet \uc548\uc5d0 \ub4e4\uc5b4\uac00\uc788\ub2e4. \\n\uc774\ub97c \uc6d0\ud558\ub294 \ud0c0\uc785\uc758 \uac12\uc73c\ub85c \ubcc0\ud658\ud574\uc57c\ud558\ub2c8 \uc77c\ub2e8 \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4. \\n\\n```java\\n@FunctionalInterface\\npublic interface RowMapper {\\n User mapRow(final ResultSet resultSet) throws SQLException;\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c\\n\\n\uc704\uc5d0\uc11c \uc815\uc758\ud55c RowMapper\ub97c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c? \\n\uc544\ub798\uc640 \uac19\uc774 SQL \ucffc\ub9ac, RowMapper, \ud30c\ub77c\ubbf8\ud130\ub97c \ubd84\ub9ac\ud55c \uba54\uc11c\ub4dc\uc5d0 \ub118\uaca8\uc8fc\uace0 \ucffc\ub9ac \uc2e4\ud589 \ud6c4 \ub9e4\ud551\ud55c \uac12\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \\n\\n```java\\npublic User findById(final int userId) {\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n return queryForSingleResult(query, resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n }, userId);\\n}\\n\\nprivate User queryForSingleResult(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n if (resultSet.next()) {\\n return rowMapper.mapRow(resultSet);\\n }\\n return null;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n\\nprivate ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c\\n\\n\ub2e8\uac74 \uc870\ud68c\uc640 \uc720\uc0ac\ud558\ub2e4.\\n\\n```java\\npublic List findAll() {\\n final String query = \\"SELECT * FROM user\\";\\n return query(query, resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n });\\n}\\n\\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(rowMapper.mapRow(resultSet));\\n }\\n return result;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n\\nprivate ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n}\\n```\\n\\n### \uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30\\n\\n\uc704\uc758 \ucf54\ub4dc\ub294 User\ub97c \uc870\ud68c\ud560 \ub54c\ub9cc \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\n\uc544\ub798\uc640 \uac19\uc774 \uc81c\ub124\ub9ad\uc744 \uc801\uc6a9\ud558\uc5ec \ub2e4\ub978 Dao\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n@FunctionalInterface\\npublic interface RowMapper {\\n T mapRow(final ResultSet resultSet) throws SQLException;\\n}\\n\\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {...}\\nprivate T queryForSingleResult(final String query, final RowMapper rowMapper, final Object... parameters) {...}\\n```\\n\\n### \uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30\\n\\n\uba54\uc11c\ub4dc\ub85c \ubd84\ub9ac\ud55c \ubd80\ubd84\uc744 JdbcTemplate\uc774\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc62e\uae34\ub2e4. \\n\ub610\ud55c null\uc744 \ubc18\ud658\ud558\uae30 \ubcf4\ub2e8 Optional\ub85c \uac10\uc2f8\uc11c \ubc18\ud658\ud558\ub3c4\ub85d \ubcc0\uacbd\ud55c\ub2e4. \\n\ucd5c\uc885\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uac00 \uc644\uc131\ub41c\ub2e4.\\n\\n\\n\\n\\n```java\\npublic class UserDao {\\n private final RowMapper rowMapper = resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n };\\n private final JdbcTemplate jdbcTemplate;\\n\\n public UserDao(final JdbcTemplate jdbcTemplate) {\\n this.jdbcTemplate = jdbcTemplate;\\n }\\n\\n public void insert(final String name) {\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n jdbcTemplate.executeUpdate(query, name);\\n }\\n\\n public void delete(final int userId) {\\n final String query = \\"DELETE FROM user WHERE user_id = ?\\";\\n jdbcTemplate.executeUpdate(query, userId);\\n }\\n\\n public Optional findById(final int userId) {\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);\\n }\\n\\n public List findAll() {\\n final String query = \\"SELECT * FROM user\\";\\n return jdbcTemplate.query(query, rowMapper);\\n }\\n}\\n```\\n\\n\\n\\n\\n```java\\npublic class JdbcTemplate {\\n private final ConnectionPool connectionPool;\\n\\n public JdbcTemplate(final ConnectionPool connectionPool) {\\n this.connectionPool = connectionPool;\\n }\\n\\n public void executeUpdate(final String query, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public Optional queryForSingleResult(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n ) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n if (resultSet.next()) {\\n return Optional.of(rowMapper.mapRow(resultSet));\\n }\\n return Optional.empty();\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n private ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters\\n ) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n }\\n\\n public List query(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n ) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(rowMapper.mapRow(resultSet));\\n }\\n return result;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n}\\n```\\n\\n\\n"},{"id":"java-class-file","metadata":{"permalink":"/java-class-file","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx","source":"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx","title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","description":"\ud074\ub798\uc2a4 \ud30c\uc77c","date":"2023-04-03T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 3\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Class","permalink":"/tags/class"}],"readingTime":5.63,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","slug":"java-class-file","tags":["Java","Class"]},"unlisted":false,"prevItem":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","permalink":"/custom-jdbc-template"},"nextItem":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","permalink":"/test-double"}},"content":"### \ud074\ub798\uc2a4 \ud30c\uc77c\\n\\n\uc790\ubc14 \uc18c\uc2a4\ucf54\ub4dc\uac00 \uc2e4\ud589\uc774 \ub418\ub824\uba74 \uc790\ubc14 \ucef4\ud30c\uc77c\ub7ec(javac)\ub97c \ud1b5\ud574 \uc18c\uc2a4\ucf54\ub4dc\ub97c \ud074\ub798\uc2a4\ud30c\uc77c\ub85c \ubcc0\ud658\ud574\uc57c \ud55c\ub2e4. \\n\ucef4\ud30c\uc77c\ub41c \ud074\ub798\uc2a4\ud30c\uc77c\uc740 \uc5b4\ub5a4 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744\uae4c?\\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd\\n\\n8\ube44\ud2b8 \ubc14\uc774\ud2b8\uc758 \uc2a4\ud2b8\ub9bc\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4. \\n16\ube44\ud2b8 \ubc0f 32\ube44\ud2b8\uc758 \ub370\uc774\ud130\ub294 \uac01\uac01 2\uac1c, 4\uac1c\uc758 \uc5f0\uc18d\ub41c 8\ube44\ud2b8\ub97c \uc77d\uc5b4\uc11c \uad6c\uc131\ub41c\ub2e4. \\n\uba40\ud2f0\ubc14\uc774\ud2b8\uc758 \uacbd\uc6b0 \ud56d\uc0c1 big endian \uc21c\uc11c\ub85c \uc800\uc7a5\ub41c\ub2e4. \\n\\nu1 \u2192 unsigned 1byte \\nu2 \u2192 unsigned 2byte \\nu4 \u2192 unsigned 4byte \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870\\n\\n```\\nClassFile {\\n u4 magic;\\n u2 minor_version;\\n u2 major_version;\\n u2 constant_pool_count;\\n cp_info constant_pool[constant_pool_count-1];\\n u2 access_flags;\\n u2 this_class;\\n u2 super_class;\\n u2 interfaces_count;\\n u2 interfaces[interfaces_count];\\n u2 fields_count;\\n field_info fields[fields_count];\\n u2 methods_count;\\n method_info methods[methods_count];\\n u2 attributes_count;\\n attribute_info attributes[attributes_count];\\n}\\n```\\n\\n### \ub9e4\uc9c1\ub118\ubc84\\n\\n\ubaa8\ub4e0 \ud074\ub798\uc2a4 \ud30c\uc77c\uc740 0xCAFEBABE\ub77c\ub294 \ub9e4\uc9c1\ub118\ubc84\ub85c \uc2dc\uc791\ud55c\ub2e4. \\n\ubcf4\ud1b5 \ub9e4\uc9c1\ub118\ubc84\ub294 \ud30c\uc77c \uc885\ub958\ub97c \uc2dd\ubcc4\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804\\n\\n\ud074\ub798\uc2a4 \ud30c\uc77c \ubc84\uc804 \uac12\uc740 \ud074\ub798\uc2a4\ub85c\ub354\uc758 \ud638\ud658\uc131 \ubcf4\uc7a5\uc744 \uc704\ud574 \uaf2d \ud544\uc694\ud55c \uac12\uc774\ub2e4. \\n- Java 17 \ubc84\uc804\uc73c\ub85c \ube4c\ub4dc\ud55c\ub2e4\uba74 class version 61 ex) 00 00 00 3D\\n\\n\ud638\ud658\ub418\uc9c0 \uc54a\ub294 \ubc84\uc804\uc758 \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \ub85c\ub529\ud558\ub824\uace0 \ud558\ub294 \uacbd\uc6b0 \ub7f0\ud0c0\uc784\uc5d0 `UnsupportedClassVersionError` \uc608\uc678\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n**class\xa0file format major versions**\\n\\n| Java SE | Released | Major | Supported majors |\\n| --- | --- | --- | --- |\\n| 8 | March 2014 | 52 | 45 .. 52 |\\n| 9 | September 2017 | 53 | 45 .. 53 |\\n| 10 | March 2018 | 54 | 45 .. 54 |\\n| 11 | September 2018 | 55 | 45 .. 55 |\\n| 12 | March 2019 | 56 | 45 .. 56 |\\n| 13 | September 2019 | 57 | 45 .. 57 |\\n| 14 | March 2020 | 58 | 45 .. 58 |\\n| 15 | September 2020 | 59 | 45 .. 59 |\\n| 16 | March 2021 | 60 | 45 .. 60 |\\n| 17 | September 2021 | 61 | 45 .. 61 |\\n\\n### \uc0c1\uc218 \ud480\\n\\n2\ubc14\uc774\ud2b8\uc758 \uc0c1\uc218\uc758 \uac1c\uc218\uac12\uc774 \uba3c\uc800\uc624\uace0 \uadf8 \ub4a4\ub85c \ucf54\ub4dc\uc5d0 \ub4f1\uc7a5\ud558\ub294 \uc0c1\uc218\uac12\uc774 \ubaa8\uc5ec\uc788\ub2e4. \\n\ud074\ub798\uc2a4\uba85, \uc0c1\uc218\uba85, \uc0c1\uc218 \uac12, \ud544\ub4dc\uba85, \uba54\uc11c\ub4dc\uba85\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4. \\nJVM\uc740 \ucf54\ub4dc \uc2e4\ud589 \uc2dc \ub7f0\ud0c0\uc784\uc5d0 \ubc30\uce58\ub41c \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c, \ud574\ub2f9 \uc0c1\uc218 \ud480 \ud14c\uc774\ube14\uc744 \ucc3e\uc544\ubcf4\uace0 \ud544\uc694\ud55c \uac12\uc744 \ucc38\uc870\ud55c\ub2e4.\\n\\n### \uc561\uc138\uc2a4 \ud50c\ub798\uadf8\\n\\n\ud074\ub798\uc2a4, \uc778\ud130\ud398\uc774\uc2a4\uc640 \uac19\uc740 \ud30c\uc77c\uc758 \uc18d\uc131\uc744 \ud45c\uc2dc\ud55c\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 public interface\ub85c \uc815\uc758\ub41c \uc778\ud130\ud398\uc774\uc2a4\uc758 \ud50c\ub798\uadf8\ub294 0x0601\uc774\ub2e4. \\n- \uacc4\uc0b0\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. `ACC_PUBLIC` xor `ACC_INTERFACE` xor `ACC_ABSTRACT`\\n\\n\uacf5\uc2dd\ubb38\uc11c\uc5d0 \ub4e4\uc5b4\uac00\uba74 \uac01 \ud50c\ub798\uadf8\uc5d0 \ub300\ud55c \uc124\uba85 + \ud50c\ub798\uadf8 \uc124\uc815\uc2dc \ub3d9\uc2dc\uc5d0 \uc124\uc815\ub418\uba74 \uc548\ub418\ub294 \ud50c\ub798\uadf8\uc640 \uac19\uc740 \uc124\uba85\uc774 \uc790\uc138\ud558\uac8c \ub098\uc640\uc788\ub2e4.\\n\\n**Class access and property modifiers**\\n\\n| Flag Name | Value | Interpretation |\\n| --- | --- | --- |\\n| ACC_PUBLIC | 0x0001 | Declared\xa0public; may be accessed from outside its package. |\\n| ACC_FINAL | 0x0010 | Declared\xa0final; no subclasses allowed. |\\n| ACC_SUPER | 0x0020 | Treat superclass methods specially when invoked by the\xa0invokespecial\xa0instruction. |\\n| ACC_INTERFACE | 0x0200 | Is an interface, not a class. |\\n| ACC_ABSTRACT | 0x0400 | Declared\xa0abstract; must not be instantiated. |\\n| ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |\\n| ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |\\n| ACC_ENUM | 0x4000 | Declared as an\xa0enum\xa0type. |\\n| ACC_MODULE | 0x8000 | Is a module, not a class or interface. |\\n\\n### this_class\\n\\n\ud074\ub798\uc2a4\uba85\uacfc \uac19\uc740 \uc774\ub984\uc744 \ud45c\ud604\ud558\ub294 \uac12\uc73c\ub85c, \uc0c1\uc218 \ud480\uc5d0\uc11c \ud074\ub798\uc2a4\uba85\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4. \\n\ud574\ub2f9 \uc778\ub371\uc2a4\uc758 \ud56d\ubaa9\uc740 `CONSTANT_Class_infoclass` \ud615\uc2dd\uc758 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### super_class\\n\\n\uc0c1\uc218 \ud480\uc5d0\uc11c \uc288\ud37c \ud074\ub798\uc2a4\uc758 \uc774\ub984\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4. \\n\uc544\ubb34\uac83\ub3c4 \uc0c1\uc18d\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\uc758 \uacbd\uc6b0 `java.lang.Object`\uc758 \uc778\ub371\uc2a4 \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4.\\n\\n### interface, field, method\\n\\n\uac01\uac01\uc758 \uac1c\uc218\uc640, \uc815\ubcf4\uc5d0 \ub300\ud55c \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4. \\ninterface, field, method\ub97c \ud45c\uc2dc\ud558\ub294 \ubc29\ubc95\uc774 \uac01\uac01 \ub2e4\ub974\uace0, \uc811\uadfc\uc790\uc5d0 \ub300\ud55c \ud50c\ub798\uadf8\ub3c4 \uac01\uac01 \ub2e4\ub974\ub2e4.\\n\\n### attributes\\n\\n\ud574\ub2f9 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucd94\uac00 \uc815\ubcf4\uc758 \ubaa8\uc74c\uc774\ub2e4. \uc608) \uc18c\uc2a4\ud30c\uc77c\uba85 \\n\uc815\ud574\uc9c4 \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \uad6c\uc870\ub97c \ud655\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4. \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234\\n\\nIntelliJ plugin - BinEd \\nIntelliJ plugin - jclasslib Bytecode Viewer\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n2\uc7a5 JVM \uc774\uc57c\uae30, \uc790\ubc14 \ucd5c\uc801\ud654 \\n[Class file in Java, File Format](https://docs.fileformat.com/ko/programming/class/) \\n[java se11 Class \ud30c\uc77c \ud615\uc2dd, Oracle](https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html) \\n[java se17 Class \ud30c\uc77c \ud615\uc2dd, Oracle](https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html)"},{"id":"test-double","metadata":{"permalink":"/test-double","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx","source":"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx","title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","description":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?","date":"2023-04-04T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 4\uc77c","tags":[{"label":"Test","permalink":"/tags/test"},{"label":"Mock","permalink":"/tags/mock"}],"readingTime":4.52,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","slug":"test-double","tags":["Test","Mock"]},"unlisted":false,"prevItem":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","permalink":"/java-class-file"},"nextItem":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","permalink":"/transaction-and-isolation"}},"content":"### \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?\\n\\n\ubaa8\ub4e0 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \uac00\uc9dc \uc758\uc874\uc131\uc744 \uc758\ubbf8\ud558\uace0, \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud589\ub420 \ub54c \ub2e4\ub978 \uac1d\uccb4\ub97c \ub300\uc2e0\ud55c\ub2e4. \\nGerard Meszaros\uc758 xUnit Test Patterns\ub77c\ub294 \ucc45\uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ub2e4\uc12f \uac00\uc9c0(\ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774, \ubaa9, \ud398\uc774\ud06c)\ub85c \uad6c\ubd84\ud55c\ub2e4.\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \uae30\ubcf8 \uba54\ucee4\ub2c8\uc998\uc740 \ub2e4\ud615\uc131\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774\ub2e4. \\n\uc678\ubd80 \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uacbd\uc6b0, \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uace0 \uc678\ubd80 \uc11c\ube44\uc2a4 \ub300\uc2e0 \ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\uc758 \uad6c\ud604\uccb4\ub97c \uc0dd\uc131\ud558\ub294 \uac83\uc774\ub2e4.\\n\\n**\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \ud0c0\uc785 \uacc4\uce35 \uad6c\uc870**\\n\\n```mermaid\\nflowchart LR\\n Mock --\x3e Spy --\x3e Stub --\x3e Dummy --\x3e TestDouble\\n Fake --\x3e TestDouble\\n```\\n\\n### \ub354\ubbf8(Dummy)\\n\\n\uac00\uc7a5 \ub2e8\uc21c\ud558\uace0, \uc6d0\uc2dc\uc801\uc778 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c \uc544\ubb34 \uc77c\ub3c4 \ud558\uc9c0 \uc54a\ub294 \uad6c\ud604\uccb4\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\uac00 \ud544\uc694\ud55c \uacbd\uc6b0 \uc0ac\uc6a9\ud55c\ub2e4. \\n\ub9cc\uc57d \uba54\uc11c\ub4dc\uac00 \ubb34\uc5b8\uac00 \ubc18\ud658\uc744 \ud574\uc57c\ud558\ub294 \uacbd\uc6b0 0, null\uacfc \uac19\uc740 \uac12\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\\n### \uc2a4\ud141(Stub)\\n\\n\uc2dc\ub098\ub9ac\uc624\ub9c8\ub2e4 \ub2e4\ub978 \uac12(\ubbf8\ub9ac \uc900\ube44 \ub41c \uacb0\uacfc)\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\uc774\ub97c \ud1b5\ud574 \ud2b9\uc815 \uc870\uac74\uc5d0\uc11c \uba54\uc11c\ub4dc\uac00 \uc608\uc0c1\ud55c\ub300\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n### \uc2a4\ud30c\uc774(Spy)\\n\\n\uc2a4\ud141\uacfc \uc720\uc0ac\ud558\uc9c0\ub9cc \ud638\ucd9c \uc5ec\ubd80\ub97c \uae30\ub85d\ud558\uac70\ub098 \ud638\ucd9c\ud560 \ub54c \uc804\ub2ec\ud55c \uc778\uc790\uac12\uc744 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4. \\n\uc608) \uba54\uc77c \uc804\uc1a1 \uae30\ub2a5\uc744 \uac00\uc9c4 \uac1d\uccb4\ub97c \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc73c\ub85c \uad6c\ud604\ud588\uc744 \ub54c \uba54\uc77c \uc804\uc1a1 \ud69f\uc218\ub97c \uae30\ub85d\ud55c\ub2e4. \\n\\n### \ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)\\n\\n\ubaa9\uc740 \ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774\ub97c \ud3ec\ud568\ud55c\ub2e4. \\n\ud638\ucd9c \uc2dc \uc0ac\uc804\uc5d0 \uc815\uc758\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud558\uace0, \uc608\uc0c1\uce58 \ubabb\ud55c \ud638\ucd9c\uc774 \uc788\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4. \\n\ub610\ud55c \ud638\ucd9c\uc5d0 \ub300\ud55c \uac80\uc99d\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n### \uac00\uc9dc(Fake)\\n\\nDOC\uc640 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc9c0\ub9cc, \ub354\uc6b1 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ub41c \uac83\uc774\ub2e4. \\n\uc608) \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \ub3d9\uc791\ud558\ub294 \uac00\uc9dc \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note DOC(depended-on component)\\n\\n\uc758\uc874 \uad6c\uc131 \uc694\uc18c, DOC\ub97c \ud14c\uc2a4\ud2b8 \ub354\ube14\ub85c \ub300\uccb4\ud560 \uc218 \uc788\ub2e4. \\n\ud14c\uc2a4\ud2b8 \ub354\ube14\uc740 DOC\uc640 \ub3d9\uc77c\ud55c API\ub97c \uc81c\uacf5\ud574\uc57c \ud55c\ub2e4. \\n\\n:::\\n\\n### \uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84\\n\\n\ub2e8\uc704 \ud14c\uc2a4\ud2b8 p.149 \uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ud06c\uac8c \ubaa9\uacfc \uc2a4\ud141\uc73c\ub85c \uad6c\ubd84\ud55c\ub2e4. \\n\ubaa9\uc740 SUT\uc640 \uad00\ub828\ub41c \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ubc18\uba74, \uc2a4\ud141\uc740 \ub2e8\uc21c \ubaa8\ubc29\ub9cc \ud55c\ub2e4. \\n\\n| TestDouble | Mock | Stub |\\n| --- | --- | --- |\\n| \ud3ec\ud568 \uc720\ud615 | \ubaa9, \uc2a4\ud30c\uc774 | \uc2a4\ud141, \ub354\ubbf8, \ud398\uc774\ud06c |\\n| \uc6a9\ub3c4 | \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ub370 \uc0ac\uc6a9 | \ub0b4\ubd80\ub85c \ub4e4\uc5b4\uc624\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\ub294 \ub370 \uc0ac\uc6a9 |\\n| \uc124\uba85 | SUT\uac00 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9 | SUT\uac00 \uc785\ub825 \ub370\uc774\ud130\ub97c \uc5bb\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9\\n| \uc608\uc2dc | \uc774\uba54\uc77c \ubc1c\uc1a1 | \ub370\uc774\ud130 \uac80\uc0c9 |\\n\\n:::note SUT(system under test)\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc0c1 \uc2dc\uc2a4\ud15c \\n\ud14c\uc2a4\ud2b8\ub97c \ud558\ub824\ub294 \ub300\uc0c1\\n\\n:::\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30 - 3\uc7a5 \uace0\uae09 \ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 \\n\ub2e8\uc704 \ud14c\uc2a4\ud2b8 - 5\uc7a5 \ubaa9\uacfc \ud14c\uc2a4\ud2b8 \ucde8\uc57d\uc131, \ube14\ub77c\ub514\ubbf8\ub974 \ucf54\ub9ac\ucf54\ud504 \\n\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uc2dc\uc791\ud558\uae30 - 7\uc7a5 \ub300\uc5ed, \ucd5c\ubc94\uade0 \\n[\ud14c\uc2a4\ud2b8 \ub354\ube14, Martin Fowler](https://www.martinfowler.com/bliki/TestDouble.html) \\n[\ud14c\uc2a4\ud2b8 \uad00\ub828 \uc6a9\uc5b4 \uc815\ub9ac, Johngrib](https://johngrib.github.io/wiki/test-terms/) \\n[Test Double, Gerard Meszaros](http://xunitpatterns.com/Test%20Double.html)"},{"id":"transaction-and-isolation","metadata":{"permalink":"/transaction-and-isolation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx","source":"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx","title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","description":"\ud2b8\ub79c\uc7ad\uc158(Transaction)","date":"2023-04-05T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 5\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Transaction","permalink":"/tags/transaction"},{"label":"Isolation","permalink":"/tags/isolation"}],"readingTime":9.57,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","slug":"transaction-and-isolation","tags":["DataBase","Transaction","Isolation"]},"unlisted":false,"prevItem":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","permalink":"/test-double"},"nextItem":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/mysql-lock"}},"content":"## \ud2b8\ub79c\uc7ad\uc158(Transaction)\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub17c\ub9ac\uc801 \uae30\ub2a5\uc744 \uc218\ud589\ud558\uae30 \uc704\ud55c \uc791\uc5c5\uc758 \ub2e8\uc704\ub97c \ub9d0\ud55c\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc740 \uc791\uc5c5\uc758 \uc644\uc804\uc131\uacfc \ub370\uc774\ud130\uc758 \uc815\ud569\uc131\uc744 \ubcf4\uc7a5\ud574 \uc900\ub2e4. \\n\ub17c\ub9ac\uc801\uc778 \uc791\uc5c5 \uc14b\uc744 \uc644\ubcbd\ud558\uac8c \ucc98\ub9ac\ud558\uac70\ub098, \uc624\ub958 \uc2dc \uc791\uc5c5\uc758 \uc77c\ubd80\ub9cc \uc801\uc6a9\ub418\ub294 \ud604\uc0c1\uc744 \ub9c9\uc544\uc900\ub2e4. \\n\\n### \ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)\\n\\n\uc6d0\uc790\uc131(Atomicity): \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \uc2e4\ud589\ub41c \uc791\uc5c5\ub4e4\uc740 \ubaa8\ub450 \uc131\uacf5\ud558\uac70\ub098, \uc2e4\ud328\ud574\uc57c \ud55c\ub2e4. \\n\uc77c\uad00\uc131(Consistency): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc218\ud589\ub418\uae30 \uc804\uacfc \ud6c4\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc77c\uad00\ub41c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud574\uc57c \ud55c\ub2e4. \\n\uaca9\ub9ac\uc131(Isolation): \uac01\uac01\uc758 \ud2b8\ub79c\uc7ad\uc158\uc740 \ub3c5\ub9bd\uc801\uc774\ub77c \uc11c\ub85c\uc5d0\uac8c \uc601\ud5a5\uc744 \uc8fc\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4. \\n\uc9c0\uc18d\uc131(Durability): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c\ub2e4\uba74 \uc601\uad6c\uc801\uc73c\ub85c \uacb0\uacfc\uc5d0 \ubc18\uc601\ub418\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### \ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc740 \uaf2d \ud544\uc694\ud55c \ucd5c\uc18c\uc758 \ucf54\ub4dc\uc5d0\ub9cc \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.(\ud2b8\ub79c\uc7ad\uc158\uc758 \ubc94\uc704\ub97c \ucd5c\uc18c\ud654\ud558\ub77c) \\n\uad6c\ud604\ud574\uc57c \ud558\ub294 \uc5c5\ubb34\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158\uc744 \ubb36\uac70\ub098 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\ub294 \uacbd\uc6b0 \ubc18\ub4dc\uc2dc \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4. \\n\\n:::info \uc65c \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\uc744 \ub54c \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud560\uae4c? \ud83e\udd14\\n\\n\ub370\uc774\ud130\uc758 \uc77c\uad00\uc131\uacfc \uc548\uc804\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4. \\n\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc744 \ud2b8\ub79c\uc7ad\uc158 \ub0b4\ubd80\uc5d0 \ud3ec\ud568\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \\n- \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc911\uac04\uc5d0 \uc2e4\ud328\ud560 \uac00\ub2a5\uc131(\uc548\uc804\uc131 X)\\n- \ud1b5\uc2e0\uc73c\ub85c \uc778\ud574 \ub370\uc774\ud130\uac00 \ubcc0\uacbd\ub420 \uc218 \uc788\ub294 \ubd80\ubd84(\uc77c\uad00\uc131 X)\\n\\n:::\\n\\n## \uaca9\ub9ac \uc218\uc900(Isolation level)\\n\\n\uc5ec\ub7ec \ud2b8\ub79c\uc7ad\uc158\uc774 \ub3d9\uc2dc\uc5d0 \ucc98\ub9ac\ub420 \ub54c \ud2b9\uc815 \ud2b8\ub79c\uc7ad\uc158\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\uc758 \uc870\ud68c \ubc0f \ubcc0\uacbd\uc744 \ud5c8\uc6a9\ud560\uc9c0 \uacb0\uc815\ud558\ub294 \uac83\uc744 \ub9d0\ud55c\ub2e4. \\n\uaca9\ub9ac \uc218\uc900\uc774 \ub192\uc544\uc9c8 \uc218\ub85d \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\uc774 \ub5a8\uc5b4\uc9c0\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\uc9c0\ub9cc, `SERIALIZABLE`\uc774 \uc544\ub2c8\ub77c\uba74 \ud06c\uac8c \uc131\ub2a5\uc758 \uc800\ud558\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\n### READ UNCOMMITTED\\n\\n\uac01 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\uc758 \ubcc0\uacbd \ub0b4\uc6a9\uc774 `COMMIT`\uc774\ub098 `ROLLBACK` \uc5ec\ubd80\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcf4\uc778\ub2e4. \\n\ub354\ud2f0 \ub9ac\ub4dc \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud558\uae30 \ub54c\ubb38\uc5d0 \uc815\ud569\uc131\uc758 \ubb38\uc81c\uac00 \ub9ce\uc740 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\nMySQL \uc0ac\uc6a9\uc2dc \ucd5c\uc18c `READ COMMITTED` \uc774\uc0c1\uc758 \uaca9\ub9ac \uc218\uc900 \uc0ac\uc6a9\uc744 \uad8c\uc7a5\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: READ UNCOMMITTED\\n---\\nsequenceDiagram\\n Alice->>Database: BEGIN\\n Alice->>Database: INSERT(Alice)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: COMMIT(Alice)\\n```\\n\\n### READ COMMITTED\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 `COMMIT`\uc774 \uc644\ub8cc\ub41c \ub370\uc774\ud130\ub9cc \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc870\ud68c\ud560 \uc218 \uc788\ub2e4. \\n\uc624\ub77c\ud074 DBMS\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\n`REPEATABLE READ`\uac00 \ubcf4\uc7a5\ub418\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 `NON-REPEATABLE READ` \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: READ COMMITTED\\n---\\nsequenceDiagram\\n Alice->>Database: BEGIN\\n Alice->>Database: UPDATE(Alice to Bob)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice(Undo log)\\n Alice->>Database: COMMIT\\n```\\n\\n### REPEATABLE READ\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \uc2dc\uc791\ub418\uae30 \uc804\uc5d0 `COMMIT`\uc774 \uc644\ub8cc\ub41c \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub9cc \uc870\ud68c\ud560 \uc218 \uc788\ub2e4. \\nMySQL\uc758 InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\nMVCC\ub97c \uc774\uc6a9\ud574 \uc5b8\ub450(Undo) \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \uc774\uc804 \ub370\uc774\ud130\ub97c \uc774\uc6a9\ud574 \ub3d9\uc77c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc5ec\uc904 \uc218 \uc788\uac8c \ubcf4\uc7a5\ud55c\ub2e4. \\n\ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc7a5\ud558\ub294 \ubc29\ubc95\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n - \ubaa8\ub4e0 InnoDB \ud2b8\ub79c\uc7ad\uc158\uc740 \uc21c\ucc28\uc801\uc73c\ub85c \uc99d\uac00\ud558\ub294 \uace0\uc720\ud55c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ub97c \uac00\uc9c4\ub2e4.\\n - Undo \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \ub808\ucf54\ub4dc\uc5d0\ub294 \ubcc0\uacbd\uc744 \ubc1c\uc0dd\uc2dc\ud0a8 \ud2b8\ub79c\uc7ad\uc158\uc758 \ubc88\ud638\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\ub2e4.\\n - Undo \uc601\uc5ed\uc758 \ubc31\uc5c5\ub41c \ub370\uc774\ud130\ub294 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774 \ubd88\ud544\uc694\ud558\ub2e4\uace0 \ud310\ub2e8\ud558\ub294 \uacbd\uc6b0 \uc0ad\uc81c\ub41c\ub2e4.\\n - `REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c\ub294 MVCC\ub97c \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \uac00\uc7a5 \uc624\ub798\ub41c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ubcf4\ub2e4 \uc55e\uc120 Undo \uc601\uc5ed\uc758 \ub370\uc774\ud130\ub294 \uc0ad\uc81c\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\nInnoDB\uc5d0\uc11c\ub294 \uac2d \ub77d\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc744 \uc774\uc6a9\ud558\uc5ec \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc744 \ubc29\uc9c0\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: REPEATABLE READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN(TRX-ID: 1)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: BEGIN(TRX-ID: 2)\\n Alice->>Database: UPDATE(Alice to Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice(Undo log)\\n```\\n\\n:::note \uac2d \ub78d(Gap lock)\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d(Next-key lock)\\n\\n\uac2d \ub77d: \ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\n\ub125\uc2a4\ud2b8 \ud0a4 \ub77d: \ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4.\\n\\n:::\\n\\n:::note MVCC(Multi Version Concurrency Control)\\n\\n\ub3d9\uc2dc\uc131\uc744 \uc81c\uc5b4\ud558\ub294 \ubc29\ubc95 \uc911 \ud558\ub098\ub85c \ud558\ub098\uc758 \ub808\ucf54\ub4dc\uc5d0 \ub300\ud574 \uc5ec\ub7ec \uac1c\uc758 \ubc84\uc804\uc774 \ub3d9\uc2dc\uc5d0 \uad00\ub9ac\ub418\ub294 \uac83\uc774\ub2e4.\\n - PostgreSQL\uc740 \ub2e4\uc911 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uac83\uc73c\ub85c MVCC\ub97c \uad6c\ud604\ud55c\ub2e4.\\n - Oracle, InnoDB\ub294 `Undo log`\ub97c \uc774\uc6a9\ud574 \uc774 \uae30\ub2a5\uc744 \uad6c\ud604\ud55c\ub2e4.(\ucd5c\uc2e0 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub9cc DB\uc5d0 \uc800\uc7a5)\\n\\n\uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc77d\uad00\ub41c \uc77d\uae30\ub97c \uc81c\uacf5\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4.\\n\\n:::\\n\\n### SERIALIZABLE\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc9c4\ud589\uc2dc\ud0a4\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uace0 \ub530\ub77c\uc11c \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\ub3c4 \ub2e4\ub978 \uaca9\ub9ac \uc218\uc900\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c4\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uace0 \uc4f0\ub294 \ub808\ucf54\ub4dc\ub97c \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\ub294 \uc811\uadfc\ud560 \uc218 \uc5c6\uace0 \ub2e8\uc21c\ud55c \uc77d\uae30 \uc791\uc5c5\ub3c4 \uacf5\uc720 \uc7a0\uae08(\uc77d\uae30 \uc7a0\uae08)\uc744 \ud68d\ub4dd\ud574\uc57c\ub9cc \ud55c\ub2e4. \\nInnoDB\uc5d0\uc11c\ub294 \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc774 `REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uad73\uc774 \uc0ac\uc6a9\ud560 \ud544\uc694\ub294 \uc5c6\ub2e4. \\n\\n## \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c\\n\\n\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ub354\ud2f0 \ub9ac\ub4dc, \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c, \ud32c\ud140 \ub9ac\ub4dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n| \uaca9\ub9ac \uc218\uc900 / \ubd80\uc815\ud569 \ubb38\uc81c | \ub354\ud2f0 \ub9ac\ub4dc | \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c | \ud32c\ud140 \ub9ac\ub4dc |\\n| --- | --- | --- | --- |\\n| READ UNCOMMITTED | O | O | O |\\n| READ COMMITTED | X | O | O |\\n| REPEATABLE READ | X | X | O(InnoDB\ub294 X) |\\n| SERIALIZABLE | X | X | X |\\n\\n### \ub354\ud2f0 \ub9ac\ub4dc(Dirty read)\\n\\n\uc5b4\ub5a4 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c \uc791\uc5c5\uc774 \uc644\ub8cc\ub418\uc9c0 \uc54a\uc558\uc5b4\ub3c4 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcfc \uc218 \uc788\ub294 \ud604\uc0c1 \\n\ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \uc218\uc900\uc774 READ UNCOMMITTED\uc77c \ub54c \ubc1c\uc0dd\ud55c\ub2e4. \\n\uc608) B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uace0 \ucee4\ubc0b\uc744 \ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, A\uac00 \ud574\ub2f9 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud560 \uc218 \uc788\ub294 \uacbd\uc6b0\\n\\n### \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)\\n\\n\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc758 \uac19\uc740 \ud589\uc5d0 \ub450 \ubc88 \uc774\uc0c1 \uc870\ud68c\uac00 \ubc1c\uc0dd\ud588\ub294\ub370, \uadf8 \uac12\uc774 \ub2e4\ub978 \ud604\uc0c1 \\n\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc5ec\ub7ec \ubc88 \uc870\ud68c\ud558\ub358 \uc911 B\uac00 \ub808\ucf54\ub4dc\ub97c \ubcc0\uacbd\ud558\uc5ec A\uac00 \uc870\ud68c\ud55c \uac12\uc774 \ub2ec\ub77c\uc9c0\ub294 \uacbd\uc6b0 \\n\\n```mermaid\\n---\\ntitle: NON REPEATABLE READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: BEGIN\\n Alice->>Database: UPDATE(Alice to Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT\\n Database->>+Bob: Bob\\n```\\n\\n### \ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)\\n\\n\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ucffc\ub9ac \uc218\ud589\uc2dc, \uc218\ud589 \uacb0\uacfc\uac00 \ub2e4\ub978 \ud604\uc0c1 \\n\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud558\uace0 B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uc5ec A\uac00 \ub2e4\uc2dc \uc870\ud68c\ud560 \ub54c \uc874\uc7ac\ud558\uc9c0 \uc54a\uc740 \ub808\ucf54\ub4dc\uac00 \uc870\ud68c\ub418\ub294 \uacbd\uc6b0 \\n\\n```mermaid\\n---\\ntitle: PHANTOM READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN(TRX-ID: 1)\\n Bob->>Database: SELECT COUNT\\n Database->>+Bob: 1\\n Alice->>Database: BEGIN(TRX-ID: 2)\\n Alice->>Database: INSERT(Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT COUNT\\n Database->>+Bob: 2\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Isolation Level, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html)"},{"id":"mysql-lock","metadata":{"permalink":"/mysql-lock","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","source":"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","description":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","date":"2023-04-06T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 6\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Lock","permalink":"/tags/lock"},{"label":"MySQL","permalink":"/tags/my-sql"}],"readingTime":4.405,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","slug":"mysql-lock","tags":["DataBase","Lock","MySQL"]},"unlisted":false,"prevItem":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","permalink":"/transaction-and-isolation"},"nextItem":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/innodb-lock"}},"content":"## MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08\\n\\nMySQL\uc5d0\uc11c\uc758 \ub77d\uc740 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub808\ubca8\uacfc, MySQL \uc5d4\uc9c4 \ub808\ubca8\ub85c \ub098\ub20c \uc218 \uc788\ub2e4. \\nMySQL \uc5d4\uc9c4 \ub808\ubca8\uc758 \uc7a0\uae08\uc740 \ubaa8\ub4e0 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce5c\ub2e4. \\n\\n### \uae00\ub85c\ubc8c \ub77d(Global lock)\\n\\nMySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08 \uc911 \uac00\uc7a5 \ub113\uc740 \ubc94\uc704\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc7a0\uae08\uc774\ub2e4. \\n - \uc601\ud5a5\uc744 \ubbf8\uce58\ub294 \ubc94\uc704\ub294 \ud574\ub2f9 \uc11c\ubc84 \uc804\uccb4\uc774\ub2e4.\\n - \uc791\uc5c5 \ub300\uc0c1 \ud14c\uc774\ube14, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0c1\uad00 \uc5c6\uc774 \ub3d9\uc77c\ud558\uac8c \uc601\ud5a5\uc744 \ubc1b\ub294\ub2e4.\\n\\n\ud55c \uc138\uc158\uc5d0\uc11c \uae00\ub85c\ubc8c \ub77d\uc744 \ud68d\ub4dd\ud558\uba74 \ud574\uc81c \ub420 \ub54c \uae4c\uc9c0 \uc870\ud68c\ub97c \uc81c\uc678\ud55c \ub300\ubd80\ubd84\uc758 \uba85\ub839\uc774 \ub300\uae30 \uc0c1\ud0dc\uac00 \ub41c\ub2e4. \\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc874\uc7ac\ud558\ub294 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \ubc31\uc5c5\uc744 \ubc1b\uc544\uc57c\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\nInnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c\ub294 \ubc31\uc5c5 \uc2dc \uc870\uae08 \ub354 \uac00\ubcbc\uc6b4 \ubc31\uc5c5 \ub77d\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\n-- GLOBAL LOCK\\nFLUSH TABLES WITH READ LOCK;\\n-- UNLOCK\\nUNLOCK TABLES;\\n\\n-- BACKUP LOCK\\nLOCK INSTANCE FOR BACKUP;\\n-- UNLOCK\\nUNLOCK INSTANCE;\\n```\\n\\n:::note MyISAM\\n\\nMySQL 5.5 \ubc84\uc804 \uc774\uc804\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, SELECT \uc791\uc5c5 \uc18d\ub3c4\uac00 \ube60\ub974\ub2e4.\\n\\n:::\\n\\n### \ud14c\uc774\ube14 \ub77d(Table lock)\\n\\n\uac1c\ubcc4 \ud14c\uc774\ube14 \ub2e8\uc704\ub85c \uc124\uc815\ub418\ub294 \uc7a0\uae08\uc774\ub2e4. \\n\uba85\uc2dc\uc801 \ub610\ub294 \ubb35\uc2dc\uc801\uc73c\ub85c \ud2b9\uc815 \ud14c\uc774\ube14\uc758 \ub77d\uc744 \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4. \\n\ubb35\uc2dc\uc801 \ub77d\uc740 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub294 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uba74 \ubc1c\uc0dd\ud55c\ub2e4. \\nInnoDB \ud14c\uc774\ube14\uc5d0\ub294 DML \ucffc\ub9ac\ub294 \ubb34\uc2dc\ub418\uace0 DDL \uc77c \uacbd\uc6b0\uc5d0\ub9cc \ubb35\uc2dc\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud55c\ub2e4.\\n\\n```sql\\n-- TABLE LOCK\\nLOCK TABLES table_name [ READ | WRITE ]\\n\\n-- UNLOCK\\nUNLOCK TABLES;\\n```\\n\\n### \ub124\uc784\ub4dc \ub77d(Named lock)\\n\\n\uc784\uc758\uc758 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc7a0\uae08\uc73c\ub85c \uc720\uc800 \ub808\ubca8 \ub77d\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\uc5ec\ub7ec \uc2a4\ub808\ub4dc\ub098 \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc77c\ud55c \ub370\uc774\ud130\ub97c \uc218\uc815\ud558\ub824\ub294 \uacbd\uc6b0, \ub3d9\uc2dc\uc5d0 \uc218\uc815\ud558\uc9c0 \ubabb\ud558\ub3c4\ub85d \ubcf4\ud638\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\n-- aGVyYg== \ub77c\ub294 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08 \ud68d\ub4dd, \uc774\ubbf8 \uc7a0\uae08\uc744 \uc0ac\uc6a9\uc911\uc778 \uacbd\uc6b0 1\ucd08 \ub3d9\uc548\ub9cc \ub300\uae30\\nSELECT GET_LOCK(\'aGVyYg==\', 1);\\n\\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc774 \uc124\uc815\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.\\nSELECT IS_FREE_LOCK(\'aGVyYg==\');\\n\\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4.\\nSELECT RELEASE_LOCK(\'aGVyYg==\');\\n\\n-- \uc704 3\uac1c \ud568\uc218 \ubaa8\ub450 \uc815\uc0c1\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud558\uac70\ub098 \ud574\uc81c\ud55c \uacbd\uc6b0\uc5d0 1\uc744, \uc544\ub2c8\uba74 0\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n-- \ubaa8\ub4e0 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4. \ud574\uc81c\ub41c \uc7a0\uae08\uc758 \uac1c\uc218\ub97c \ubc18\ud658\ud55c\ub2e4.\\nSELECT RELEASE_ALL_LOCKS();\\n```\\n\\n### \uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac1d\uccb4\uc758 \uc774\ub984\uc774\ub098 \uad6c\uc870\ub97c \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \ud68d\ub4dd\ud558\ub294 \uc7a0\uae08\uc774\ub2e4. \\n\uba85\uc2dc\uc801\uc73c\ub85c \ud68d\ub4dd \ub610\ub294 \ud574\uc81c \ud560 \uc218 \uc5c6\uc9c0\ub9cc \ud14c\uc774\ube14\uc758 \uc774\ub984\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4. \\n\ubcf4\ud1b5 \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ud14c\uc774\ube14\uc744 \ubc14\uafd4\uc57c\ud558\ub294 \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ub41c\ub2e4.\\n\\n```sql\\n-- \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ubcc4\ub3c4\uc758 \uc784\uc2dc \ud14c\uc774\ube14\uc5d0 \uc11c\ube44\uc2a4\uc6a9 \ub7ad\ud0b9 \ub370\uc774\ud130 \uc0dd\uc131 \ud6c4 \uae30\uc874 \ud14c\uc774\ube14\uc744 \ubc31\uc5c5\ud558\ub294 \uacbd\uc6b0\\n-- \uc544\ub798 \uad6c\ubb38 \uc2e4\ud589 \uc2dc \uba54\ud0c0\ub370\uc774\ud130 \ub77d\uc744 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.\\nRENAME TABLE rank TO rank_backup, rank_new TO rank;\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[MySQL\uc758 User Level Lock\ub97c \ud65c\uc6a9\ud55c\ub2e4\uba74?, gywndi](https://gywn.net/2013/12/mysql-user-level-lock/) \\n[Locking Functions, MySQL 5.7 Reference](https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html#function_release-all-locks) \\n[Locking Functions, MySQL 8.0 Reference](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks)"},{"id":"innodb-lock","metadata":{"permalink":"/innodb-lock","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","source":"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","description":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","date":"2023-04-07T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 7\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Lock","permalink":"/tags/lock"},{"label":"InnoDB","permalink":"/tags/inno-db"}],"readingTime":5.805,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","slug":"innodb-lock","tags":["DataBase","Lock","InnoDB"]},"unlisted":false,"prevItem":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/mysql-lock"},"nextItem":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","permalink":"/book-leadership-and-self-deception"}},"content":"## InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08\\n\\nMySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08\uacfc \ubcc4\uac1c\ub85c \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub0b4\ubd80\uc5d0\uc11c \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \\n\ubcf4\ud1b5 \uba85\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\ub294 \ub4dc\ubb3c\uace0, \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ubb35\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc774 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n\ub3d9\uc2dc\uc131 \uc81c\uc5b4 \ubc29\uc2dd\uc5d0\ub294 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uacfc \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc774 \uc788\ub2e4. \\nInnoDB\ub294 \uae30\ubcf8\uc801\uc73c\ub85c MVCC(\ub2e4\uc911 \ubc84\uc804 \ub3d9\uc2dc\uc131 \uc81c\uc5b4)\ub97c \ud1b5\ud574 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uace0 \ub77d\uc744 \ud1b5\ud574 \ud2b9\uc815 \uc0c1\ud669\uc5d0\uc11c \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n:::note \ub099\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(OCC, Optimistic concurrency control)\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \uc11c\ub85c \ucda9\ub3cc\ud558\uc9c0 \uc54a\ub294\ub2e4\uace0 \uac00\uc815\ud558\ub294 \ubc29\uc2dd \\n\\n:::\\n\\n:::note \ube44\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(PCC, Pessimistic Concurrency Control)\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ucda9\ub3cc\ud558\ub294 \uac00\uc815\ud558\uc5d0 \uc7a0\uae08\uc744 \uac70\ub294 \ubc29\uc2dd \\n\uc77c\ubc18\uc801\uc73c\ub85c\xa0Shared Lock, Exclusive Lock\uc744 \ud1b5\ud574 \uc774\ub97c \uad6c\ud604\ud55c\ub2e4.\\n\\n:::\\n\\n### Shared & Exclusive Locks\\n\\nInnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc218\ud589\ud560 \ub54c \uacf5\uc720 \uc7a0\uae08\uacfc \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n**\uacf5\uc720 \uc7a0\uae08(S, shared lock)**\\n\\n\ub370\uc774\ud130 \uc870\ud68c\ub97c \uc704\ud55c \ub77d, \uc77d\uae30 \uc7a0\uae08(read lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uae30\uac00 \uac00\ub2a5\ud558\uc9c0\ub9cc, \uc4f0\uae30\ub294 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc608) `SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;`\\n\\n**\ubc30\ud0c0\uc801 \uc7a0\uae08(X, exclusive lock)** \\n\\n\ub370\uc774\ud130 \ubcc0\uacbd\uc744 \uc704\ud55c \ub77d, \uc4f0\uae30 \uc7a0\uae08(write lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\ub77d\uc744 \uac74 \ud2b8\ub79c\uc7ad\uc158\ub9cc\uc774 \ud574\ub2f9 \ub370\uc774\ud130\uc5d0 \uc811\uadfc \uac00\ub2a5\ud558\ub2e4. \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \uc77d\uae30, \uc4f0\uae30\uac00 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc608) `SELECT * FROM table_name WHERE id = 1 FOR UPDATE;`\\n\\n### Intention Locks\\n\\nInnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uacfc \ud14c\uc774\ube14 \uc7a0\uae08\uc758 \uacf5\uc874\uc744 \uc704\ud574 \uc778\ud14d\uc158 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \\n\ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ub85c\uc6b0\uc5d0 \ub300\ud574\uc11c \ub098\uc911\uc5d0 \uc694\uccad\ub418\ub294 \uac83\uc774 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uc7a0\uae08\uc778\uc9c0 \uac00\ub9ac\ud0a4\uae30 \uc704\ud574 \uc0ac\uc6a9\ub41c\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 \uc778\ud150\uc158 \uc7a0\uae08\uc744 \uba3c\uc800 \ud68d\ub4dd\ud55c\ub2e4. \\n\uc778\ud150\uc158 \ub77d\uc740 \uae30\ubcf8\uc801\uc73c\ub85c \ucda9\ub3cc\uc744 \ubc29\uc9c0\ud558\uace0 \ub370\ub4dc\ub77d\uc744 \ubc29\uc9c0\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4. \\n\\n**\uc778\ud150\uc158 \uacf5\uc720 \uc7a0\uae08(IS, intention shared lock)**\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \uacf5\uc720 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.\\n\\n**\uc778\ud150\uc158 \ubc30\ud0c0\uc801 \uc7a0\uae08(IX, intention exclusive lock)** \\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.\\n\\n** \uc7a0\uae08\uac04\uc758 \ud638\ud658\uc131 **\\n\\n| | X | IX | S | IS |\\n| --- | --- | --- | --- | --- |\\n| X | Conflict | Conflict | Conflict | Conflict |\\n| IX | Conflict | Compatible | Conflict | Compatible |\\n| S | Conflict | Conflict | Compatible | Compatible |\\n| IS | Conflict | Compatible | Compatible | Compatible |\\n\\n### Record Locks\\n\\n\ub808\ucf54\ub4dc \uc790\uccb4\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\nInnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc740 \ub808\ucf54\ub4dc \uc790\uccb4\uac00 \uc544\ub2c8\ub77c \uc778\ub371\uc2a4\uc758 \ub808\ucf54\ub4dc\ub97c \uc7a0\uadfc\ub2e4. \\n\\n### Gap Locks\\n\\n\ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\n\ub808\ucf54\ub4dc\uc640 \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\uc5d0 \uc0c8\ub85c\uc6b4 \ub808\ucf54\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \uc81c\uc5b4\ud558\uace0, \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc758 \uc77c\ubd80\ub85c \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### Next-Key Locks\\n\\n\ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4. \\n`REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ud32c\ud140 \ub9ac\ub4dc\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uc7a0\uae08\uc774\ub2e4. \\n\\n### AUTO-INC Locks\\n\\n`AUTO_INCREMENT` \uce7c\ub9bc\uc774 \uc0ac\uc6a9\ub41c \ud14c\uc774\ube14\uc5d0 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \ub808\ucf54\ub4dc\uac00 `INSERT`\ub418\ub294 \uacbd\uc6b0, \uac01 \ub808\ucf54\ub4dc\ub294 \uc911\ubcf5\ub418\uc9c0 \uc54a\uace0 \uc800\uc7a5\ub41c \uc21c\uc11c\ub300\ub85c \uc99d\uac00\ud558\ub294 \uc77c\ub828\ubc88\ud638 \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4. \\nInnoDB \ub294 \ub0b4\ubd80\uc801\uc73c\ub85c AUTO-INC \ub77d\uc774\ub77c\uace0 \ud558\ub294 \ud14c\uc774\ube14 \uc218\uc900\uc758 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uacfc \uad00\uacc4 \uc5c6\uc774 `INSERT`\ub098 `REPLACE` \ubb38\uc7a5\uc5d0\uc11c `AUTO_INCREMENT` \uac12\uc744 \uac00\uc838\uc624\ub294 \uc21c\uac04\ub9cc \ub77d\uc774 \uac78\ub838\ub2e4\uac00 \ud574\uc81c\ub41c\ub2e4.\\n\\n### \uc7a0\uae08 \uc608\uc2dc\\n\\n```sql\\n-- \ub808\ucf54\ub4dc\ub294 id \uae30\uc900 10, 20, 30, 40, 50\uc774 \uc788\ub2e4\uace0 \uac00\uc815\\n-- Record Locks: 10\uc5d0 \ub300\ud574 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id = 10 for update;\\n\\n-- Gap Locks: 51\ubd80\ud130 PositiveInfinity\uae4c\uc9c0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id > 100 for update;\\n\\n-- Next-Key Locks: 21\ubd80\ud130 30, 31\ubd80\ud130 40\uc5d0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id BETWEEN 25 AND 35 for update;\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Optimistic and Pessimistic record locking, IBM](https://www.ibm.com/docs/en/rational-clearquest/9.0.0?topic=clearquest-optimistic-pessimistic-record-locking) \\n[MySQL Innodb Locks, cecil1018](https://cecil1018.wordpress.com/2016/06/18/mysql-innodb-locks/) \\n[MySQL 8.0 InnoDB Locks, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html) \\n[Locks Set by Different SQL Statements in InnoDB, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html)"},{"id":"book-leadership-and-self-deception","metadata":{"permalink":"/book-leadership-and-self-deception","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx","source":"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx","title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","description":"\ucc45 \uc815\ubcf4","date":"2023-04-08T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 8\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":5.16,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","slug":"book-leadership-and-self-deception","tags":["Book"]},"unlisted":false,"prevItem":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/innodb-lock"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","permalink":"/tecochat-retrospective-1"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c \\n> \uc544\ube48\uc800\uc5f0\uad6c\uc18c\\n> \\n\\n### \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\\n\\n\ucc45\uc5d0\uc11c\ub294 \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc744 \ub2e4\ub8ec\ub2e4. \\n- \uc790\uae30\uae30\ub9cc: \uc790\uc2e0\uc758 \ubb38\uc81c\ub97c \uc778\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \\n- \uc790\uae30\ubc30\ubc18: \ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ubb34\uc5b8\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uc744 \ubc18\ud558\ub294 \ud589\uc704\\n\\n\uc790\uae30\ubc30\ubc18\uc744 \ud55c\ub2e4\uba74 \uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uac00 \ub41c\ub2e4. \\n\uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uc5d0 \ube60\uc9c0\ub294 \uac83\uc744 \ucc45\uc5d0\uc11c\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac04\ub2e4\uace0 \ud45c\ud604\ud55c\ub2e4. \\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\ucd5c\uadfc\uc5d0 \uc77d\uc740 \ucc45 \uc911 \uac00\uc7a5 \ub9c8\uc74c\uc774 \ubd88\ud3b8\ud588\ub2e4. \\n\uadf8\ub807\uae30\uc5d0 \ub354\ub354\uc6b1 \ub098\uc5d0\uac8c \ud544\uc694\ud55c \ub0b4\uc6a9\uc774 \ub2f4\uaca8\uc788\uc5c8\ub2e4. \\n\\n\uc0b4\uba74\uc11c \ub9ce\uc740 \uc120\ud0dd\uc758 \uc21c\uac04\uc774 \uc874\uc7ac\ud588\uace0, \uadf8 \uc21c\uac04\ub9c8\ub2e4 \uc790\uae30\ubc30\ubc18\uc744 \ud0dd\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4. \\n\uc791\uac8c\ub294 \uc9d1\uc548\uc77c\uc744 \ud574\uc57c \ud558\ub294\ub370 \ubab8\uc774 \uc870\uae08 \ud798\ub4e4\ub2e4\uace0 \ud558\uc9c0 \uc54a\uac70\ub098 \\n\ud06c\uac8c\ub294 \uc798\ubabb\uc744 \uc778\uc815\ud574\uc57c \ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uadf8\ub7ec\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uac00 \uc788\uc5c8\ub2e4. \\n\uc774\ub7f0 \uc0c1\ud669\uc774 \ubc18\ubcf5\ub418\uc5b4 \uacb0\uad6d \uc0c1\uc790 \uc548\uc5d0 \ub098 \uc790\uc2e0\uc744 \uac00\ub450\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4. \\n\\n\ub354 \ub098\uc740 \uc0b6\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \uc9c0\uc18d\uc801\uc73c\ub85c \ud655\uc778\ud558\uace0, \uc0c1\uc790 \ubc16\uc73c\ub85c \ub098\uac00\ub824\ub294 \uc5f0\uc2b5\uc744 \ud574\uc57c\uaca0\ub2e4. \\n\ub113\uc740 \uc2dc\uc120\uc744 \uac00\uc9c0\uace0, \ud56d\uc0c1 \ub0b4\uac00 \ud2c0\ub9b4 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc0dd\uac01\ud558\uace0 \uc0b4\uc544\uac00\uc790. \\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \uc6b0\ub9ac\uc758 \uc0dd\uac01\uc740 \uc9c0\uc2dd\ubcf4\ub2e4 \uc791\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc9c0\uc2dd\uc740 \uc0ac\ub791\ubcf4\ub2e4 \uc791\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc0ac\ub791\uc740 \uc874\uc7ac\ubcf4\ub2e4 \uc791\ub2e4. \\n\uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc0dd\uac01\ud558\ub294 \ub098\ub294 \uc2e4\uc81c\uc758 \ub098\ubcf4\ub2e4 \uadf8\ub9cc\ud07c \uc791\ub2e4. \\nR. D. \ub7ad \\np.19\\n>\\n\\n> \uc6b0\ub9ac\uac00 \uc678\uc801\uc73c\ub85c \uc5b4\ub5a4 \ud589\ub3d9\uc744 \ud558\ub4e0\uc9c0 \uac04\uc5d0, \uc0ac\ub78c\ub4e4\uc740 \uc6b0\ub9ac \ub9c8\uc74c\uc5d0\uc11c \uadf8\ub4e4\uc744 \uc5b4\ub5bb\uac8c \ub300\ud558\uace0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \uc8fc\ub85c \ubc18\uc751\ud569\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uac00 \uc0ac\ub78c\ub4e4\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \ub290\ub07c\uac8c \ub418\ub294\uc9c0\ub294 \uc6b0\ub9ac\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \ud639\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c0\uac8c \ub429\ub2c8\ub2e4. \\np.66\\n>\\n\\n> \ube44\ub09c\uc740 \uac10\uc815\uc5d0 \uc18d\ud558\uace0 \ub099\uad00\uc740 \uc758\uc9c0\uc5d0 \uc18d\ud55c\ub2e4. \\n\uc778\uac04\uc740 \uac10\uc815\ubcf4\ub2e4 \ub354 \ud070 \uc874\uc7ac\uc774\ub2e4. \\n\uc54c\ub7ad, \ud0c1\ub2db\ud55c \\np.103\\n>\\n\\n> \uc6b0\ub9ac\uac00 \uc790\uc2e0\uc5d0\uac8c\ub9cc \uc9d1\uc911\ud558\uace0 \uc788\ub294 \ud55c, \ud63c\uc790\uc11c \uc77c\ud558\ub294 \uac83 \uc774\uc0c1\uc758 \ucc3d\uc870\uc801\uc778 \uacb0\uacfc\ub098 \ud611\ub825\uc744 \uc774\ub04c\uc5b4 \ub0b8\ub2e4\ub294 \uac83\uc740 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4. \\n\uc624\ub298\ub0a0 \uacbd\uc81c \ud658\uacbd\uc5d0\uc11c\ub294 \ud63c\uc790\uc11c\ub294 \uc77c\uc758 \uacb0\uacfc\ub97c \ud0c1\uc6d4\ud558\uac8c \ub9cc\ub4e4\uc5b4 \ub0b4\uae30\uac00 \uc5b4\ub835\uc2b5\ub2c8\ub2e4. \\n\ub0b4\uac00 \uc911\uc2ec\uc774\uc5b4\uc57c \ub41c\ub2e4\ub294 \ud3d0\uc1c4\uc801\uc778 \uc0ac\uace0\ub294 \ud568\uaed8 \uc77c\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uc5f4\uc815\uc744 \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud569\ub2c8\ub2e4. \\np.175\\n> \\n\\n> \uc194\uc9c1\ud568\uc740 \uc6b0\ub9ac\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\ub294 \uc5f4\uc1e0\uc785\ub2c8\ub2e4. \\n\uadf8\uac83\uc740 \uc790\uc2e0\uc758 \ud589\ub3d9\uacfc \uad00\ub828\ub41c \uc0ac\ub78c\uc5d0 \ub300\ud574 \uae30\uaebc\uc774 \uc0ac\uacfc\ub97c \ud558\ub294 \uac83\uc785\ub2c8\ub2e4. \\n\uadf8\uac83\ub9cc\uc774 \uc2e4\ud0c0\ub798\ucc98\ub7fc \uc5c9\ud0a8 \uad00\uacc4\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\uc8e0. \\np.188\\n> \\n\\n> \ub204\uad70\uac00\ub97c \ub098\uc640 \uac19\uc774 \ub3d9\uc77c\ud55c \uac00\uce58\ub97c \uc9c0\ub2cc \ud55c \uc778\uac04\uc73c\ub85c \uc0dd\uac01\ud574\uc11c \uadf8 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \ubc16\uc5d0 \uacc4\uc18d \uba38\ubb34\ub974\uace0 \uc2f6\uc740 \uc5f4\ub9dd\uc774 \uc0dd\uae38 \ub54c, \ub098\ub294 \uc774\ubbf8 \uadf8 \uc0ac\ub78c\uc5d0 \ub300\ud574 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub2e4. \\np.214\\n> \\n\\n> \ub300\ubd80\ubd84\uc758 \uc0ac\ub78c\ub4e4\uc774 \uad00\uacc4 \uae30\uc220\uc744 \uac00\uc9c0\uace0 \uadf8\ub4e4\uc774 \uacaa\uace0 \uc788\ub294 \ubb38\uc81c\ub97c \ubc14\ub85c\uc7a1\uc73c\ub824\uace0 \ud558\ub294 \ub178\ub825\uc774 \uacb0\uc2e4\uc744 \uc5bb\uc9c0 \ubabb\ud558\ub294 \uac83\uc740 \uacb0\ucf54 \uadf8\ub7ec\ud55c \uae30\uc220 \ubd80\uc871 \ub54c\ubb38\uc5d0 \uc0dd\uae30\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4. \\n\uadf8\uac83\ub4e4\uc740 \uc790\uae30\ubc30\ubc18 \ub54c\ubb38\uc5d0 \uc0dd\uaca8\ub0a9\ub2c8\ub2e4. \\np.224\\n>\\n\\n> \uc6b0\ub9ac\ub294 \ud568\uaed8 \uc77c\ud558\uace0 \uc6b0\ub9ac\uc640 \ud568\uaed8 \uc0b4\uc544\uac00\ub294 \uc0ac\ub78c\uc774 \uc9c4\uc815\uc73c\ub85c \ub204\uad6c\uc778\uc9c0 \uc54c\uc9c0 \ubabb\ud569\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uac00 \uadf8\ub4e4\uacfc \uc9c4\uc815\uc73c\ub85c \ud568\uaed8 \uc18c\ud1b5\ud558\uae30 \uc804\uae4c\uc9c0\ub294 \uc6b0\ub9ac\ub294 \uadf8\ub4e4\uc758 \uac00\uce58\ub97c \uc798 \ubaa8\ub985\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc704\ub300\ud568\uc774\ub780 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc704\ub300\ud55c \uc810\uc744 \ubc1c\uacac\ud574 \uc8fc\ub294 \uac83\uc5d0 \uc788\uc2b5\ub2c8\ub2e4. \\np.280\\n>"},{"id":"tecochat-retrospective-1","metadata":{"permalink":"/tecochat-retrospective-1","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx","source":"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx","title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","description":"4\uc6d4 21\uc77c \uae08\uc694\uc77c","date":"2023-04-22T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 22\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.68,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","slug":"tecochat-retrospective-1","tags":["TecoChat","Retrospective"]},"unlisted":false,"prevItem":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","permalink":"/book-leadership-and-self-deception"},"nextItem":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","permalink":"/jenkins"}},"content":"### 4\uc6d4 21\uc77c \uae08\uc694\uc77c\\n\\n\ub808\ubca8 2\ub97c \uc2dc\uc791\ud55c \ub4a4 \ub0b4\uac00 \ud559\uc2b5\uc5d0 \ub300\ud55c \ubc29\ud5a5\uc744 \uc783\uc5b4\ubc84\ub838\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub808\ubca8 3, 4\uc5d0\uc11c \ub098\ub9cc\uc758 \uac15\uc810\uc744 \uac00\uc9c0\uace0 \uc2f6\uc5b4 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\ub2e8\uc21c\ud788 \uc2a4\ud504\ub9c1\uc744 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ud6a8\uc728\uc774 \ub9ce\uc774 \ub5a8\uc5b4\uc9c4\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uae00\uc4f0\uae30 \uc218\uc0c1\uc73c\ub85c \ubc1b\uc740 \ucfe0\ud3f0\uc744 \uc0ac\uc6a9\ud574 \ube0c\ub77c\uc6b4\uc5d0\uac8c \ucee4\ud53c\ucc57\uc744 \uc2e0\uccad\ud588\uace0, \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud574\ubcf4\ub77c\ub294 \ub2f5\uc744 \ubc1b\uc558\ub2e4. \\n\\n\ub098\ub294 \uc544\uc774\ub514\uc5b4\ub97c \ubabb\ub0b4\ub294 \ud3b8\uc778\ub370 \ube0c\ub77c\uc6b4\uc774 \uc544\uc774\ub514\uc5b4\uae4c\uc9c0 \ub358\uc838\uc8fc\uc168\ub2e4. \\n`Chat-GPT \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uace0, \ud574\ub2f9 \ud06c\ub8e8\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc744 \uacf5\uc720\ud560 \uc218 \uc788\ub294 \uac74 \uc5b4\ub5a4\uc9c0?` \\n\\n\uae30\uc220\uc774 \ubaa9\uc801\uc778 \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4\ub294 \ub2f5\ubcc0\uc744 \ub4e4\uc5c8\uace0, \ud63c\uc790 \uc544\ub2c8\uba74 \ud398\uc5b4\ud560 \uc218 \uc788\uc744 \uc815\ub3c4\uc758 \uc778\uc6d0\uc73c\ub85c \uc9c4\ud589\ud558\uba74 \uc88b\uaca0\ub2e4\uace0 \ud558\uc168\ub2e4. \\n\ud504\ub860\ud2b8\ub791 \uac04\ub2e8\ud558\uac8c \ubc30\ud3ec\uae4c\uc9c0 \ud574\ubcf8 \uacbd\ud5d8\uc774 \uc788\uc5b4\uc11c \ud63c\uc790\ud574\ub3c4 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc744 \uac83 \uac19\uc544\uc11c \ud63c\uc790 \ud558\uae30\ub85c \ub9c8\uc74c\uc744 \uba39\uc5c8\ub2e4. \\n\\n\uc774\uac74 \ubabb\ucc38\uc9c0\\n\\n### \ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?\\n\\n\ucee4\ud53c\ucc57\uc774 \ub05d\ub098\uace0 \uc9d1\uc73c\ub85c \ub3cc\uc544\uac00\ub294 \uae38\uc5d0 \ubc14\ub85c \ub3c4\uba54\uc778\uc744 \uad6c\ub9e4\ud558\ub824\uace0 namecheap\uc5d0\uc11c \uc801\ub2f9\ud55c \ub3c4\uba54\uc778\uc774 \uc5c6\uc744\uae4c \uac80\uc0c9\uc744 \uacc4\uc18d\ud588\ub2e4. \\n\ub9c8\uce58 \uc5b4\ub9b4 \ub54c \ud588\ub358 \uac8c\uc784 \ub2c9\ub124\uc784 \uc815\ud558\ub294 \uac83\ucc98\ub7fc \uc2dc\uac04\uc774 \uc624\ub798 \uac78\ub838\ub2e4. \\ndev, io, chat \ub3c4\uba54\uc778\uc774 \ud6c4\ubcf4\uc600\uace0 \uc9d1 \uac00\ub294 \uae38\uc5d0 \uacb0\uc815\ub9cc \ud558\ub2e4\uac00 \uad6c\ub9e4\ud558\uc9c0 \ubabb\ud588\ub2e4.\\n\\n### \ub9d0\ub791\uc758 DM\\n\\n\uc9d1\uc5d0 \uac00\uc11c \ubc25\uc744 \uba39\uace0 \ub9d0\ub791\uc774\ub791 DM \ud558\ub2e4 \ud504\ub85c\uc81d\ud2b8\ub97c \uac19\uc774 \ud558\uc790\ub294 \uc774\uc57c\uae30\uac00 \ub098\uc654\ub2e4. \\n\uc6b0\ud14c\ucf54 \ucd5c\uace0 \uace0\uc218 \ub9d0\ub791\uc758 \uc694\uad6c\ub77c \uc218\ub77d\ud558\uc9c0 \uc54a\uc73c\uba74 \ud6c4\ud3ed\ud48d\uc744 \uac10\ub2f9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\\n\uc774\ub7f0\uc800\ub7f0 \ub300\ud654\ub97c \ub098\ub204\ub2e4\uac00 \ub09c \ube60\ub974\uac8c \ud504\ub85c\ud1a0\ud0c0\uc785\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uace0 \uc2f6\uc5b4\uc11c \ud504\ub860\ud2b8\ub97c \uad6c\ud604\ud55c\ub2e4\uace0 \ud588\uace0, \ub9d0\ub791\uc740 GPT api\ub97c \uc870\uc0ac\ud558\uae30\ub85c \ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub3c4\uba54\uc778\uc5d0 \uad00\ud55c \uc774\uc57c\uae30\ub97c \ud558\ub2e4\uac00 woowachat\uc774 \uc5b8\uae09\ub418\uc5c8\uace0, namecheap\uc5d0\uc11c chat \ub3c4\uba54\uc778\uc744 \uc0ac\uc6a9\ud55c woowa.chat\uc73c\ub85c \uad6c\ub9e4\ud588\ub2e4. \\n\uc774\ud6c4\uc5d0 teco.chat\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4!\\n\\n### \ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec\\n\\n\ud1a0\uc694\uc77c\uc5d0 \uad6c\ub9e4\ud55c \ub3c4\uba54\uc778\uc744 CDN, \ubcf4\uc548 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 Cloudflare\uc5d0 \ub3c4\uba54\uc778 \ub4f1\ub85d\uc744 \ud588\ub2e4. \\n\ub098\uc5d0\uac8c \uc775\uc219\ud55c Nuxt3\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\uace0, Cloudflare Pages\ub97c \uc774\uc6a9\ud558\uc5ec \ubc30\ud3ec\ud588\ub2e4. \\n\\n### GPT\\n\\n\ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud558\ub2c8 api limit\uc774 \uc788\uc5b4 \ubd84\ub2f9 3\ubc88\ubc16\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uc77c\ub2e8 \ubc31\uc5d4\ub4dc\ub97c \uad6c\ucd95\ud558\uae30 \uc804\uc5d0\ub294 \ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud560 \uc0dd\uac01\uc774\ub2e4. \\n\\n### Sonarcloud\\n\\n\uc815\uc801 \ucf54\ub4dc \ubd84\uc11d \ub3c4\uad6c\ub85c Sonarcloud\ub97c \uc801\uc6a9\ud588\ub2e4. \\nSonarcloud\ub294 SonarQube\uc758 SaaS \ubc84\uc804\uc774\uace0 \uc0ac\uc6a9\uc774 \ub9e4\uc6b0 \ud3b8\ud558\ub2e4. \\n\uc608\uc804\uc5d0 Sonarcloud\ub97c \uc0ac\uc6a9\ud560 \ub550 \ubc84\ud2bc \uba87 \ubc88 \ub204\ub974\uba74 \uc801\uc6a9\ud560 \uc218 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \ubc14\ub85c github action\uc744 \uc0ac\uc6a9\ud558\ub77c\ub294 \uc548\ub0b4 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud588\ub2e4. \\nSonarcloud\uac00 \uc790\uccb4\uc801\uc73c\ub85c github repository\uc5d0 push \ud558\uba74 \uc815\uc801 \ubd84\uc11d\uc744 \ud574\uc8fc\ub294 \uae30\ub2a5\uc744 \uc6d0\ud588\uace0, Administration -> Analysis Method\uc5d0 Automatic Analysis\ub97c \uc124\uc815\ud558\ub2c8 \ub418\uc5c8\ub2e4. \\n\ub108\ubb34 \uaf41\uaf41 \uc228\uaca8\uc838\uc788\ub124\\n\\n### Tiptap\\n\\n\ucf54\ub4dc \ud558\uc774\ub77c\uc774\ud305 \uae30\ub2a5\uc744 \ub123\uace0 \uc2f6\uc5b4\uc11c Tiptap\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\nTiptap\uc740 Headless WYSIWYG \uc5d0\ub514\ud130\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uae30\ub2a5\uc5d0 \ud2b9\ud654\ub418\uc5b4\uc788\ub294 \uc5d0\ub514\ud130\ub2e4. \\n\uc544\uc9c1 Tiptap\uc774 \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uae30\ub2a5\uc744 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc0ac\uc6a9\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc CodeBlockLowlight \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucf54\ub4dc \ube14\ub85d\uc744 \uc608\uc058\uac8c \ucd9c\ub825\ud560 \uc218 \uc788\uc5c8\ub2e4. \\napi \ubc18\ud658\uac12 \uadf8\ub300\ub85c tiptap\uc758 content\uc5d0 \uc124\uc815\ud588\ub354\ub2c8 \ucf54\ub4dc \ube14\ub85d\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc544\uc11c \ubc31 \ud2f1 3\uac1c\ub97c `
`\ub85c \ubcc0\ud658\ud588\ub2e4.  \\n\ucd94\uac00\ub85c \ub744\uc5b4\uc4f0\uae30\ub3c4 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc544\uc11c `\\\\n`\ub97c `
`\ud0dc\uadf8\ub85c \ubcc0\ud658\ud588\ub2e4. \\n\ubcc0\ud658\ud558\ub294 \ub85c\uc9c1\uc740 GPT\uc758 \ub3c4\uc6c0\uc744 \ub9ce\uc774 \ubc1b\uc558\ub2e4. \\n\\n```ts\\nconst replaceCodeFences = (input: String) => {\\n const codeFencesRegex = /```([\\\\w-]*)\\\\n([\\\\s\\\\S]*?)\\\\n```/g;\\n return input\\n .replace(codeFencesRegex, (match, p1, p2) => {\\n const languageClass = p1 ? ` class=\\"language-${p1}\\"` : \\"\\";\\n return `
${p2}
`;\\n })\\n .replace(/\\\\n/g, \\"
\\");\\n};\\n```\\n\\nTiptap\uc744 \uc801\uc6a9\ud558\ub2c8 \ub2e4\uc74c\uacfc \uac19\uc774 \uae54\ub054\ud55c \ucf54\ub4dc \ube14\ub85d\uc744 \ubcfc \uc218 \uc788\uc5c8\ub2e4. \\n\\n![tecochat](./teco-chat.png)\\n\\n### \ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9\\n\\n\ud0c0\uc774\ud2c0\uc740 \ubc30\ub2ec\uc758\ubbfc\uc871 \ub3c4\ud604\uccb4, \ub0b4\uc6a9\uc740 IBM Plex Sans\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\ucd94\uac00\ub85c favicon\ub3c4 \uac04\ub2e8\ud558\uac8c \uc801\uc6a9\ud574\uc11c \ub9cc\uc871\uc2a4\ub7ec\uc6e0\ub2e4."},{"id":"jenkins","metadata":{"permalink":"/jenkins","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx","source":"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx","title":"Jenkins\ub85c CI/CD \uc124\uc815","description":"\uc124\uc815 \ud658\uacbd","date":"2023-04-30T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 30\uc77c","tags":[{"label":"Jenkins","permalink":"/tags/jenkins"},{"label":"Elastic Beanstalk","permalink":"/tags/elastic-beanstalk"}],"readingTime":7.495,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","slug":"jenkins","tags":["Jenkins","Elastic Beanstalk"]},"unlisted":false,"prevItem":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","permalink":"/tecochat-retrospective-1"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","permalink":"/tecochat-retrospective-2"}},"content":"### \uc124\uc815 \ud658\uacbd\\n\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc774\ubbf8\uc9c0: Amazon Linux 2023 AMI \\n\uc544\ud0a4\ud14d\uccd0: ARM \\n\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small \\n\ud658\uacbd \uad6c\uc131\uc774 \uc644\ub8cc\ub41c Elastic Beanstalk \\n\ub2e8\uc77c Spring Boot \ud504\ub85c\uc81d\ud2b8\uac00 \uc874\uc7ac\ud558\ub294 Github Repository\\n\\n### \\\\[EC2 CLI\\\\] Swap \uba54\ubaa8\ub9ac \uc124\uc815\\n\\nt4g.small\uc774 \ub7a8\uc774 2G\uc778\ub370 \ub7a8\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \ub290\uaef4\uc838\uc11c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud588\ub2e4. \\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \ub530\ub77c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud558\uace0 free -h \uba85\ub839\uc5b4\ub97c \ud1b5\ud574 \uc798 \uc124\uc815\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n``` bash\\n# fallocate \uc774\uc6a9\ud558\uc5ec \uc2a4\uc651 \ud30c\uc77c \uc0dd\uc131\\nsudo fallocate -l 2G /swapfile\\n\\n# \uad8c\ud55c \uc124\uc815\\nsudo chmod 600 /swapfile\\n\\n# \ud30c\uc77c\uc744 Swap \ud3ec\ub9f7\uc73c\ub85c \ubcc0\uacbd \ud6c4 \uc2dc\uc2a4\ud15c\uc5d0 \ub4f1\ub85d\\nsudo mkswap /swapfile\\nsudo swapon /swapfile\\n\\n# Swap \uba54\ubaa8\ub9ac \ubd80\ud305\uc2dc \uc790\ub3d9\uc73c\ub85c \ub9c8\uc6b4\ud2b8\ud558\ub3c4\ub85d \uc801\uc6a9\\n# \ucd5c\ud558\ub2e8\uc5d0 \ub2e4\uc74c \uad6c\ubb38 \uc124\uc815 -> /swapfile swap swap defaults 0 0\\nsudo vim /etc/fstab\\n```\\n\\n\\n### \\\\[EC2 CLI\\\\] jenkins \uc124\uce58\\n\\n```bash\\nsudo wget -O /etc/yum.repos.d/jenkins.repo \\\\\\n https://pkg.jenkins.io/redhat-stable/jenkins.repo\\nsudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key\\nsudo yum upgrade\\nsudo yum install java-17-amazon-corretto-devel\\nsudo yum install jenkins\\nsudo systemctl daemon-reload\\n```\\n\\n[Jenkins \uacf5\uc2dd \ud648\ud398\uc774\uc9c0](https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos) \ub97c \ucc38\uace0\ud558\uc5ec \uc124\uce58\ud558\ub294 \uac8c \uc88b\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] Jenkins \uc2dc\uc791\\n\\n```bash\\nsudo systemctl enable jenkins\\nsudo systemctl start jenkins\\n```\\n\\nenable\ub85c \uc124\uc815\ud558\uc5ec \ubd80\ud305\uc2dc \uc790\ub3d9\uc2dc\uc791 \ub418\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] nginx & git \uc124\uce58\\n\\n```bash\\nsudo yum install nginx\\nsudo systemctl enable nginx\\nsudo systemctl start nginx\\n\\nsudo yum install git\\n```\\n\\nnginx\uc640 \ucf54\ub4dc\ub97c \ubd88\ub7ec\uc62c \ub54c \uc0ac\uc6a9\ud560 git\uc744 \uc124\uce58\ud55c\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815\\n\\n\uc544\ub798 \uc124\uc815 \ud30c\uc77c\uc740 \uacf5\uc2dd \ud648\ud398\uc774\uc9c0\uc5d0\uc11c \uc548\ub0b4\ud55c \uae30\ubcf8\uc801\uc778 \uc124\uc815 \ud30c\uc77c\uc774\ub2e4.\\n\\n```bash\\nupstream jenkins {\\n keepalive 32; # keepalive connections\\n server 127.0.0.1:8080; # jenkins ip and port\\n}\\n\\n# Required for Jenkins websocket agents\\nmap $http_upgrade $connection_upgrade {\\n default upgrade;\\n \'\' close;\\n}\\n\\nserver {\\n listen 80; # Listen on port 80 for IPv4 requests\\n\\n server_name jenkins.example.com; # replace \'jenkins.example.com\' with your server domain name\\n\\n # this is the jenkins web root directory\\n # (mentioned in the output of \\"systemctl cat jenkins\\")\\n root /var/run/jenkins/war/;\\n\\n access_log /var/log/nginx/jenkins.access.log;\\n error_log /var/log/nginx/jenkins.error.log;\\n\\n # pass through headers from Jenkins that Nginx considers invalid\\n ignore_invalid_headers off;\\n\\n location ~ \\"^/static/[0-9a-fA-F]{8}\\\\/(.*)$\\" {\\n # rewrite all static files into requests to the root\\n # E.g /static/12345678/css/something.css will become /css/something.css\\n rewrite \\"^/static/[0-9a-fA-F]{8}\\\\/(.*)\\" /$1 last;\\n }\\n\\n location /userContent {\\n # have nginx handle all the static requests to userContent folder\\n # note : This is the $JENKINS_HOME dir\\n root /var/lib/jenkins/;\\n if (!-f $request_filename){\\n # this file does not exist, might be a directory or a /**view** url\\n rewrite (.*) /$1 last;\\n break;\\n }\\n sendfile on;\\n }\\n\\n location / {\\n sendfile off;\\n proxy_pass http://jenkins;\\n proxy_redirect default;\\n proxy_http_version 1.1;\\n\\n # Required for Jenkins websocket agents\\n proxy_set_header Connection $connection_upgrade;\\n proxy_set_header Upgrade $http_upgrade;\\n\\n proxy_set_header Host $host;\\n proxy_set_header X-Real-IP $remote_addr;\\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\\n proxy_set_header X-Forwarded-Proto $scheme;\\n proxy_max_temp_file_size 0;\\n\\n #this is the maximum upload size\\n client_max_body_size 10m;\\n client_body_buffer_size 128k;\\n\\n proxy_connect_timeout 90;\\n proxy_send_timeout 90;\\n proxy_read_timeout 90;\\n proxy_buffering off;\\n proxy_request_buffering off; # Required for HTTP CLI commands\\n proxy_set_header Connection \\"\\"; # Clear for keepalive\\n }\\n\\n}\\n```\\n\\nJenkins\ub294 8080 \ud3ec\ud2b8\ub85c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc\ub97c \uc124\uc815\ud574\uc900\ub2e4. \\n`/etc/nginx/conf.d`\xa0\uc544\ub798\xa0`default.conf`\xa0\ud30c\uc77c\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uace0 \uc704\uc640 \uac19\uc774 \uc785\ub825\ud558\uace0 \uc800\uc7a5\ud55c\ub2e4. \\nnginx\uc758 \uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\uc5d0 \uc874\uc7ac\ud558\ub294\xa0`include /etc/nginx/conf.d/*.conf;`\xa0\uc124\uc815 \ub54c\ubb38\uc5d0\xa0`.conf`\xa0\ub85c \ub05d\ub09c\ub2e4\uba74 \uc124\uc815\uc774 \uc801\uc6a9\ub41c\ub2e4. \\n\uc124\uc815 \ud6c4\xa0`sudo nginx -t`\ub85c \uc124\uc815\ud30c\uc77c\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud558\uace0,\xa0`sudo systemctl restart nginx`\xa0\uba85\ub839\uc5b4\ub85c nginx\ub97c \uc7ac\uc2dc\uc791\ud55c\ub2e4. \\n\\n### \\\\[Jenkins\\\\] Jenkins \uc811\uc18d\\n\\nJenkins\ub97c \uc124\uce58\ud55c EC2 \uc778\uc2a4\ud134\uc2a4 \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc5d0 80\ubc88 \ud3ec\ud2b8\uac00 \uc5f4\ub824\uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\nEC2\uc758 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \ub4e4\uc5b4\uac00\uba74 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4.\\n\\n![jenkins-start](./jenkins-start.png)\\n\\n\ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud558\ub294\ub370 `sudo cat /var/lib/jenkins/secrets/initialAdminPasswor` \ub97c \uc785\ub825\ud574 \ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc5bb\uc744 \uc218 \uc788\ub2e4. \\n\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 \ud50c\ub7ec\uadf8\uc778 \uc124\uc815 \ucc3d\uc774 \ub098\uc62c\ud150\ub370 `install suggested plugins`\uc744 \ud074\ub9ad\ud558\uc5ec Jenkins\uac00 \ucd94\ucc9c\ud558\ub294 \uae30\ubcf8 \ud50c\ub7ec\uadf8\uc778\ub4e4\uc744 \uc124\uce58\ud558\uba74 \ub41c\ub2e4. \\n\ud50c\ub7ec\uadf8\uc778\uc744 \uc124\uce58\ud558\uba74 \uacc4\uc815 \ubc0f \uc8fc\uc18c \uc124\uc815\uc744 \ud574\uc57c\ud558\ub294\ub370 \uc774\uac74 \ud3b8\ud558\uac8c \uc124\uc815\ud558\uba74 \ub41c\ub2e4. \\n\\n### \\\\[Jenkins\\\\] Jenkins Blue Ocean \uc124\uce58\\n\\nJenkins \uad00\ub9ac \u2192 Plugin Manager\uc5d0\uc11c Blue Ocean\uc744 \uac80\uc0c9\ud574 \uc124\uce58\ud55c\ub2e4.\\n\\n### \\\\[AWS IAM & EC2\\\\] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30\\n\\nS3\uc640 Elastic Beanstalk\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub824\uba74 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk \ub450 \uac1c\uc758 \uc815\ucc45\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uc5ed\ud560\uc744 \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4. \\nIAM\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc774 \uc5ed\ud560\uc744 \ud558\ub098 \uc0c8\ub85c \uc0dd\uc131\ud55c\ub2e4.\\n\\n1. \uc5d4\ud130\ud2f0 \uc120\ud0dd\\n\\n![aws-iam1](./aws-iam1.png)\\n\\n2. \uad8c\ud55c \ucd94\uac00\\n\\n![aws-iam2](./aws-iam2.png)\\n\\n3. \uc774\ub984 \uc9c0\uc815, \uac80\ud1a0 \ubc0f \uc0dd\uc131\\n\\n![aws-iam3](./aws-iam3.png)\\n\\n4. \uc0dd\uc131\ud55c IAM EC2 Jenkins \uc778\uc2a4\ud134\uc2a4\ub97c \uc120\ud0dd\ud558\uace0, \uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc744 \ub20c\ub7ec Role \uc124\uc815\\n\\n![aws-iam4](./aws-iam4.png)\\n\\n### \\\\[AWS S3\\\\] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131\\n\\n\ubc84\ud0b7\uc744 \uc0dd\uc131\ud560 \ub54c \ub2e4\uc74c \uc124\uc815\uc744 \uc81c\uc678\ud558\uace0 \ubaa8\ub450 \ucc28\ub2e8 \ud65c\uc131\ud654\ub97c \ud574\uc900\ub2e4.\\n\\n- `\uc0c8 ACL(\uc561\uc138\uc2a4 \uc81c\uc5b4 \ubaa9\ub85d)\uc744 \ud1b5\ud574 \ubd80\uc5ec\ub41c \ubc84\ud0b7 \ubc0f \uac1d\uccb4\uc5d0 \ub300\ud55c \ud37c\ube14\ub9ad \uc561\uc138\uc2a4 \ucc28\ub2e8`\\n\\n![aws-s3](./aws-s3.png)\\n\\n### \\\\[Github\\\\] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131\\n\\nrepo, user:email \uad8c\ud55c\uc774 \uc788\ub294 \ud1a0\ud070\uc774 \ud544\uc694\ud558\ub2e4. \\n\\n### \\\\[Jenkins\\\\] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\\n\\n![jenkins-blue-ocean1](./jenkins-blue-ocean1.png)\\n\\n\ube14\ub8e8 \uc624\uc158 \uc5f4\uae30\ub85c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc0dd\uc131\ud55c\ub2e4. \\n\ud1a0\ud070 \uc785\ub825 \u2192 \uc870\uc9c1 \uc120\ud0dd \u2192 CI/CD \uc124\uc815\ud560 Repository \uc120\ud0dd\uc744 \ud558\uba74 \ud30c\uc774\ud504\ub77c\uc778 \ucc3d\uc73c\ub85c \ub118\uc5b4\uac04\ub2e4. \\nJenkinsfile\uc744 \uc9c1\uc811 \uc791\uc131\ud558\uc5ec \uc124\uc815\ud558\uae30 \uc704\ud574 \uac04\ub2e8\ud558\uac8c print \ud558\ub098 \ucd9c\ub825\ud558\ub294 \uac83\uc73c\ub85c \uc124\uc815\ud588\ub2e4. \\n\\n![jenkins-blue-ocean2](./jenkins-blue-ocean2.png)\\n\\n\ud30c\uc774\ud504\ub77c\uc778\uc774 \uc2e4\ud589\ub420 \ud150\ub370 pipeline status\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ucd08\ub85d\ubd88\uc774 \ub728\uba74 \ub41c\ub2e4.\\n\\n![jenkins-blue-ocean3](./jenkins-blue-ocean3.png)\\n\\n### \\\\[Github Repsoitory\\\\] Jenkinsfile \uc124\uc815\\n\\n\ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\uc744 \ud1b5\ud574 \uc124\uc815\ud558\uba74 Jenkinsfile\uc774 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc9c0\uace0, \uc544\ub798\uc640 \uac19\uc774 \uc6d0\ud558\ub294 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc124\uc815\ud55c\ub2e4.\\n\\n```bash\\npipeline {\\n agent any\\n stages {\\n stage(\'build and test\') {\\n steps {\\n sh \'/gradlew clean build\'\\n }\\n }\\n stage(\'zip\') {\\n steps {\\n sh \'mv ./build/libs/woowachat.jar .\'\\n sh \'zip -r woowachat.zip .platform delivery.jar Procfile\'\\n }\\n }\\n stage(\'upload\') {\\n steps {\\n sh \'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2\'\\n }\\n }\\n stage(\'deploy\') {\\n steps {\\n sh \'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket=\\"woowa-chat\\",S3Key=\\"woowachat.zip\\"\'\\n sh \'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}\'\\n }\\n }\\n }\\n}\\n```\\n\\n### \\\\[Github\\\\] Webhooks \uc124\uc815\\n\\n![github-hook](./github-hook.png)\\n\\npush \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud560 \ub54c `http://Jenkins\uc8fc\uc18c/github-webhook/` \ub85c post request\ub97c \ud558\ub3c4\ub85d \uc6f9\ud6c5\uc744 \uc124\uc815\ud55c\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Install Jenkins - CentOS, Jenkins](https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos) \\n[Nginx Reverse Proxy Configuration, Jenkins](https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/) \\n[Amazon Corretto 17 JDK Install, AWS](https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html) \\n[Amazon Linux 2023 packages, AWS](https://docs.aws.amazon.com/linux/al2023/release-notes/all-packages-al2023-20230419.html)"},{"id":"tecochat-retrospective-2","metadata":{"permalink":"/tecochat-retrospective-2","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx","source":"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx","title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","description":"\ud504\ub860\ud2b8\uc5d4\ud2b8","date":"2023-05-01T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 1\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.67,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","slug":"tecochat-retrospective-2","tags":["TecoChat","Retrospective"]},"unlisted":false,"prevItem":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","permalink":"/jenkins"},"nextItem":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","permalink":"/web-racing-car-retrospective"}},"content":"### \ud504\ub860\ud2b8\uc5d4\ud2b8\\n\\n\ub2c9\ub124\uc784\uc744 \uc785\ub825\ud558\uc5ec \uac04\ub2e8\ud788 \ub85c\uadf8\uc778\ud558\ub294 \ud654\uba74, \ucc44\ud305 \ubaa9\ub85d\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\uace0 \ub2e8\uc77c \ucc44\ud305\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\ub2e4. \\n\ucd94\uac00\ub85c \ucc44\ud305\uc744 \uc774\uc5b4\ub098\uac08 \uc218 \uc788\uac8c \ud558\ub294 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4. \\n\uc790\uc798\ud558\uac8c \uc2e0\uacbd \uc4f8 \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c, \ud504\ub860\ud2b8\uc5d4\ub4dc \ud558\ub294 \uc0ac\ub78c\ub4e4\uc774 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4. \\n\uc5ec\uc720\uac00 \ub41c\ub2e4\uba74 \uc790\uc2e0\uc758 \ucc44\ud305\uc744 \ubcfc \uc218 \uc788\ub294 \uae30\ub2a5\uc774\ub098, \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub294 \uae30\ub2a5, \ub313\uae00 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud560 \uc608\uc815\uc774\ub2e4. \\n\\n### \ubc31\uc5d4\ub4dc\\n\\n\ucd5c\ub300\ud55c \ube68\ub9ac \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uae30\ub85c \uc815\ud574\uc11c, \ubc31\uc5d4\ub4dc\ub294 \ub9d0\ub791\uc774 \uc77c\ub2e8 \ub2e4 \ub9cc\ub4e4\uace0 \uc788\ub2e4. \\n\ub9d0\ub791\uc774 \ud55c \ubd80\ubd84\uc774 \ub108\ubb34 \ub9ce\uc544\uc11c \ub0b4\uac00 \ubabb \ub530\ub77c\uac00\ub294 \uac83 \uac19\ub2e4. \\n\ub098\uc911\uc5d0 \ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc774\ud574\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### Http Request Header\\n\\n\uc544\uc9c1 \uc778\uc99d\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ud558\uc9c0 \uc54a\uc544\uc11c \uc694\uccad \ud5e4\ub354\uc5d0 \uc774\ub984\uc744 \ubcf4\ub0b4\uae30\ub85c \ud588\ub2e4. \\n\ub9d0\ub791\uc774 \ud55c\uae00\uc740 \uc548\ub41c\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c Base64\ub85c \uc778\ucf54\ub529\ud558\uace0, \ubc31\uc5d4\ub4dc\uc5d0\uc11c \ub514\ucf54\ub529 \ud558\uc5ec \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\n\uc544\ub798\ub294 pinia\uc5d0 \uc788\ub294 name \uac12\uc744 \uc778\ucf54\ub529 \ud558\ub294 \ucf54\ub4dc\ub2e4. deprecated \ub418\uc5c8\ub2e4\ub294\ub370, \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560 \uc904 \ubab0\ub77c\uc11c \uc77c\ub2e8 \uc774\uac78 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n```ts\\nconst encodedName = () => {\\n const uriComponent = unescape(encodeURIComponent(name.value));\\n return btoa(uriComponent);\\n};\\n```\\n\\n### Elastic Beanstalk\\n\\n\uac00\uc7a5 \ube60\ub974\uac8c \ubc31\uc5d4\ub4dc\ub97c \ubc30\ud3ec\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ubb58\uc9c0 \uace0\ubbfc\ud558\ub2e4\uac00 Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\nElastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uba74 \uc778\ud504\ub77c\uc5d0 \ub300\ud574 \uc798 \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube60\ub974\uac8c \ubc30\ud3ec\ud558\uace0 \uad00\ub9ac\ud560 \uc218 \uc788\ub2e4. \\n\ubaa8\ub2c8\ud130\ub9c1, \ub85c\uae45, \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4. \\n\\n### Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac\\n\\n\ucd08\uae30 \uc124\uc815 \uc2dc RDS\ub97c \uc5f0\uacb0\ud558\uace0 \uc124\uc815 \uc644\ub8cc \ud6c4 \ubd84\ub9ac\ud55c\ub2e4\uba74, Beanstalk \uc778\uc2a4\ud134\uc2a4 -> RDS \uc694\uccad \uc2dc \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc744 \uc548 \ud574\ub3c4 \ub41c\ub2e4. \\nRDS \ubd84\ub9ac \uc2dc Beanstalk\uc5d0 \uae30\ubcf8\uc801\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub294 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD\uc640 \uac19\uc740 \ud658\uacbd \ubcc0\uc218\uac00 \uac19\uc774 \uc81c\uac70\ub41c\ub2e4. \\n\ucd94\uac00\ub85c Elastic Beanstalk\ub85c RDS\ub97c \uc124\uc815\ud558\uba74 \uae30\ubcf8 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uba85\uc740 ebdb\ub2e4. \\n\\n### Elastic Beanstalk nginx \uc124\uc815\\n\\n\uc5c5\ub85c\ub4dc\ud558\ub294 zip \ud30c\uc77c \ub0b4\ubd80\uc5d0 `.platform/nginx/conf.d/` \uacbd\ub85c\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ucd94\uac00\ud558\uba74 nginx \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n### Jenkins\\n\\n\ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc77c\uc77c\ud788 \ubc30\ud3ec\ud558\uae30 \ubd88\ud3b8\ud574\uc11c Jenkins\ub97c \uc774\uc6a9\ud558\uc5ec Repository\uc5d0 \ucf54\ub4dc\ub97c push \ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ubc30\ud3ec\uac00 \ub418\uac8c \uc124\uc815\ud558\uae30\ub85c \ud588\ub2e4. \\n\uc791\ub144\uc5d0 \ud655\uc778\ud588\uc744 \ub550 2022\ub144 12\uc6d4 31\uc77c\uae4c\uc9c0 EC2 ARM \uae30\ubc18 t4g.small\uc774 \ubb34\ub8cc\uc600\ub294\ub370, \ub2e4\uc2dc \ub4e4\uc5b4\uac00 \ubcf4\ub2c8 2023\ub144\uae4c\uc9c0 12\uc6d4 31\uc77c\uae4c\uc9c0 t4g.small\uc744 \ubb34\ub8cc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\ub2e4. \\nt4g.small\uc740 \ub7a8\uc774 2G\uc778\ub370, \uc608\uc804\uc5d0\ub294 \ubd80\uc871\ud558\uc9c0 \uc54a\uc558\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370 Java 17\uc744 \uc368\uc11c \uadf8\ub7f0\uac00 \ube4c\ub4dc \ud560 \ub54c \ub7a8\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\uc544\uc11c Swap \uba54\ubaa8\ub9ac 2\uae30\uac00\ub97c \ucd94\uac00\ub85c \uc124\uc815\ud588\ub2e4. \\n\ucd94\uac00\ub85c build.gradle\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8 \uc2dc \uc0ac\uc6a9\ud558\ub294 \ub7a8\uc744 \ub298\ub9b4 \uc218 \uc788\ub2e4. \uae30\ubcf8\uac12\uc740 512MB\ub77c\uace0 \ud55c\ub2e4. \\n\\n```groovy\\ntest {\\n maxHeapSize = \\"1024m\\"\\n}\\n```\\n\\n### Jenkins Blue Ocean\\n\\nBlue Ocean\uc740 Jenkins Pipeline\uc744 \uad6c\uc131\ud558\ub294 \ub370\uc5d0 \uc788\uc5b4 \ud3b8\ub9ac\ud558\uac8c \ud574\uc8fc\ub294 \ub3c4\uad6c\ub2e4. \\n\uc2dc\uac01\ud654\ub3c4 \uc798 \ub418\uc5b4\uc788\uace0, \uc124\uc815\ub3c4 \ud3b8\ub9ac\ud55c \uac83 \uac19\ub2e4. \\n\uc624\ub298 \uc801\uc6a9\ud574 \ubcf4\ub2c8 \ub7a8\uc774 \ubd80\uc871\ud558\uc5ec \uc911\uac04\uc5d0 \uc798 \uc548\ub418\uae30\ub3c4 \ud558\uace0 \uadf8\ub798\uc11c \uadf8\ub0e5 \\"Pipeline\ub9cc \uc0ac\uc6a9\ud560 \uac78 \uadf8\ub7ac\ub098?\\" \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Elastic Beanstalk, AWS](https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/Welcome.html) \\n[EC2 AWS Graviton, AWS](https://aws.amazon.com/ko/ec2/graviton/) \\n[Default Memory Settings, AWS](https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings)"},{"id":"web-racing-car-retrospective","metadata":{"permalink":"/web-racing-car-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-racingcar/pull/24","date":"2023-05-02T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 2\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.6,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","slug":"web-racing-car-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","permalink":"/tecochat-retrospective-2"},"nextItem":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","permalink":"/shopping-cart-retrospective"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-racingcar/pull/24 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-racingcar/pull/128 \\n:::\\n\\n### \uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\\n\\n\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud55c\ub2e4\uace0 \uc2dc\uac04\uc774 \ub9ce\uc774 \uc5c6\uc5b4\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc84c\ub2e4. \\n\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\uc5d0\uc11c\ub294 \ube44\ubc84\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\ub808\ubca8 2\uc5d0\uc11c \uc9c4\ud589\ud558\ub294 \uccab \ubbf8\uc158\uc774\ub77c \ub9ce\uc774 \uae34\uc7a5\ub418\uc5c8\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ube44\ubc84\ub791 \ucd08\ubc18\uc5d0 \ub9db\uc788\ub294 \uac83\ub3c4 \ub9ce\uc774 \uba39\uc73c\uba74\uc11c \ube68\ub9ac \uce5c\ud574\uc838\uc11c \uc7ac\ubc0c\uac8c \ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\uc2a4\ud504\ub9c1\uc744 \uc870\uae08 \uc0ac\uc6a9\ud560 \uc904 \uc54c\uc544\uc11c, \ube44\ubc84\ub791 \uac19\uc774 \ud559\uc2b5\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\uccab \ubbf8\uc158\uc774\ub77c \uadf8\ub7f0\uc9c0 \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc740 \uc5c6\uc5c8\uace0, \ucd5c\ub300\ud55c \uae54\ub054\ud558\uac8c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ub09c\uc774\ub3c4 \ub192\uc740 \ubbf8\uc158\uc774 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ub9ac\ubdf0\uc5b4\uc778 \ub77c\ube48\uc5d0\uac8c \uce6d\ucc2c\uc744 \ub9ce\uc774 \ubc1b\uc544\uc11c \uae30\ubd84\uc774 \uc88b\uc558\ub2e4. \\n\ub77c\ube48 \uac10\uc0ac\ud569\ub2c8\ub2e4! \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ucee8\ub514\uc158\ub3c4 \uc88b\uc9c0 \uc54a\uace0 \uc5f4\uc815\ub3c4 \uc2dd\uc740 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4. \\n\ubbf8\uc158\uc774 \ub2e4\uc18c \uc5ec\uc720\ub86d\ub2e4\uace0 \ub290\uaef4\uc838\uc11c, \uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ubd84\ub3c4 \uc798 \uad00\ub9ac\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4. \\n\ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud574\uc11c \ud398\uc5b4\uc5d0\uac8c \ub9ce\uc774 \ubbf8\uc548\ud588\uace0, \ub098 \uc790\uc2e0\uc5d0\uac8c \uc544\uc26c\uc6e0\ub358 \ubd80\ubd84\uc774 \ub9ce\uc558\ub2e4. \\n\\n\uc9c0\ub09c\ubc88 \ud68c\uace0\ub97c \ub2e4\uc2dc \ubcf4\ub294\ub370 \uc9d1\uc911\uc744 \uc798 \ubabb\ud55c \uacbd\uc6b0\uac00 \ub9ce\uc740 \uac83 \uac19\ub2e4. \\n\ub3c4\uc804\uc801\uc774\uc9c0 \uc54a\uac70\ub098 \uc2dc\uac04\uc774 \ubd80\uc871\ud558\uc9c0 \uc54a\uc73c\uba74 \uc9d1\uc911\uc744 \uc798 \ubabb\ud558\ub294 \uac83 \uac19\ub2e4. \\n\uba38\ub9bf\uc18d\uc5d0\uc11c \uc2dc\uac04\uc801 \uc5ec\uc720\uac00 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \ub54c\uac00 \uac00\uc7a5 \uc704\ud5d8\ud55c \uc21c\uac04\uc778 \uac83 \uac19\ub2e4. \\n\\n\ud568\uaed8 \uc790\ub77c\uae30\uc5d0\uc11c \ub098\uc628 `\ub09c\uc774\ub3c4 \ub192\uc774\uae30`\uac00 \ud544\uc694\ud574\uc9c0\ub294 \uc21c\uac04\uc774\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uc911\uc694\ub3c4\uac00 \uc788\ub294 \uc5b4\ub178\ud14c\uc774\uc158\ubd80\ud130 \ud074\ub798\uc2a4 \uc774\ub984\uc5d0 \uac00\uae5d\uac8c \uba85\uc2dc\ud558\uae30**\\n\\n```java\\n@SuppressWarnings(\\"NonAsciiCharacters\\")\\n@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)\\n@Transactional\\n@AutoConfigureMockMvc\\n@SpringBootTest\\npublic class RacingGameIntegrationTest {\\n```\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\ube44\ubc84\uc758 \uc131\uaca9** \\n\ube44\ubc84\uac00 \uc131\uaca9\uc774 \uc88b\uc544\uc11c \ud3b8\ud558\uac8c \ud398\uc5b4\ub97c \ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc131\uae09\ud558\uc9c0 \uc54a\uace0 \uc5ec\uc720\ub85c\uc6cc\uc11c \uc88b\uc558\ub2e4. \\n\\n**\ubbf8\uc158\uc5d0 \uc9d1\uc911\ud558\ub294 \ubd80\ubd84** \\n\ub0b4\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud588\ub294\ub370\ub3c4 \uac19\uc774 \ud398\uc5b4\ub97c \uc798 \uc9c4\ud589\ud55c \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ube44\ubc84\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud574\uc11c \uadf8\ub807\uc9c0 \uc54a\uc558\ub098 \uc0dd\uac01\ud588\ub2e4. \\n\uadfc\uc721\ub9e8 \ube44\ubc84\ub77c \uadf8\ub7f0\uc9c0 \uccb4\ub825\uc774 \uc88b\uc544\uc11c \uadf8\ub7f0\uac00? \\n\uc911\uac04\uc5d0 \uc798 \uc548 \uc26c\uace0\ub3c4 \uc9d1\uc911\ud574\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac78 \ubcf4\uace0 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n**\ud559\uc2b5\uc5d0 \ub300\ud55c \uc5f4\uc815** \\n\ucd94\uac00\uc801\uc73c\ub85c \uc54c\uace0 \uc2f6\uc740 \ubd80\ubd84\uc744 \ub530\ub85c \ud559\uc2b5\ud558\ub294 \uc5f4\uc815\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ube44\ubc84\uc640 \uc2a4\ud504\ub9c1\uc5d0 \ub300\ud574 \uc54c\uc544\uac00\ub294 \uc2dc\uac04\uc744 \ub9ce\uc774 \uac00\uc9c4 \ubd80\ubd84\uc774 \ub9e4\uc6b0 \uc88b\uc558\ub2e4. \\n\ub098\ub3c4 5\uc6d4\ubd80\ud130 \uc870\uae08 \ub354 \ud654\uc774\ud305 \ud574\uc57c\uaca0\ub2e4."},{"id":"shopping-cart-retrospective","metadata":{"permalink":"/shopping-cart-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-shopping-cart/pull/244","date":"2023-05-12T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 12\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.845,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","slug":"shopping-cart-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","permalink":"/web-racing-car-retrospective"},"nextItem":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","permalink":"/accidental-duplication"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-shopping-cart/pull/244 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-shopping-cart/pull/300 \\n:::\\n\\n### \uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\\n\\n\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc740 \ube14\ub799\ucea3\uc774\ub791 \uc9c4\ud589\ud588\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d\uc774 \uc5c4\uccad \ubcf5\uc7a1\ud55c \ubbf8\uc158\uc740 \uc544\ub2c8\uc5c8\uace0, \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\ubcf8\uc801\uc778 CRUD\ub97c \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n2\ub2e8\uacc4\uc5d0\uc11c\ub294 Basic \uc778\uc99d\uc744 \ud1b5\ud574 \uc790\uc2e0\uc758 \uc7a5\ubc14\uad6c\ub2c8\uc5d0\ub9cc \uc0c1\ud488\uc744 \ub2f4\uace0, \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \uad6c\ud604\ud558\ub294 \uc694\uad6c\uc0ac\ud56d\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\nInterceptor\ub098 Argument Resolver\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\uac00 \ub192\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc870\uae08 \ub354 \uc54c\uc544\uac04 \ub290\ub08c\uc774\ub2e4. \\n\uc774\uc804\uc5d0 \uc2a4\ud504\ub9c1 \uc0ac\uc6a9\ud560 \ub54c\ub294 \uc544\ubb34 \uc0dd\uac01 \uc5c6\uc774 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub294\ub370, \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \ub54c \uadfc\uac70\uac00 \uc0dd\uae30\uace0 \uc788\ub294 \uac83 \uac19\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**DTO \uc6b0\ubc1c\uc801 \uc911\ubcf5**\\n\\n\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\\n![dto1](./dto1.png)\\n\\n\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d \ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0 \uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\uc744 \ud588\uace0, \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4. \\n\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec \uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4. \\n\\n- \uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n- \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4.\\n\\n\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131 \uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4. \\n\ub530\ub77c\uc11c \ub9ac\ubdf0\uc5b4 \uc6e8\uc9c0\uac00 \uc544\ub798\uc640 \uac19\uc774 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\uace0 \uc54c\ub824\uc8fc\uc168\ub2e4. \\n\\n![dto2](./dto2.png)\\n\\n**Interceptor\uc5d0\uc11c \uc778\uc99d\ud55c \uac12 \uc7ac\uc0ac\uc6a9**\\n\\n\uc0ac\uc2e4 \uc870\ud68c\ub97c \ub450 \ubc88 \ud558\uae30 \uc2eb\uc5b4\uc11c \ub2e4\uc591\ud55c \ubc29\ubc95\uc744 \uc0dd\uac01\ud588\uc5c8\ub294\ub370 \uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 ThreadLocal\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n\uc77c\ub2e8 Tomcat\uc740 \uc694\uccad\ub9c8\ub2e4 \ub2e4\ub978 \uc2a4\ub808\ub4dc\ub97c \uc0ac\uc6a9\ud558\uace0, Interceptor\uc5d0\uc11c \uc870\ud68c\ud574\uc11c \ub9cc\ub4e0 Credential\uc744 ThreadLocal\uc5d0 \ub123\uc5b4\ub450\uc5c8\ub2e4\uac00 ArgumentResolver\uc5d0\uc11c \uaebc\ub0b8 \ub2e4\uc74c ThreadLocal\uc744 clear \ud558\uba74 \ubb38\uc81c\uac00 \uc5c6\uc744 \uac70\ub77c \ud310\ub2e8\ud588\ub2e4. \\n\\n\ub9ac\ubdf0\uc5b4\uc778 \uc6e8\uc9c0\uc5d0\uac8c\ub3c4 \uc5b4\ub5a4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560\uc9c0 \uad81\uae08\uc99d\uc744 \uc791\uc131\ud588\uc5c8\ub2e4. \\n\uc6e8\uc9c0\ub294 email\uc5d0 index\ub97c \uac78\uc5b4\ub450\uace0 dao \uc7ac\uc870\ud68c\ub97c \uc0ac\uc6a9\ud560 \uac83\uc774\ub77c\uace0 \ud588\ub2e4. \\n\uc7ac\uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 db\uc5d0 \uc778\ub371\uc2a4\ub97c \uac78 \uc0dd\uac01\uc740 \ud558\uc9c0 \ubabb\ud588\ub294\ub370, \uc81c\uc77c \uc9c1\uad00\uc801\uc774\uace0 \uc88b\uc740 \ubc29\ubc95\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uae30\ub85d**\\n\\n\ube14\ub799\ucea3\uc740 \uae30\ub85d\uc744 \uad49\uc7a5\ud788 \uc798 \ud558\ub294 \ud06c\ub8e8\uc600\ub2e4. \\n\ub178\uc158\uc5d0 \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ud588\ub358 \ub0b4\uc6a9 + \uace0\ubbfc\ud588\ub358 \ubd80\ubd84 + \ud68c\uace0\ub97c \uaf3c\uaf3c\ud558\uac8c \uae30\ub85d\ud574\uc11c \uacf5\uc720\ud574 \uc8fc\uc5c8\ub2e4. \\n\ucd94\uac00\uc801\uc73c\ub85c \uc774\ubaa8\uc9c0\ub97c \uc801\uadf9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uc5ec \ub354\uc6b1 \uc88b\uc558\ub2e4!\\n\\n**\uc758\uacac \uc77c\uce58\uc2dc\ud0a4\uae30**\\n\\n\ud398\uc5b4 \uc2dc\uac04\uc740 \ud55c\uc815\ub418\uc5b4 \uc788\uace0, \uae30\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574\uc57c \ud55c\ub2e4. \\n\ub530\ub77c\uc11c \uc801\ub2f9\ud788 \ud0c0\ud611\uc744 \ubd10\uc11c \uc758\uacac\uc744 \ube60\ub974\uac8c \uc218\uc6a9\ud574 \ub370\ub4dc\ub77c\uc778\uc744 \ub9de\ucd94\ub294 \uac83\ub3c4 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ube14\ub799\ucea3\uc740 \ub0b4 \uc758\uacac\uc744 \uc798 \ub4e4\uc5b4\uc92c\uace0, \ub355\ubd84\uc5d0 \ub9c9\ud788\ub294 \ubd80\ubd84 \uc5c6\uc774 \ube60\ub974\uac8c \ubbf8\uc158\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\ube68\ub9ac \uce5c\ud574\uc84c\uace0, \uc758\uc0ac\uc18c\ud1b5\uc774 \uc798 \ub3fc\uc11c \uc7ac\ubc0c\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uc5c8\ub2e4!"},{"id":"accidental-duplication","metadata":{"permalink":"/accidental-duplication","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx","source":"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx","title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","description":"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.","date":"2023-05-24T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 24\uc77c","tags":[{"label":"DTO","permalink":"/tags/dto"}],"readingTime":7.525,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","slug":"accidental-duplication","tags":["DTO"]},"unlisted":false,"prevItem":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","permalink":"/shopping-cart-retrospective"},"nextItem":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","permalink":"/subway-retrospective"}},"content":"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\uc694\uccad\uc5d0 \ub2f4\uae34 Body\ub97c \ud1b5\ud574 \uc804\ub2ec\ubc1b\uc740 \uac12\uc744 DTO\ub85c \ub9e4\ud551\ud558\uc5ec \ucd94\uac00\uc640 \uc218\uc815\uc744 \ud588\ub2e4.\\n\\n### \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815\\n\\n![\uc911\ubcf51](./\uc911\ubcf51.png)\\n\\n\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d\ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0\uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4. \\n\uc704 \uacbd\uc6b0\ub294 \uc911\ubcf5\uc77c\uae4c? \uc911\ubcf5\uc774 \uc544\ub2d0\uae4c?\\n\\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ub9ac\ubdf0\ub97c \ubc1b\uc558\ub2e4.\\n\\n> `ProductSaveRequest`\uc640 `ProductUpdateRequest`\uac00 \uc644\uc804\ud788 \ub3d9\uc77c\ud55c\ub370, \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc744\uae4c? \ub77c\ub294 \ub9ac\ubdf0\ub97c \ub0a8\uacbc\uc5c8\uc5b4\uc694. \uc0ac\uc2e4 \uc0dd\uc131\uacfc \uc218\uc815\uc740 \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac1c\uc5f0\uc131\uc774 \ub192\uc544\uc11c \ubbf8\ub9ac \ubd84\ub9ac\ud574\ub193\ub294 \uac8c \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\uae34 \ud55c\ub370, \uadf8\ub798\ub3c4 \uc911\ubcf5\uc740 \uc2eb\uc5b4\uc11c \uc800\ub3c4 \uc694\uc998 \uc774\ub7f0\uc800\ub7f0 \ubc29\ubc95\ub4e4\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub294 \uc911 \uc785\ub2c8\ub2e4. \ud5c8\ube0c\ub294 \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc5b4\ub5a4 \uc0dd\uac01\uc744 \uac00\uc9c0\uace0 \uc788\uc744\uc9c0 \uad81\uae08\ud558\ub124\uc694 \u314e\u314e\\n> \\n\\n\uc9c8\ubb38\uc5d0 \ub300\ud574 \uc544\ub798\uc640 \uac19\uc774 \ub2f5\ubcc0\uc744 \ud588\ub2e4.\\n\\n> \uc800\uc7a5\uacfc \uc218\uc815\ud560 \ub54c \ud544\uc694\ud55c \ud544\ub4dc\uac12\uc774 \ub3d9\uc77c\ud558\uc5ec \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c\ub294 \ud558\ub098\ub85c \uc0ac\uc6a9\ud574\ub3c4 \ub41c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud558\uc9c0\ub9cc, \ub9d0\uc500\ud574\uc8fc\uc2e0\ub300\ub85c \uc694\uad6c\uc0ac\ud56d\uc774 \ubcc0\uacbd\ub41c\ub2e4\uba74 \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\ub2e4\uace0 \ud310\ub2e8\ud558\uc600\uc2b5\ub2c8\ub2e4!\\n> \\n\\n### \uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5\\n\\n\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec\uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4.\\n\\n- \uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n- \uac70\uc9d3\ub41c \uc911\ubcf5, \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4.\\n\\n\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131\uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.\\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc704 \uc0c1\ud669\uc740 \uc6b0\ubc1c\uc801 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc778\ub2e4. \uadf8\ub798\ub3c4 \uc911\ubcf5\uc744 \uc81c\uac70\ud574\ubcfc \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?\\n\\n### \ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\\n\\n\uc9c0\uae08\uc740 \ucd94\uac00, \uc218\uc815 2\uac00\uc9c0 \uacbd\uc6b0 \ubc16\uc5d0 \uc5c6\uc9c0\ub9cc \uc870\uae08 \ub354 \ubcf5\uc7a1\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc8fc\uc5b4\uc838\uc11c 10\uac00\uc9c0 \uacbd\uc6b0\ub85c \uc785\ub825\uc744 \ubc1b\uc73c\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c? \\n\uc11c\ube44\uc2a4 \uacc4\uce35\uc5d0\uc11c\ub3c4 \uacc4\uce35\uc758 \ubd84\ub9ac\ub97c \uc704\ud574\uc11c \ub2e4\ub978 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uba74 20\uac1c\uc758 DTO\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud560\uae4c? \\n\ub9ac\ubdf0\uc5b4\uac00 \uc54c\ub824\uc900 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud55c \ubc29\ubc95\uc744 \ud1b5\ud574 \uc774\ub97c \ud574\uacb0\ud574\ubcf4\uc790! \\n\\n### \uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc\\n\\n\ud604\uc7ac \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\ub2e4. \\nController\uc640 Service\uc5d0\uc11c \uc800\uc7a5, \uc218\uc815\ud560 \ub54c \uac01\uac01\uc758 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.\\n\ud604\uc7ac DTO\ub294 controller, service \ud328\ud0a4\uc9c0 \ub0b4\uc5d0 \uc788\ub294 \uac83\uc774 \uc544\ub2c8\ub77c dto\ub77c\ub294 \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\ud558\uace0 \uc788\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductService\\n\u251c\u2500\u2500 dto\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n![\uc911\ubcf52](./\uc911\ubcf52.png)\\n\\n### \uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30\\n\\n![\uc911\ubcf53](./\uc911\ubcf53.png)\\n\\n\uc11c\ube44\uc2a4 \ub808\uc774\uc5b4\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uac12\ub4e4\uc744 \uc778\ud130\ud398\uc774\uc2a4\ub85c \uc815\uc758\ud55c\ub2e4. \\n\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 service \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub85c \uc62e\uaca8\uc900\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n```java\\npublic interface ProductSaveRequest {\\n\\n String getName();\\n\\n String getImage();\\n\\n Long getPrice();\\n}\\n\\n// ProductService\\npublic Long save(final ProductSaveRequest request) {\\n final Product product = new Product(request.getName(), request.getImage(), request.getPrice());\\n return productDao.saveAndGetId(product);\\n}\\n```\\n\\n### \uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30\\n\\n![\uc911\ubcf54](./\uc911\ubcf54.png)\\n\\n\uc704\uc5d0\uc11c \uc791\uc131\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc791\uc131\ud55c\ub2e4. \\n\uc694\uccad\uc740 ProductRequest \ud074\ub798\uc2a4\ub85c \ubc1b\uace0, \uc11c\ube44\uc2a4\uc5d0 \uc804\ub2ec\ud560 \ub550 \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\uc758 \uba85\uc138\ub9cc \ub9de\ucd94\uba74 \ubb38\uc81c\uc5c6\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductController\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductRequest\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n```java\\npublic class ProductRequest implements ProductSaveRequest, ProductUpdateRequest {\\n\\n @NotBlank(message = \\"\uc774\ub984\uc740 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\")\\n @Size(min = 1, max = 100, message = \\"\uc774\ub984\uc740 \ucd5c\uc18c {min}\uc790 \uc774\uc0c1, {max}\uc790 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.\\")\\n private final String name;\\n\\n @NotBlank(message = \\"\uc774\ubbf8\uc9c0\ub294 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\")\\n private final String image;\\n\\n @Range(message = \\"\uac00\uaca9\uc740 \ucd5c\uc18c {min}\uc6d0 \uc774\uc0c1, {max}\uc6d0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.\\")\\n private final long price;\\n\\n public ProductRequest(final String name, final String image, final long price) {\\n this.name = name;\\n this.image = image;\\n this.price = price;\\n }\\n\\n @Override\\n public String getName() {\\n return name;\\n }\\n\\n @Override\\n public String getImage() {\\n return image;\\n }\\n\\n @Override\\n public long getPrice() {\\n return price;\\n }\\n}\\n\\n// ProductController\\n@PostMapping(\\"/products\\")\\npublic ResponseEntity save(@Valid @RequestBody final ProductRequest request) {\\n final Long id = productService.save(request);\\n return ResponseEntity.created(URI.create(\\"/products/\\" + id)).build();\\n}\\n```\\n\\n### \uc815\ub9ac\\n\\n\uc704\uc640 \uac19\uc774 \uad6c\ud604\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\ub2e4. \\n\\n1. Service\uc5d0\uc11c \ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc5d0 \ub300\ud55c DTO\ub97c \uc54c\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.\\n2. \uacf5\ud1b5\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 DTO\ub97c \uc81c\uc678\ud558\uace0 DTO \ud328\ud0a4\uc9c0\uc5d0 \ub300\ud55c \uacb0\ud569\ub3c4\uac00 \ub0ae\uc544\uc9c0\uace0, \uac01 \ub808\uc774\uc5b4\uc758 \uc751\uc9d1\ub3c4\uac00 \uc99d\uac00\ud55c\ub2e4.\\n3. \uc694\uccad \uac1d\uccb4\ub9cc \ub2e4\ub974\uace0 \uc11c\ube44\uc2a4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ud589\uc704\ub97c \uc218\ud589\ud558\ub294 \uacbd\uc6b0 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc704 \ubc29\ubc95\uc744 \uc9c0\uae08 \ubbf8\uc158\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560\uae4c \ud558\ub2e4\uac00, \ub098\uc911\uc5d0 \ud544\uc694\ud560 \ub54c \uc801\uc6a9\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\uc544\uc11c \ubbf8\uc158\uc5d0\ub294 \uc801\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\uc0c1\ud669\uc5d0 \ub9de\ucdb0 \uc801\uc7ac\uc801\uc18c\uc5d0 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud574\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98 16\uc7a5 \ub3c5\ub9bd\uc131, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 \\n[https://techblog.woowahan.com/2647/](https://techblog.woowahan.com/2647/) \\n[https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/](https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/)"},{"id":"subway-retrospective","metadata":{"permalink":"/subway-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-subway-path/pull/16","date":"2023-05-25T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 25\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.98,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","slug":"subway-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","permalink":"/accidental-duplication"},"nextItem":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","permalink":"/composite"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-subway-path/pull/16 \\n2, 3\ub2e8\uacc4: https://github.com/woowacourse/jwp-subway-path/pull/126 \\n:::\\n\\n### \uc9c0\ud558\ucca0 \ubbf8\uc158\\n\\n\uc810\uc810 \uc77c\uc815\uc774 \ub9ce\uc544\uc9c0\ub294 \ub290\ub08c\uc774 \ub4e4\uba74\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc9c4\ub2e4. \\n\uc9c0\ud558\ucca0 \ubbf8\uc158\uc740 \ubc00\ub9ac\ub791 \ud398\uc5b4\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\uac04\ub2e8\ud55c CRUD\ub9cc \uc788\ub358 \uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac, \uc870\uae08 \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\uc774\ub54c API, \ud14c\uc774\ube14, \ub3c4\uba54\uc778 \uc124\uacc4\ub97c \ud574\uc57c \ud588\ub294\ub370 \uc5b4\ub5a4 \uac83\ubd80\ud130 \ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\nAPI\uc640 \ud14c\uc774\ube14 \uad6c\uc870\ub97c \uc6b0\ub9ac\uac00 \uc815\ud560 \uc218 \uc788\ub294 \uc0c1\ud669\uc774\uc5c8\uace0, \ub3c4\uba54\uc778 \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \ub3c4\uba54\uc778\uc744 \uba3c\uc800 \uad6c\ud604\ud588\ub2e4.\\n\\n**\ub178\uc120\uc758 \uad6c\uac04 \ucd94\uac00 \ubc0f \uc0ad\uc81c**\\n\\n\ub178\uc120\uc744 \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \ubc00\ub9ac\uc640 \uc774\uc57c\uae30\ub97c \ub098\ub234\ub2e4.\\n\\n1. \uad6c\uac04\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc804\ubd80 \uc81c\uac70\ud558\uace0 \uc804\ubd80 \ucd94\uac00\ud558\ub294 \ubc29\ubc95\\n2. \ubcc0\uacbd\ub41c \uc694\uc18c\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ubc18\uc601\ud558\ub294 \ubc29\ubc95\\n\\n\ud398\uc5b4 \uc2dc\uac04\uc774 \uc9e7\uc544\uc11c \ub354\uc6b1 \uac04\ub2e8\ud55c 1\ubc88\uc744 \uc120\ud0dd\ud588\uace0, \uc2dc\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0a4\uae30 \uc704\ud574 \ub354 \uac04\ub2e8\ud558\uac8c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud558\ub294 \uac83\ub3c4 \uc88b\uc740 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\uc600\ub358 \uac83 \uac19\ub2e4. \\n\ucd94\ud6c4 \ud398\uc5b4\uac00 \ub05d\ub098\uace0 \ub9ac\ubdf0\uc5b4\uc778 \uc11c\ube0c\uc6e8\uc774\uac00 \uc77c\ubd80\ubd84\ub9cc \ubc18\uc601\ud558\ub294 \uac83\uc73c\ub85c \uac1c\uc120\ud574 \ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4\uace0 \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c \uc694\uc18c\ub9cc \ubc18\uc601\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ubbf8\uc158\uc758 \ub09c\uc774\ub3c4\uac00 \uc62c\ub77c\uac04 \ub9cc\ud07c, \ud398\uc5b4 \ud560 \ub550 \ucee8\ub514\uc158 \uad00\ub9ac\ub3c4 \uc798\ud558\ub824\uace0 \ub178\ub825\ud558\uace0 \ubbf8\uc158 \ud560 \ub54c\ub3c4 \uc9d1\uc911\ud574\uc11c \uc798 \ub05d\ub0b8 \uac83 \uac19\ub2e4. \\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc54c\uc544\uc57c \ud558\ub294 \uac8c \ub9ce\uc544\uc9c0\uba74\uc11c \uac00\ub054 \uc870\ubc14\uc2ec\uc744 \uac00\uc9c8 \ub54c\uac00 \uc788\ub294 \uac83 \uac19\uc740\ub370, \uc870\ubc14\uc2ec\uc744 \uacbd\uacc4\ud560 \ud544\uc694\uac00 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ubd80\uc871\ud55c \ubd80\ubd84\uc740 \uc778\uc815\ud558\uace0, \uc55e\uc73c\ub85c \ub098\uc544\uac00\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654**\\n\\n\uc694\uae08 \uc815\ucc45\uc740 \uae30\ubcf8\uc694\uae08 \uc815\ucc45, \uac70\ub9ac\ubcc4 \uc694\uae08 \uc815\ucc45, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc774 \uc788\uc5c8\ub2e4. \\n\uc694\uae08\uc744 \ub354\ud558\ub294 \ubd80\ubd84\uacfc, \ud560\uc778\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5b4\uc11c \uc774 \ub458\uc744 \ubd84\ub9ac\ud560\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc, \uc774 \uc815\ub3c4 \ud06c\uae30\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc624\ud788\ub824 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uace0 \ud558\ub098\ub85c \ud569\uce58\ub294 \uac8c \ub354 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub610\ud55c \ubd84\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \uc815\ucc45\uc758 \uc21c\uc11c\uac00 \uc911\uc694\ud55c\ub370, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc744 \ub9c8\uc9c0\ub9c9\uc5d0 \ub450\uc5b4\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ucc45\uc784 \uc5f0\uc1c4 \ud328\ud134\ub3c4 \uace0\ub824\ub97c \ud588\uc9c0\ub9cc \uc870\uae08 \ub354 \uac04\uacb0\ud574 \ubcf4\uc774\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \uc120\ud0dd\ud588\ub2e4.\\n\\n**\ub3c4\uba54\uc778\uc5d0 \ud2b9\uc815 \uae30\uc220\uc758 \uc758\uc874\uc131\uc744 \ubd84\ub9ac**\\n\\n\ucc98\uc74c\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uc5d0 jgrapht \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc758\uc874\ud558\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \ub450\uc5b4\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uac00 jgrapht\uc640 \uac15\uacb0\ud569\uc774 \ub418\uc5b4\ubc84\ub838\ub2e4. \\n\ub530\ub77c\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\uc5d0\ub294 \uacbd\ub85c \uac80\uc0c9\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0, \uc138\ubd80 \uad6c\ud604\uc740 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \uc678\ubd80\ub85c \ubd84\ub9ac\ud588\ub2e4. \\n\ucd5c\ub300\ud55c \uac04\uacb0\ud558\uac8c \uad6c\ud604\ud55c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud574\ub3c4, \uc774\ub7f0 \ubd80\ubd84\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uc5b4 \uacb0\ud569\uc744 \ud53c\ud558\ub294 \uac83\uc774 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n:::note \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4. \\n\uc774\ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n:::\\n\\n**\uc778\uc218 \ud14c\uc2a4\ud2b8 \uc791\uc131**\\n\\n\uc778\uc218 \ud14c\uc2a4\ud2b8\ub294 \uc0ac\uc6a9\uc790 \uc2a4\ud1a0\ub9ac \uc2dc\ub098\ub9ac\uc624 \uae30\ubc18 \ud14c\uc2a4\ud2b8\ub2e4. \\n\ube0c\ub77c\uc6b4\uc774 \ud574\uc8fc\uc2e0 \uac15\uc758 + \uc720\ud29c\ube0c\uc5d0 \uc788\ub294 \ube0c\ub77c\uc6b4\uc758 \uac15\uc758\ub97c \ubcf4\uace0 \uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0 \uc778\uc218 \ud14c\uc2a4\ud2b8\ub97c \uc801\uc6a9\ud574 \ubcf4\uc558\ub2e4. \\n\uba54\uc11c\ub4dc, \ubcc0\uc218\uba85\uc744 \uc804\ubd80 \ud55c\uae00\ub85c \uc791\uc131\ud588\ub294\ub370 \uc804\uccb4\uc801\uc778 \ud750\ub984\uc744 \uc54c\uae30 \ud3b8\ud558\uace0 \uc77d\uae30\ub3c4 \uc88b\uc558\ub2e4. \\n\uadf8\ub9ac\uace0 \uc778\uc218 \ud14c\uc2a4\ud2b8\uc5d0 \ud544\uc694\ud55c Steps\ub97c \ub9cc\ub4dc\ub294 \uacfc\uc815\uc774 \ub108\ubb34 \uc7ac\ubc0c\uc5c8\ub2e4.\\n\\n\uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4.\\n\\n```java\\n@Nested\\npublic class \ub178\uc120\uc744_\uc804\uccb4_\uc870\ud68c\ud560_\ub54c {\\n\\n @Test\\n void \uc0c1\ud589\uc885\uc810\uc5ed_\ubd80\ud130_\ud558\ud589\uc885\uc810\uc5ed\uc73c\ub85c_\uc815\ub82c\ub41c_\uacb0\uacfc\ub97c_\ubc18\ud658\ud55c\ub2e4() {\\n // given\\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\ucd08\ub85d\\", 0);\\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\uc7a0\uc2e4\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", 5);\\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \uc624\ub978\ucabd, 5);\\n\\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\uace0\ub3d9\\", 0);\\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\ubd09\uc740\uc0ac\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", 3);\\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \\"\uc0bc\uc804\\", \uc624\ub978\ucabd, 7);\\n\\n // when\\n final var \uc870\ud68c_\uacb0\uacfc = \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uc694\uccad();\\n\\n // then\\n \uc694\uccad_\uacb0\uacfc\uc758_\uc0c1\ud0dc\ub97c_\uac80\uc99d\ud55c\ub2e4(\uc870\ud68c_\uacb0\uacfc, \uc815\uc0c1_\uc694\uccad);\\n \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uacb0\uacfc\ub97c_\ud655\uc778\ud55c\ub2e4(\\n \uc870\ud68c_\uacb0\uacfc,\\n \ub178\uc120_\uc815\ubcf4(\\"2\ud638\uc120\\", \\"\ucd08\ub85d\\", 0, \\"\uc7a0\uc2e4\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\"),\\n \ub178\uc120_\uc815\ubcf4(\\"9\ud638\uc120\\", \\"\uace0\ub3d9\\", 0, \\"\ubd09\uc740\uc0ac\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \\"\uc0bc\uc804\\")\\n );\\n }\\n}\\n```\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uc758\uacac \uc870\uc728\ud558\uae30**\\n\\n\ubc00\ub9ac\uac00 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\uc11c \uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \uc9c4\ud589\uc774 \uc218\uc6d4\ud588\ub2e4. \\n\uc758\uc0ac\uc18c\ud1b5\uc774 \ub9e4\uc6b0 \uc798 \ub3fc\uc11c \uc88b\uc558\uace0 \ub355\ubd84\uc5d0 \uc2dc\uac04 \ub0b4\uc5d0 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574 \ubbf8\uc158\uc744 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\\n**\uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\ud558\uae30**\\n\\n\ubc00\ub9ac\ub294 \ucf54\ub529\uc744 \uc5c4\uccad \uaf3c\uaf3c\ud558\uac8c \ud558\ub294 \uac83 \uac19\ub2e4. \\n\ubcc0\uc218\uba85, \uba54\uc11c\ub4dc\uba85\uc744 \uc911\uc694\ud558\uac8c \uc0dd\uac01\ud588\uace0, \uc88b\uc740 \ubcc0\uc218\uba85\uc744 \uc798 \uc9d3\ub294 \uac83 \uac19\ub2e4. \\n\ub610\ud55c \ucf54\ub529\ud560 \ub54c \ub0b4\uac00 \ud3c9\uc18c\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub529 \ucee8\ubca4\uc158\uc5d0 \ub9de\ucdb0\uc8fc\ub294 \uac83 \uac19\uc544\uc11c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud588\ub2e4! \\n\\n**\ud3b8\ud55c \ubd84\uc704\uae30**\\n\\n\uc804\uccb4\uc801\uc73c\ub85c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud558\uac8c \uc9c4\ud589\ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc77c\uc815\ub3c4 \uadf8\ub807\uace0, \ud398\uc5b4 \uc9c4\ud589\ud560 \ub54c\ub3c4 \uadf8\ub807\uace0 \ud070 \ubb38\uc81c\uac00 \uc5c6\uc5c8\ub358 \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ub098\ub294 \uacfc\uc5f0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \ud3b8\ud55c \uc0ac\ub78c\uc77c\uae4c?"},{"id":"composite","metadata":{"permalink":"/composite","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx","source":"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx","title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","description":"\uc694\uad6c\uc0ac\ud56d","date":"2023-05-26T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 26\uc77c","tags":[{"label":"Pattern","permalink":"/tags/pattern"},{"label":"Composite","permalink":"/tags/composite"}],"readingTime":4.74,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","slug":"composite","tags":["Pattern","Composite"]},"unlisted":false,"prevItem":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","permalink":"/subway-retrospective"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","permalink":"/tecochat-retrospective-3"}},"content":"### \uc694\uad6c\uc0ac\ud56d\\n\\n\uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.\\n\\n- \uac70\ub9ac\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45\\n- \ub178\uc120\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45\\n- \uc5f0\ub839\ubcc4 \uc694\uae08 \ud560\uc778 \uc815\ucc45\\n\\n### \uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9\\n\\n\uc694\uae08 \uc815\ucc45\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud45c\ud604\ud560 \uc218 \uc788\ub2e4. \\n\uc694\uae08\uc744 \uacc4\uc0b0\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ucd5c\ub2e8 \uacbd\ub85c \uacc4\uc0b0\uc758 \uacb0\uacfc, \uc0ac\uc6a9\uc790\uc758 \uc815\ubcf4, \uc694\uae08\uc744 \ubc1b\uc544 \uc694\uae08\uc744 \uacc4\uc0b0\ud55c\ub2e4.\\n\\n```java\\npublic interface FarePolicy {\\n int calculate(Path path, Passenger passenger, int fare);\\n}\\n\\npublic class BaseFarePolicy implements FarePolicy { ... }\\npublic class DistanceFarePolicy implements FarePolicy { ... }\\npublic class AgeDiscountFarePolicy implements FarePolicy { ... }\\n```\\n\\n![composite1](./composite1.png)\\n\\n### \ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30\\n\\n\ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub97c \ubaa8\ub450 \uac00\uc9c0\uace0 \uc788\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. \\n\uc774 \ub610\ud55c FarePolicy\ub97c \uad6c\ud604\ud55c \ud615\ud0dc\uac00 \ub418\uace0, \ud544\ub4dc\ub85c\ub294 \ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub4e4\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4.\\n\\n```java\\npublic class SubwayFarePolicy implements FarePolicy {\\n\\n private final List farePolicies;\\n\\n public SubwayFarePolicy(final List farePolicies) {\\n this.farePolicies = farePolicies;\\n }\\n\\n @Override\\n public int calculate(final Path path, final Passenger passenger, final int fare) {\\n int calculatedFare = fare;\\n for (FarePolicy farePolicy : farePolicies) {\\n calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);\\n }\\n return calculatedFare;\\n }\\n}\\n```\\n\\n\ub530\ub77c\uc11c \uadf8\ub9bc\uc73c\ub85c \ubcf8\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4.\\n\\n![composite2](./composite2.png)\\n\\n### \uc815\ucc45\uc758 \uc21c\uc11c\\n\\n\uc9c0\ud558\ucca0 \uc694\uad6c\uc0ac\ud56d\uc740 \uc21c\uc11c\uac00 \uc911\uc694\ud588\ub2e4. \\n\uae08\uc561\uc758 \ucd1d\ud569\uc744 \uad6c\ud558\uace0, \uadf8 \ud6c4\uc5d0 \ud560\uc778 \uc815\ucc45\uc774 \ub4e4\uc5b4\uac00\uc57c\ud588\ub2e4. \\n\ub530\ub77c\uc11c \uc790\uc2dd\ub4e4\uc758 \uc21c\uc11c\ub97c \uad00\ub9ac\ud560 \ub54c \uc8fc\uc758\ub97c \uae30\uc6b8\uc5ec\uc57c \ud588\ub2e4. \\nConfiguration \ud074\ub798\uc2a4\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc21c\uc11c\ub97c \uc9c1\uc811 \uc801\uc6a9\uc2dc\ucf30\ub2e4. \\n\\n```java\\n@Configuration\\npublic class FareConfiguration {\\n\\n @Bean\\n public FarePolicy farePolicy() {\\n return new SubwayFarePolicy(List.of(\\n new BaseFarePolicy(),\\n new DistanceFarePolicy(),\\n new AgeDiscountFarePolicy()\\n ));\\n }\\n}\\n```\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?\\n\\n![composite3](./composite3.png)\\n\\nGOF\uc758 \ub514\uc790\uc778 \ud328\ud134 \ucc45\uc5d0\uc11c\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uba85\ud558\uace0 \uc788\ub2e4.\\n\\n> \ubd80\ubd84\uacfc \uc804\uccb4\uc758 \uacc4\uce35\uc744 \ud45c\ud604\ud558\uae30 \uc704\ud574 \uac1d\uccb4\ub4e4\uc744 \ubaa8\uc544 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ud569\ub2c8\ub2e4. \\n\uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ubcf5\ud569 \uac1d\uccb4\ub97c \ubaa8\ub450 \ub3d9\uc77c\ud558\uac8c \ub2e4\ub8f0 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc785\ub2c8\ub2e4.\\n> \\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4. \\n\uc774 \ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c\\n\\nComponent\\n\\n- \uc9d1\ud569 \uad00\uacc4\uc5d0 \uc815\uc758\ub420 \ubaa8\ub4e0 \uac1d\uccb4\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4 \\n- ex) \uc694\uae08 \uc815\ucc45(FarePolicy) \\n\\nLeaf\\n\\n- \uac1c\ubcc4 \uac1d\uccb4, \uac1d\uccb4 \ud569\uc131\uc5d0 \uae30\ubcf8\uc774 \ub418\ub294 \uac1d\uccb4\uc758 \ud589\ub3d9 \\n- ex) \uac70\ub9ac \ubcc4 \uc694\uae08 \uc815\ucc45(DistanceFarePolicy) \\n\\nComposite\\n\\n- \uc5ec\ub7ec \uac1c\uc758 \uac1c\ubc1c \uac1d\uccb4\ub97c \ud3ec\ud568\ud558\ub294 \ud569\uc131 \uac1d\uccb4 \\n- ex) \uc9c0\ud558\ucca0 \uc694\uae08 \uc815\ucc45(SubwayFarePolicy) \\n\\nClient\\n\\n- \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c\\n\\n\ubd80\ubd84 - \uc804\uccb4\uc758 \uad00\uacc4\ub97c \ud45c\ud604\ud558\uace0 \uc2f6\uc744 \ub54c \\nClient \uae30\uc900\uc73c\ub85c Composite\uc640 Leaf\uc758 \ucc28\uc774\ub97c \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc798 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud574\uc57c\ub420 \ub54c\\n\\n### \ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84\\n\\n\ud328\ud134\uc740 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc758 \ud15c\ud50c\ub9bf\uc774\ub2e4. \\n\ubc18\ubcf5\ub418\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc788\uc9c0\ub9cc \ud328\ud134\uc5d0 \ub9e4\ubab0\ub418\uc11c\ub294 \uc548\ub41c\ub2e4. \\n\ud328\ud134\uc744 \ub9f9\ubaa9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548\ub418\uace0, \ud604\uc7ac\uc758 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub530\ub77c \ud328\ud134\uc744 \uc720\ub3d9\uc801\uc73c\ub85c \uc218\uc815\ud574\uac00\uba74\uc11c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\ud56d\uc0c1 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uc0dd\uac01\ud558\uc790!\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134, GoF\uc758 \ub514\uc790\uc778 \ud328\ud134 \\n\ub514\uc790\uc778 \ud328\ud134\uacfc \ud504\ub808\uc784\uc6cc\ud06c, \uc624\ube0c\uc81d\ud2b8"},{"id":"tecochat-retrospective-3","metadata":{"permalink":"/tecochat-retrospective-3","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx","source":"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx","title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","description":"\uac1c\uc694","date":"2023-06-01T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 1\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.005,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","slug":"tecochat-retrospective-3","tags":["TecoChat","Retrospective"]},"unlisted":false,"prevItem":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","permalink":"/composite"},"nextItem":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","permalink":"/order-retrospective"}},"content":"### \uac1c\uc694\\n\\n\uc6d0\ub798 \ubaa9\uc801\uc778 `\ud06c\ub8e8\ub4e4\uc758 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0`\uc744 \uc8fc\uae30 \uc704\ud574 \uc5b4\ub5a4 \uae30\ub2a5\uc744 \ucd94\uac00\ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\ub808\ubca8 2\uac00 \uac70\uc758 \ub05d\ub098\uac00\ub294 \uc2dc\uc810, \uadf8\ub3d9\uc548 \ud588\ub358 \uac83\uc744 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n### \ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5\\n\\nGPT\uc5d0\ub3c4 \uc788\ub294 \uae30\ub2a5\uc778\ub370, \ub0b4\uac00 \uc774\uc804\uc5d0 \ud588\ub358 \ucc44\ud305\uc744 \uc774\uc5b4\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\uc608\uc804\uc5d0 \uc5b4\ub5a4 \uc9c8\ubb38\uc744 \ub0a8\uacbc\ub294\uc9c0, \ub610\ud55c \ud574\ub2f9 \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub2e4. \\n\\n![chat1](./chat1.png)\\n\\n### \uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5\\n\\n\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc5d0 \ubc18\uc751\ud560 \uc218 \uc788\ub294 \ubb34\uc5b8\uac00\uac00 \uc788\uc5c8\uc73c\uba74 \uc88b\uaca0\ub2e4\ub294 \uc758\uacac\ub4e4\uc774 \ub9ce\uc558\ub2e4. \\n\ub204\uac00 \uc88b\uc544\uc694\ub97c \ub20c\ub800\ub294\uc9c0, \uc5b4\ub5a4 \ucc44\ud305\uc774 \uc88b\uc544\uc694\ub97c \uac00\uc7a5 \ub9ce\uc774 \ubc1b\uc558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\ub610\ud55c \ub313\uae00 \ucd94\uac00 \ubc0f \uc0ad\uc81c \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4.\\n\\n### \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\\n\\n\uc5b4\ub5bb\uac8c \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\uc744 \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub294\ub370, \uc77c\ub2e8 GPT\ub97c \uc774\uc6a9\ud574\uc11c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\uae30\ub85c \ud588\ub2e4. \\n\ud574\ub2f9 \ubd80\ubd84\uc740 \uccab \uc9c8\ubb38\uc5d0 \ub300\ud55c \ud0a4\uc6cc\ub4dc\ub9cc \ucd94\ucd9c\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\ubc31\uc5d4\ub4dc\uc5d0\uc120 \ub9d0\ub791\uc774 \uc774\ubca4\ud2b8 \uc774\uc6a9\ud574\uc11c \uccab \ucc44\ud305 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74, \ube44\ub3d9\uae30\ub85c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\ub294 \uc9c8\ubb38\uc744 \ucd94\uac00\ub85c \ub0a0\ub9ac\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4. \\nCSV \ud615\uc2dd\uc73c\ub85c GPT\uc5d0\uac8c \ub2f5\ubcc0\uc744 \uc785\ub825\ud574\ub2ec\ub77c\uace0 \uc694\uccad\ubc1b\ub294\ub370, \uc774 \ubd80\ubd84\uc774 \ubb38\uc81c(\ud504\ub86c\ud504\ud2b8 \uc5d4\uc9c0\ub2c8\uc5b4\ub9c1 \ubd80\ubd84\uc774 \ubc18\ud658\ub41c\ub2e4.)\uac00 \uc880 \uc788\ub294 \uac83 \uac19\uc544\uc11c \uac1c\uc120\uc774 \ud544\uc694\ud55c \uac83 \uac19\ub2e4. \\n\\n![chat2](./chat2.png)\\n\\n### \ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5\\n\\n\ub2e4\ub978 \ud06c\ub8e8\ub4e4\uc758 \ucc44\ud305\uc744 \uc77d\ub2e4\uac00 \uad81\uae08\ud55c \uc810\uc774 \uc788\ub2e4\uba74 \ubcf5\uc0ac\ud574\uc11c \ubc14\ub85c \uc9c8\ubb38\uc744 \ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\ucc44\ud305\uc774 \ubcf5\uc0ac\ub41c \ud6c4 \ubc14\ub85c GPT\uc640 \ub300\ud654\ub97c \ud560 \uc218 \uc788\ub294 \uba54\uc778 \ud654\uba74\uc73c\ub85c \uc774\ub3d9\ud55c\ub2e4. \\n\\n### \uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30\\n\\n![chat3](./chat3.png)\\n\\n\uc704 \ud654\uba74\uc740 \ud68c\uc6d0\uac00\uc785 \ucc3d\uc774\ub2e4. \\n\uc0ac\uc2e4 \uac00\uc7a5 \ub9c8\uc74c\uc5d0 \ub4dc\ub294 \ubd80\ubd84\uc774\uace0, \ud68c\uc6d0\uac00\uc785(\ub2c9\ub124\uc784\ub9cc \uc785\ub825\ud558\uc9c0\ub9cc)\ud560 \ub54c \uc775\uba85\uc744 \uc6d0\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uace0\ubbfc\uc744 \ub3c4\uc640\uc8fc\uac8c \ub054 \uc74c\uc2dd, \uacfc\uc77c, \uacfc\uc790 \ub4f1\uc758 \uc694\uc18c\ub4e4\uc744 \uc785\ub825\ud558\ub3c4\ub85d \uc720\ub3c4\ud588\ub2e4!\\n\ucd94\uac00\ub85c GPT\uc758 \ub2f5\ubcc0\uc774 \uc624\uba74 \uc790\ub3d9\uc73c\ub85c \ud654\uba74\uc744 \uc2a4\ud06c\ub864 \ud574\uc8fc\ub294 \uac83\uacfc \uac19\uc774 \uc0ac\uc6a9\uc131\uc744 \uac1c\uc120\ud574 \ubcf4\ub824\uace0 \ub178\ub825\ud588\uc9c0\ub9cc \uc27d\uc9c0 \uc54a\uc558\ub2e4. \\n\uc81c\uc77c \ud558\uace0 \uc2f6\uc740 \uac83\uc740 \uc2e4\uc81c GPT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ucc98\ub7fc stream/text \uac12\uc744 \ucc98\ub9ac\ud558\uace0 \uc2f6\uc740\ub370 \uc774 \ubd80\ubd84\uc740 \ubc29\ud559 \ub54c \uae30\ud68c\uac00 \ub418\uba74 \ub3c4\uc804\ud574 \ubd10\uc57c\uaca0\ub2e4. \\n\\n### \ud5a5\ud6c4 \uacc4\ud68d\\n\\n\uc2e4\uc81c \ud06c\ub8e8\ub4e4\uc774 \uc0ac\uc6a9\ud574 \uc8fc\ub294 \uc11c\ube44\uc2a4\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\ubcf4\uba74\uc11c \uc0ac\uc6a9\uc790\uc758 \uc785\uc7a5\uc5d0\uc11c \uace0\ubbfc\ub3c4 \ud558\uac8c \ub418\ub294 \uac83 \uac19\ub2e4. \\n\ud06c\ub8e8\ub4e4\uc774 \uc9c1\uc811 \uc0ac\uc6a9\ud574 \uc8fc\ub2c8\uae4c \ub108\ubb34 \uace0\ub9d9\uace0, \ud55c\ud3b8\uc73c\ub85c\ub294 \uc2e0\uae30\ud558\ub2e4. \\n\uc77c\ub2e8 \ubc29\ud559 \ub54c stream/text \uad00\ub828\ub41c \ubd80\ubd84 \ub3d9\uc791\ub418\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\ub824\uace0 \ud558\uace0, \uadf8 \uc678\uc758 \ubd80\ubd84\uc740 \uc870\uae08 \ub354 \uace0\ubbfc\ud574\uc57c\ub420 \uac83 \uac19\ub2e4."},{"id":"order-retrospective","metadata":{"permalink":"/order-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4: AWS \ubc30\ud3ec","date":"2023-06-04T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 4\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.67,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","slug":"order-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","permalink":"/tecochat-retrospective-3"},"nextItem":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","permalink":"/level2-interview-retrospective"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: AWS \ubc30\ud3ec \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-shopping-order/pull/7 \\n:::\\n\\n### \uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158\\n\\n\ubc30\ud3ec \ubc0f \ud611\uc5c5\uc744 \ud560 \uc218 \uc788\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ub9c8\ucf54, \uc6b0\uac00, \uc6b0\ucf54, \uc6b0\uc2a4 \uadf8\ub9ac\uace0 \ub098\uae4c\uc9c0 \ud569\uccd0\uc11c 5\uba85\uc774 \ud55c \ud300\uc774 \ub418\uc5c8\ub2e4. \\n\\n### \ubc30\ud3ec\\n\\n\uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac AWS\ub97c \uc774\uc6a9\ud574 \ubc30\ud3ec\ub97c \ud574\uc57c \ud588\ub2e4. \\n\uac01\uc790 \ud558\ub098\uc758 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc744 \uc218 \uc788\uc5c8\uace0, \ud300 \ubcc4\ub85c DB\ub97c \uc704\ud55c \ucd94\uac00 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc558\ub2e4. \\n\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uacbd\ud5d8\uc744 \ud574\ubcfc \uc218 \uc788\uc5c8\ub2e4. \\n\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ud22c\uc790\ud558\uc9c4 \uc54a\uc558\uace0, \ub2e4\uc74c\uacfc \uac19\uc774 \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4.\\n\\n```bash\\necho \\"Start Deploy Script\\"\\nREPOSITORY_NAME=/home/ubuntu/jwp-shopping-order\\nPROJECT_NAME=jwp-shopping-order\\n\\necho \\"Change Directory\\"\\ncd $REPOSITORY_NAME\\n\\necho \\"Git Pull\\"\\ngit pull origin step2\\n\\necho \\"Build\\"\\n./gradlew bootJar\\n\\necho \\"Copy, Start Server\\"\\nmv ./build/libs/$PROJECT_NAME.jar .\\n\\nPID=$(pgrep -f $PROJECT_NAME)\\n\\nif [ -n $PID ]; then\\n kill -9 $PID\\n\\tsleep 5\\nfi\\n\\nnohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &\\n```\\n\\n### \ud611\uc5c5\\n\\n\uc77c\ub2e8 \uc6b0\uc2a4\ub791 \uc6b0\ucf54\uac00 \uba3c\uc800 \uc7a0\uc2e4\ub85c \uc640\uc918\uc11c \ub108\ubb34 \uac10\uc0ac\ud588\ub2e4. \\n\ubc31\uc5d4\ub4dc\uac00 \uc544\ub2cc \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \ud574\ubcf4\ub294 \uccab \ud611\uc5c5\uc774\ub77c \uc57d\uac04 \ub450\uadfc\uac70\ub838\ub2e4. \\n\uc608\uc0c1\uc678\ub85c \ub300\ud654\uac00 \uc798 \ub418\uc5b4\uc11c, \ube60\ub974\uac8c \uba85\uc138\ub97c \uc815\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uc5ec\ub7ec\uac00\uc9c0 \ubc29\ubc95\uc5d0 \ub300\ud55c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud574\ubcf4\uae30**\\n\\n\ubc31\uc5d4\ub4dc\uc640 \ud14c\uc774\ube14 \uba85\uc138\ub098 \ucfe0\ud3f0 \uad6c\ud604\uc5d0 \ub300\ud574\uc11c \uc774\uc57c\uae30\ud560 \ub54c \uc7a5\ub2e8\uc5d0 \ub300\ud574 \ub9ce\uc774 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4. \\n\uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc5ec\uc11c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud588\ub2e4\uba74 \ub354 \uc88b\uc740 \uacb0\uacfc\ubb3c\uc774 \ub098\uc624\uc9c0 \uc54a\uc558\uc744\uae4c? \\n\uc55e\uc73c\ub85c \uc120\ud0dd\uc758 \uc21c\uac04\uc5d0\uc11c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub4e4\uc5ec\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4. \\n\\n### \uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84\\n\\n**expose headers**\\n\\n\uc6f9 \ud398\uc774\uc9c0\uc5d0\uc11c Location \ud5e4\ub354\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \uc788\uc5c8\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c [\ud5c8\uc6a9 \ubaa9\ub85d\uc5d0 \uc874\uc7ac\ud558\ub294 \uc751\ub2f5\ud5e4\ub354](https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header)\ub9cc \ubc18\ud658\ud55c\ub2e4\ub294 \uac83\uc744 \ubaa8\ub974\uace0 \uc788\uc5c8\ub2e4. \\n\uc774\ub97c expose headers \uc124\uc815\uc744 \ud1b5\ud574 \ud574\uacb0\ud560 \uc218 \uc788\uc5c8\ub2e4. \\nnginx \uc124\uc815\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \ucd94\uac00\ud574 \uc8fc\uc5c8\ub2e4. \\n\\n```bash\\nadd_header \'Access-Control-Expose-Headers\' \'Location\'\\n```\\n\\n**\uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158** \\n\\n\ub2e8\uc21c \uc870\ud68c \uc694\uccad\uc5d0 \ub300\ud55c \uc131\ub2a5\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc900\ub2e4\ub294 \uac83\uc774\ub77c\uace0 \uac04\ub2e8\ud788\ub9cc \uc54c\uace0 \uc788\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0 \ucf54\uba58\ud2b8\uac00 \ub2ec\ub824\uc11c \uc870\uae08 \ub354 \uc790\uc138\ud788 \uacf5\ubd80\ud574 \ubcf4\uae30\ub85c \ud588\ub2e4. \\nTransactional(readOnly = true)\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc774 \ub3d9\uc791\ud55c\ub2e4.\\n\\nsetReadOnly(true) \uc124\uc815\uc774 \ub41c Connection\uc73c\ub85c \uc5f0\uacb0\uc744 \uc2dc\ub3c4\ub97c \ud55c\ub2e4. \uc774 \uc124\uc815\uc744 \ud558\ub294 \uacbd\uc6b0 DB\ub9c8\ub2e4 \ub2e4\ub974\uac8c \ub3d9\uc791\ud55c\ub2e4.\\n- h2\uc758 Connection \uad6c\ud604\uccb4\ub294 readOnly \uc124\uc815\uc744 \ubb34\uc2dc\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 Transactional \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4. \\n- MySQL 8.0(InnoDB \uc0ac\uc6a9 \uc2dc)\uc758 \uacbd\uc6b0 \uc77d\uae30 \uc804\uc6a9\uc73c\ub85c \uc54c\ub824\uc9c4 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158 ID\ub97c \uc124\uc815\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uc870\ud68c \uc18d\ub3c4\uac00 \ub354 \ube68\ub77c\uc9c4\ub2e4.\\n\\nORM \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 prepareTransactionalConnection\ub97c \ud638\ucd9c\ud55c\ub2e4\uace0 \ud55c\ub2e4. \\n\ucd94\uac00\ub85c \ud604\uc5c5\uc5d0\uc11c\ub294 \uace0\uac00\uc6a9\uc131 \ub0b4\uacb0\ud568\uc131 \ub4f1\uc744 \uc704\ud558\uc5ec \ud074\ub7ec\uc2a4\ud130\ub97c \uad6c\uc131\ud558\uc5ec \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uace0, \uc774 \uacbd\uc6b0 readOnly \uc124\uc815\uc774 \ub418\uc5b4\uc788\ub2e4\uba74 \uc77d\uae30 \uc804\uc6a9 DB\ub85c \uc9c8\uc758\uac00 \ub4e4\uc5b4\uac00\uc11c \ubd80\ud558 \ubd84\uc0b0\uc758 \ud6a8\uacfc\uac00 \uc788\ub2e4\uace0 \ud55c\ub2e4. \\n\\n**DAO\uc5d0 `@Transactional` \uc801\uc6a9** \\n\\nDAO\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \ubcf4\ub294 \uac74 \uc5b4\ub5bb\uaca0\ub0d0\uace0 \ub9ac\ubdf0\uac00 \ub2ec\ub824\uc11c \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\nService \uacc4\uce35\uc5d0 \uc774\ubbf8 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \uc8fc\uace0 \uc788\uae30\uc5d0 \ud544\uc694 \uc5c6\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4. \\nDAO\ub97c \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574(\ud655\uc7a5\uc131 \uace0\ub824) `@Transactional`\uc744 \uc801\uc6a9\ud558\ub294 \uac83\ub3c4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."},{"id":"level2-interview-retrospective","metadata":{"permalink":"/level2-interview-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx","title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","description":"\ub808\ubca8 \uc778\ud130\ubdf0","date":"2023-06-08T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 8\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.435,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","slug":"level2-interview-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","permalink":"/order-retrospective"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","permalink":"/woowacourse-level2-retrospective"}},"content":"### \ub808\ubca8 \uc778\ud130\ubdf0\\n\\n\ub808\ubca8 1 \ub54c\ub294 \uc900\ube44\ud574\ub454 \ub0b4\uc6a9\uc73c\ub85c \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud574\uc11c \uadf8\ub807\uac8c \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc774 \uc5c6\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \ub808\ubca8 1 \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0\ub294 \ub808\ubca8 1 \ud68c\uace0\ub97c \uc791\uc131\ud560 \ub54c \ub07c\uc6cc\ub123\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \ubc94\uc704\ub3c4 \uc81c\ud55c\ub418\uc5b4 \uc788\uc5b4 \uc5b4\ub5bb\uac8c \uc900\ube44\ud574\uc57c \ud560\uc9c0 \ub2f9\ud669\ud588\uace0, \ub2f5\ubcc0\uc5d0\ub3c4 \ubd80\uc871\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4. \\n\uae30\uc5b5\uc774 \uc0ac\ub77c\uc9c0\uae30 \uc804\uc5d0 \ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\ud55c \ub0b4\uc6a9\uc744 \uc81c\uc678\ud558\uace0, \uae30\uc5b5 \ub0a8\ub294 \uac83 \uc704\uc8fc\ub85c \uc791\uc131\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n### API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd\\n\\n\ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\uc744 \ud588\ub294\ub370 \uc55e\uc73c\ub85c\ub3c4 \ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \ud558\uba74\uc11c \ub3c4\uc6c0 \ub420 \uac83 \uac19\uc740 \ub0b4\uc6a9\uc774 \uc788\uc5b4\uc11c \ub0a8\uaca8\ub450\ub824\uace0 \ud55c\ub2e4. \\n\ubc31\uc5d4\ub4dc \ud300\uc6d0\uc774 \ud568\uaed8 \uc758\uc0ac\uacb0\uc815\uc744 \ud588\uace0, \ubbf8\uc158 \uae30\uac04\uc774 \uc9e7\uc740 \ub9cc\ud07c \ud300 \ucc28\uc6d0\uc5d0\uc11c \ube44\uad50\uc801 \ud559\uc2b5\ud558\uae30 \uc26c\uc6b4 Swagger\ub97c \uc120\ud0dd\ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub4e4\uc5b4\uac00\ub294 \uc2dc\uac04 \ub300\ube44 \ud558\uc774 \ub9ac\ud134\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4\uace0 \ub2f5\ubcc0\ud588\ub2e4.\\n\\n\ud300 \ucc28\uc6d0\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uc5b8\uae09\ud574\uc11c, \ub2e4\uc74c\uacfc \uac19\uc740 \uc88b\uc740 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4.\\n\\n> \ud2b9\ud788 \ud300\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\ud558\ub294 \uacfc\uc815\uc744 \uacf5\uc720\ud574 \uc900 \uc810\uc774 \uc88b\uc558\uace0 \uae30\uc220\uc801 \uc758\uc0ac\uacb0\uc815 \uacfc\uc815\uc5d0\uc11c \ud300\uc758 \ud559\uc2b5\ube44\uc6a9\uc744 \uace0\ub824\ud55c \uc810\uc774 \uc88b\uc558\uc74c. \\n> \uc55e\uc73c\ub85c\ub3c4 \ud559\uc2b5 \ube44\uc6a9\uc740 \uc8fc\uc694\ud558\uac8c \uace0\ub824\ud574\uc57c \ud560 \uc0ac\ud56d\\n>\\n\\n### PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158\\n\\nPUT\uacfc PATCH \ucc28\uc774\ub97c \uc124\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c\ub294 PATCH\ub97c \uc0ac\uc6a9\ud560 \ub54c \ud398\uc774\ub85c\ub4dc\uac00 \uc801\uc5b4\uc9c4\ub2e4\ub294 \ub0b4\uc6a9\uc744 \ube7c\uba39\uace0 \ub2f5\ubcc0\uc744 \ud588\ub2e4. \\n\ud1a0\ud070\uacfc \uc138\uc158\uc758 \uacbd\uc6b0 \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud574\ub2ec\ub77c\ub294 \uc81c\uc57d\uc870\uac74\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n\ud574\ub2f9 \ub0b4\uc6a9\uc744 \ub2f5\ubcc0\ud558\uba74\uc11c \uae30\uc220\uc801\uc778 \uae4a\uc774\uac00 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\uc2e4\uc81c\ub85c \ub808\ubca8 2 \ub54c \uc774\ub860\uc801\uc778 \ud559\uc2b5 \uc2dc\uac04\uc774 \ub9e4\uc6b0 \uc801\uc5c8\uace0, \uc9d1\uc911\ub825\ub3c4 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4. \\n\uc55e\uc73c\ub85c \uc5b4\ub5bb\uac8c \uae4a\uc774\ub97c \ucc44\uc6b8\uc9c0 \uace0\ubbfc\uc744 \ud560 \uc218 \uc788\ub294 \uc9c8\ubb38\ub4e4\uc774\uc5c8\ub2e4. \\n\\n\ucd94\uac00\ub85c \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud558\ub294 \uac00\uc815\uc744 \ub450\uace0 \ud559\uc2b5\uc744 \ud55c\ub2e4\uba74 \ud070 \ub3c4\uc6c0\uc774 \ub420 \uac70\ub77c\ub294 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4. \\n\\n### \uadf8 \uc678 \uac1c\uc120\ud560 \uc810\\n\\n\uc778\ud130\ubdf0\ud560 \ub54c \ud2b9\uc720\uc758 \ub9d0\ubc84\ub987\uc744 \uac1c\uc120\ud558\uae30 \\n\uc0dd\uac01\ud560 \uc2dc\uac04\uc744 \uac00\uc84c\uc744 \ub54c \\"\ub2e4\uc2dc \ub9d0\uc500\ub4dc\ub824\ub3c4 \ub420\uae4c\uc694?\\"\ub77c\uace0 \ub9d0\ud558\uace0 \ub2f5\ubcc0\uc744 \uc774\uc5b4\ub098\uac00\uae30 \\n\uae30\uc220\uc801\uc73c\ub85c \uae4a\uc774\uac00 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5b4\uc11c \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\uae30 \\n\uc774\uc804\uc5d0 \uacf5\ubd80\ud588\ub358\uac70 \ub418\ub3cc\uc544 \ubcf4\ub294 \uc2dc\uac04 \uac00\uc9c0\uae30"},{"id":"woowacourse-level2-retrospective","metadata":{"permalink":"/woowacourse-level2-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","description":"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.","date":"2023-06-11T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 11\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":2.545,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","slug":"woowacourse-level2-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","permalink":"/level2-interview-retrospective"},"nextItem":{"title":"Docusaurus","permalink":"/docusaurus"}},"content":"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4. \\n\ube60\ub974\uac8c \uc9c0\ub098\uac00\uc11c \uc870\uae08 \uc544\uc27d\ub2e4. \\n\\n### \ud559\uc2b5\\n\\n\ud68c\uace0\ub97c \uc791\uc131\ud558\uae30 \uc804\uc5d0 \ub808\ubca8 2 \ub3d9\uc548 \ubcf4\ub0c8\ub358 PR\uacfc \ud68c\uace0\ub97c \ucb49 \uc77d\uc5b4\ubd24\ub2e4. \\n\ud56d\uc0c1 \uc544\uc26c\uc6b4 \uacf3\uc740 \uc788\uae30 \ub9c8\ub828\uc774\uc9c0\ub9cc, \uc798 \ud559\uc2b5\ud55c \uac83 \uac19\ub2e4. \\n\ubbf8\uc158\uc744 \ud558\uba74\uc11c \uae30\uc220\uc744 \uc5b4\ub5bb\uac8c \uc120\ud0dd\ud558\uace0, \uc801\uc6a9\ud560 \uac83\uc778\uc9c0 \uace0\ubbfc\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \uaf64\ub098 \ub9ce\uc740 \uc131\uc7a5\uc744 \ud55c \uac83 \uac19\ub2e4. \\n\\n\uace0\ubbfc\uc740 \uae4a\uc5c8\uc9c0\ub9cc \uc774\ub860\uc801\uc778 \ud559\uc2b5\uc774 \ubd80\uc871\ud55c \ub808\ubca8 2\uc600\ub2e4. \\n\ubc29\ud559 \uadf8\ub9ac\uace0 \ub808\ubca8 3 \ub54c\ub294 \uc870\uae08 \ub354 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc744 \ud559\uc2b5\ud558\ub294\ub370 \uc9d1\uc911\ud574\uc57c\uaca0\ub2e4. \\n\\n\uc810\ucc28 \ud559\uc2b5 \ubc94\uc704\uac00 \ub113\uc5b4\uc9c0\uba74\uc11c \uc790\uc5f0\uc2a4\ub7fd\uac8c \ubaa8\ub974\ub294 \ub0b4\uc6a9\uc774 \uc313\uc5ec\uac04\ub2e4. \\n\ud544\uc694\ud55c \ub0b4\uc6a9\uc740 \uc55e\uc73c\ub85c \ucc9c\ucc9c\ud788 \ud559\uc2b5\ud558\uba74 \ub418\ub2c8\uae4c \uc870\uae09\ud574\uc9c0\uc9c0 \ub9d0\uc544\uc57c\uaca0\ub2e4. \\n\\n### \uc218\uba74\\n\\n\ub808\ubca8 2\ub97c \uc9c4\ud589\ud558\ub294 \ub3d9\uc548 \uc218\uba74\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\uc5c8\uace0, \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \uadf8\ub0a0\uc758 \ucee8\ub514\uc158\uc744 \ub9ce\uc774 \uc88c\uc6b0\ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c \uc218\uba74 \uc2dc\uac04\uc744 \ub298\ub9ac\uace0, \uc88b\uc740 \uc218\uba74 \uc2b5\uad00\uc744 \uac00\uc9c0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### \ud611\uc5c5\\n\\n\ub808\ubca8 2 \ub9c8\uc9c0\ub9c9\uc5d0 \ud611\uc5c5 \ubbf8\uc158\uc774 \uc788\uc5c8\ub2e4. \\n\uc9c0\uae08\uae4c\uc9c0\ub294 \ubc31\uc5d4\ub4dc \ud06c\ub8e8\ub4e4\uacfc \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \ud611\uc5c5\uc744 \uacbd\ud5d8\ud588\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \ud504\ub7f0\ud2b8\uc5d4\ub4dc \ud06c\ub8e8\uc640 \ud611\uc5c5\uc744 \ud588\ub2e4. \uc18c\ud1b5\uc740 \uc798 \ub41c \uac83 \uac19\uc9c0\ub9cc API \uba85\uc138\ub97c \uc815\ud558\ub294 \ubd80\ubd84\uc774 \uc544\uc9c1 \ubbf8\uc219\ud55c \uac83 \uac19\ub2e4. \\n\\n\ub808\ubca8 3 \ub54c\ubd80\ud130 \ubcf8\uaca9\uc801\uc73c\ub85c \ud504\ub85c\uc81d\ud2b8\uac00 \uc2dc\uc791\ub41c\ub2e4. \\n\ud300\uc744 \uc704\ud574 \uc5b4\ub5a4 \uac83\uc744 \ud560 \uc218 \uc788\uc744\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud574\ubd10\uc57c\uaca0\ub2e4. \\n\\n### \ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70\\n\\n\ud68c\uace0 \uc791\uc131\ud558\uba74\uc11c \ub808\ubca8 2\uc5d0\uc11c \ud588\ub358 \uac83\ub4e4\uc744 \ubc18\ucd94\ud574 \ubd24\ub294\ub370 \ubd80\uc871\ud55c \uc810\uc740 \ub9ce\uc558\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \uac00\uace0 \uc788\ub294 \uac83 \uac19\ub2e4.\\n\uc77d\uace0 \uc2f6\uc740 \ucc45\ub3c4 \uc77d\uace0, \ubd80\uc871\ud55c \ubd80\ubd84 \ucc44\uc6b0\uba74\uc11c \uc26c\uc5b4\uc57c\uaca0\ub2e4."},{"id":"docusaurus","metadata":{"permalink":"/docusaurus","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx","source":"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx","title":"Docusaurus","description":"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4.","date":"2023-06-18T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 18\uc77c","tags":[{"label":"Documentation","permalink":"/tags/documentation"}],"readingTime":10.095,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Docusaurus","slug":"docusaurus","tags":["Documentation"]},"unlisted":false,"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","permalink":"/woowacourse-level2-retrospective"},"nextItem":{"title":"\uc6f9\uc18c\ucf13","permalink":"/websocket"}},"content":"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4. \\n\\n## \uc124\uce58\\n\\n[\uacf5\uc2dd \ud648\ud398\uc774\uc9c0](https://docusaurus.io/docs/installation)\uc5d0 \ub4e4\uc5b4\uac00\uc11c \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58\ud55c\ub2e4. \\n\\n```bash\\nyarn create docusaurus\\n````\\n\\n## \ubc30\ud3ec\\n\\n[\ubc30\ud3ec \uc548\ub0b4 \ubb38\uc11c](https://docusaurus.io/docs/next/deployment#deploying-to-github-pages) \\nnetlify\ub098 vercel \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ud50c\ub7ab\ud3fc\uc744 \ucd94\ucc9c\ud558\uace0 \uc788\uace0, \uac04\ub2e8\ud558\uace0, \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \ubc30\ud3ec\ub97c \ud560 \uc218 \uc788\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 github pages\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud55c\ub2e4.\\n\\n### \ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131\\n\\ngithub pages\ub97c \uc774\uc6a9\ud558\ub824\uba74 [\uc608\uc2dc](https://github.com/greeng00se/greeng00se.github.io)\uc640 \uac19\uc774 `username.github.io` \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4. \\n\uc774\ub54c organization\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 `organization.github.io` \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n### \uc124\uc815 \ud30c\uc77c \uc218\uc815\\n\\n```js title=\\"docusaurus.config\\"\\nmodule.exports = {\\n // ...\\n url: \'https://greeng00se.github.io\',\\n baseUrl: \'/\',\\n projectName: \'greeng00se.github.io\',\\n organizationName: \'greeng00se\',\\n trailingSlash: false,\\n // ...\\n};\\n```\\n\\n### \ud1a0\ud070 \uc124\uc815\\n\\ngithub action\uc744 \uc704\ud574 \ubc30\ud3ec\uc6a9 \ud1a0\ud070\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uc5ec \uc0dd\uc131\ud55c \ub808\ud3ec\uc9c0\ud1a0\ub9ac\uc5d0 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 \ud1a0\ud070\uc744 \ud074\ub798\uc2dd \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ud588\uace0 \uc2a4\ucf54\ud504\ub294 [repo, user, workflow] \uc744 \uc124\uc815\ud588\ub2e4. \\n\\n![github](./github.png)\\n\\n### \ube0c\ub79c\uce58 \uc0dd\uc131\\n\\ngithub\uc5d0\uc11c gh-pages \ube0c\ub79c\uce58\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4. \\nrepository -> settings -> pages -> branch\uc5d0\uc11c \uc0dd\uc131\ud55c gh-pages\ub85c \ube0c\ub79c\uce58\ub97c \ubcc0\uacbd\ud55c\ub2e4. \\n\uc124\uc815\ud55c \ube0c\ub79c\uce58\uac00 \ubc30\ud3ec \ube0c\ub79c\uce58\uac00 \ub418\uba70, \ud574\ub2f9 \ube0c\ub79c\uce58\uc5d0 \uc788\ub294 \ud30c\uc77c\ub4e4\uc744 \uc774\uc6a9\ud574\uc11c \uc815\uc801 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc81c\uacf5\ud55c\ub2e4. \\n\\n### \uc6cc\ud06c\ud50c\ub85c \uc791\uc131\\n\\nDocusaurus 2.0 \uae30\uc900 Node.js 16.14 \uc774\uc0c1\uc758 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4. \\n\ubc30\ud3ec\uc2dc\uc5d0\ub294 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c DEPLOY_TOKEN \uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4. \\n\\n```yml title=\\".github/workflows/deploy.yml\\"\\nname: blog\\n\\non:\\n push:\\n branches: [main]\\n\\njobs:\\n deploy:\\n name: Deploy to GitHub Pages\\n runs-on: ubuntu-latest\\n steps:\\n - uses: actions/checkout@v2\\n - uses: actions/setup-node@v3\\n with:\\n node-version: 18\\n cache: yarn\\n\\n - name: Install dependencies\\n run: yarn install --frozen-lockfile\\n - name: Build website\\n run: yarn build\\n\\n - name: Deploy to GitHub Pages\\n uses: peaceiris/actions-gh-pages@v3\\n with:\\n github_token: ${{ secrets.DEPLOY_TOKEN }}\\n publish_dir: ./build\\n user_name: github-actions[bot]\\n user_email: 41898282+github-actions[bot]@users.noreply.github.com\\n```\\n\\n## \ub313\uae00 \uae30\ub2a5\\n\\ngiscus\ub97c \uc774\uc6a9\ud558\uc5ec \ub313\uae00 \uae30\ub2a5\uc744 \ucd94\uac00\ud55c\ub2e4. \\n\\n### giscus \uc124\uc815\\n\\n1. \uacf5\uac1c \uc800\uc7a5\uc18c\uc5ec\uc57c \ud55c\ub2e4.\\n2. giscus \uc571\uc774 \uc124\uce58\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4.\\n3. Discussions \uae30\ub2a5\uc774 \ud574\ub2f9 \uc800\uc7a5\uc18c\uc5d0\uc11c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4.\\n\\n\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [giscus](https://giscus.app/ko)\ub97c \ud655\uc778\ud558\uc790.\\n\\n### docusaurus \uc124\uc815\\n\\n[swizzling](https://docusaurus.io/ko/docs/next/swizzling)\uc744 \uc774\uc6a9\ud558\uc5ec \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac10\uc2fc\ub2e4. \\n\uae30\uc874\uc5d0 \uac8c\uc2dc\ubb3c\uc744 giscus\uac00 \ud3ec\ud568\ub41c \ub9ac\uc561\ud2b8 \ucef4\ud3ec\ub10c\ud2b8\ub85c \uac10\uc2f8\ub294 \ud615\ud0dc\uac00 \ub41c\ub2e4. \\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec BlogPostItem\uc744 \ucd94\ucd9c\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nyarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap\\n```\\n\\n\uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uba74 `/src/theme/BlogPostItem/index.js` \uc704\uce58\uc5d0 \ud30c\uc77c\uc774 \uc0dd\uc131\ub41c\ub2e4. \\n\ud30c\uc77c\uc758 \ub0b4\uc6a9\uc744 \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud558\uace0, \uc774\ub54c setAttribute \ubd80\ubd84\uc740 \uc801\uc808\ud558\uac8c \uc790\uc2e0\uc758 giscus \uc124\uc815\uc744 \uc774\uc6a9\ud55c\ub2e4. \\n\\n```js title=\\"/src/theme/BlogPostItem/index.js\\"\\nimport OriginalBlogPostItem from \\"@theme-original/BlogPostItem\\";\\nimport React, { useEffect, useRef } from \\"react\\";\\n// @ts-expect-error internal code\\nimport { useColorMode } from \\"@docusaurus/theme-common\\";\\nimport { useBlogPost } from \\"@docusaurus/theme-common/internal\\";\\n\\nconst giscusSelector = \\"iframe.giscus-frame\\";\\n\\nfunction BlogPostItem(props) {\\n const { colorMode } = useColorMode();\\n const { isBlogPostPage } = useBlogPost();\\n const giscusTheme = colorMode === \\"dark\\" ? \\"dark\\" : \\"light\\";\\n const containerRef = useRef(null);\\n\\n useEffect(() => {\\n if (!isBlogPostPage) return;\\n\\n const giscusEl = containerRef.current.querySelector(giscusSelector);\\n\\n const createGiscusEl = () => {\\n const script = document.createElement(\\"script\\");\\n\\n script.src = \\"https://giscus.app/client.js\\";\\n script.setAttribute(\\"data-repo\\", \\"teco-chat/teco-chat.github.io\\");\\n script.setAttribute(\\"data-repo-id\\", \\"R_kgDOJZ5j0Q\\");\\n script.setAttribute(\\"data-category\\", \\"Announcements\\");\\n script.setAttribute(\\"data-category-id\\", \\"DIC_kwDOJZ5j0c4CXS_Q\\");\\n script.setAttribute(\\"data-mapping\\", \\"pathname\\");\\n script.setAttribute(\\"data-strict\\", \\"0\\");\\n script.setAttribute(\\"data-reactions-enabled\\", \\"1\\");\\n script.setAttribute(\\"data-emit-metadata\\", \\"0\\");\\n script.setAttribute(\\"data-input-position\\", \\"bottom\\");\\n script.setAttribute(\\"data-theme\\", giscusTheme);\\n script.setAttribute(\\"data-lang\\", \\"ko\\");\\n script.crossOrigin = \\"anonymous\\";\\n script.async = true;\\n \\n containerRef.current.appendChild(script);\\n };\\n\\n const postThemeMessage = () => {\\n const message = {\\n setConfig: {\\n theme: giscusTheme,\\n }\\n };\\n\\n giscusEl.contentWindow.postMessage({ giscus: message }, \\"https://giscus.app\\");\\n };\\n\\n giscusEl ? postThemeMessage() : createGiscusEl();\\n }, [giscusTheme]);\\n\\n return (\\n <>\\n \\n {isBlogPostPage &&
}\\n \\n );\\n}\\n\\nexport default BlogPostItem;\\n```\\n\\n## \uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30\\n\\n\uc54c\uace0\ub9ac\uc544\ub97c \uc0ac\uc6a9\ud558\uba74 \uac80\uc0c9 \uae30\ub2a5\uc744 \ucd94\uac00\ud560 \uc218 \uc788\ub2e4. \\n\uc720\ub8cc \ud50c\ub79c\uc774\ub098 netlify\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ud06c\ub864\ub7ec\ub97c \ub530\ub85c \uc81c\uacf5\ud574 \uc8fc\ub294 \uac83 \uac19\ub2e4. \\n\\n\ubb34\ub8cc \ud50c\ub79c\uc740 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uacfc, [docsearch](https://docsearch.algolia.com/)\ub97c \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4. \\ndocsearch\uc5d0 \ub4f1\ub85d\ud55c\ub2e4\uba74 \uc77c\uc8fc\uc77c\uc5d0 \ud55c \ubc88\uc529 \ud06c\ub864\ub9c1\uc774 \uc9c4\ud589\ub41c\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n- [\uc9c1\uc811 \uc778\ub371\uc2a4 \uc218\uc9d1](https://docsearch.algolia.com/docs/legacy/run-your-own/) \\n- [\uc124\uc815 \ud30c\uc77c](https://docsearch.algolia.com/docs/legacy/config-file)\\n\\n### \uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778\\n\\n\ud68c\uc6d0\uac00\uc785\uc744 \ud558\uace0 \uc0c8\ub85c\uc6b4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131\uc744 \ub204\ub978\ub2e4. \\n\uc0dd\uc131\uc744 \ub2e4 \ub9c8\uce58\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 api \ud0a4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n![algolia](./algolia.png)\\n\\n### \ud0a4 \uc0dd\uc131\\n\\n\uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\uae30 \uc704\ud55c \ud0a4\ub97c \uc0dd\uc131\ud55c\ub2e4. \\naddObject, editSettings, deleteIndex acl(\uc811\uadfc \uc81c\uc5b4 \ubaa9\ub85d)\uc774 \uc788\uc73c\uba74 \ub41c\ub2e4. \\n\\n![key](./key.png)\\n\\n### .env \ud30c\uc77c \uc0dd\uc131\\n\\n\ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0c1\ub2e8\uc5d0 .env \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4. \\n\\n```bash title=\\".env\\"\\nAPPLICATION_ID=MVIU5UEMOM\\nAPI_KEY=\uc778\ub371\uc2a4_\uc0dd\uc131\uc6a9_\ud0a4\\n```\\n\\n### config \ud30c\uc77c \uc0dd\uc131\\n\\n\ub9c8\ucc2c\uac00\uc9c0\ub85c \ucd5c\uc0c1\ub2e8\uc5d0 config.json \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4.\\n\uc124\uc815 \ud30c\uc77c\uc740 \ud574\ub2f9 [\ub9c1\ud06c](https://docsearch.algolia.com/docs/legacy/config-file)\ub97c \ucc38\uace0\ud55c\ub2e4. \\n\ub610\ub294 Docusaurus\uc758 [\uc124\uc815 \ud30c\uc77c](https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json)\uc744 \ucc38\uace0\ud55c\ub2e4.\\n\\n```json title=\\"config.json\\"\\n{\\n \\"index_name\\": \\"teco\\",\\n \\"start_urls\\": [\\n \\"https://teco-chat.github.io/\\"\\n ],\\n \\"sitemap_urls\\": [\\n \\"https://teco-chat.github.io/sitemap.xml\\"\\n ],\\n \\"sitemap_alternate_links\\": true,\\n \\"stop_urls\\": [\\n \\"/tests\\"\\n ],\\n \\"selectors\\": {\\n \\"lvl0\\": {\\n \\"selector\\": \\"(//ul[contains(@class,\'menu__list\')]//a[contains(@class, \'menu__link menu__link--sublist menu__link--active\')]/text() | //nav[contains(@class, \'navbar\')]//a[contains(@class, \'navbar__link--active\')]/text())[last()]\\",\\n \\"type\\": \\"xpath\\",\\n \\"global\\": true,\\n \\"default_value\\": \\"Documentation\\"\\n },\\n \\"lvl1\\": \\"header h1\\",\\n \\"lvl2\\": \\"article h2\\",\\n \\"lvl3\\": \\"article h3\\",\\n \\"lvl4\\": \\"article h4\\",\\n \\"lvl5\\": \\"article h5, article td:first-child\\",\\n \\"lvl6\\": \\"article h6\\",\\n \\"text\\": \\"article p, article li, article td:last-child\\"\\n },\\n \\"strip_chars\\": \\" .,;:#\\",\\n \\"custom_settings\\": {\\n \\"separatorsToIndex\\": \\"_\\",\\n \\"attributesForFaceting\\": [\\n \\"language\\",\\n \\"version\\",\\n \\"type\\",\\n \\"docusaurus_tag\\"\\n ],\\n \\"attributesToRetrieve\\": [\\n \\"hierarchy\\",\\n \\"content\\",\\n \\"anchor\\",\\n \\"url\\",\\n \\"url_without_anchor\\",\\n \\"type\\"\\n ]\\n },\\n \\"conversation_id\\": [\\n \\"833762294\\"\\n ],\\n \\"nb_hits\\": 46250\\n}\\n```\\n\\n### docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\\n\\ndocker\uc640 jq\uac00 \ud544\uc694\ud558\ub2e4. \\njq\uac00 \uc124\uce58\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74 mac \uae30\uc900 brew\ub97c \uc774\uc6a9\ud574\uc11c \uc124\uce58\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nbrew install jq\\n```\\n\\n\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec .env\uc640 config.json\uc744 \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\uc744 \ud55c\ub2e4. \\n\\n```bash\\ndocker run -it --env-file=.env -e \\"CONFIG=$(cat ./config.json | jq -r tostring)\\" algolia/docsearch-scraper\\n```\\n\\n### docusaurus \uc124\uc815\\n\\n\uc804\uc5d0 \ud655\uc778\ud55c APP ID, Search-Only API KEY, IndexName\uc744 \uc774\uc6a9\ud558\uc5ec docusaurus.config \ud30c\uc77c\uc5d0 \uc124\uc815\ud55c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nthemeConfig:\\n /** @type {import(\'@docusaurus/preset-classic\').ThemeConfig} */\\n ({\\n ...\\n algolia: {\\n appId: \'MVIU5UEMOM\', // Application ID\\n apiKey: \'b68f378013817d9a190df88cdde226a0\', // Search-Only API Key\\n indexName: \'teco\', // config.json\uc5d0 \uc124\uc815\ud55c \uc778\ub371\uc2a4\uba85\\n contextualSearch: true,\\n },\\n })\\n```\\n\\n## \ubd80\uac00 \uc124\uc815\\n\\n### \ud654\uba74 \uc0c1\ub2e8 Github Icon\\n\\n\ud30c\uc77c \ucd5c\ud558\ub2e8\uc5d0 \uc544\ub798 css \uad6c\ubb38\uc744 \ucd94\uac00\ud55c\ub2e4.\\n\\n```css title=\\"/src/css/custom.css\\"\\n.header-github-link:hover {\\n opacity: 0.6;\\n}\\n\\n.header-github-link:before {\\n content: \'\';\\n width: 24px;\\n height: 24px;\\n display: flex;\\n background: url(\\"data:image/svg+xml,%3Csvg viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\'/%3E%3C/svg%3E\\")\\n no-repeat;\\n}\\n\\nhtml[data-theme=\'dark\'] .header-github-link:before {\\n background: url(\\"data:image/svg+xml,%3Csvg viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath fill=\'white\' d=\'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\'/%3E%3C/svg%3E\\")\\n no-repeat;\\n}\\n```\\n\\nthemeconfig -> navbar\uc5d0 github link\ub97c \uc124\uc815\ud55c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nnavbar: {\\n title: \'HELLO\',\\n items: [\\n {\\n href: \'https://github.com/greeng00se\',\\n position: \'right\',\\n className: \'header-github-link\',\\n \'aria-label\': \'GitHub repository\',\\n },\\n ],\\n},\\n```\\n\\n### \ucf54\ub4dc\ube14\ub7ed\\n\\njava\ub098 kotlin\uc758 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ub77c\uc774\ud305\uc744 \uc9c0\uc6d0\ud574 \uc8fc\uc9c0 \uc54a\ub294\ub2e4. \\nprism \uc124\uc815\uc744 \uc544\ub798\uc640 \uac19\uc774 \ubcc0\uacbd\ud574 \uc900\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nprism: {\\n theme: lightCodeTheme,\\n darkTheme: darkCodeTheme,\\n additionalLanguages: [\'java\', \'kotlin\'],\\n}\\n```\\n\\n### mermaid\\n\\nmermaid\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 `@docusaurus/theme-mermaid` \ub97c \uc124\uce58\ud574\uc57c \ud55c\ub2e4.\\n\\n```bash\\nyarn add @docusaurus/theme-mermaid\\n```\\n\\n\uc124\uce58 \ud6c4 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\uc744 \ucd94\uac00\ud55c\ub2e4.\\n\\n```js title=\\"docusaurus.config\\"\\nconst config = {\\n ...\\n markdown: {\\n mermaid: true,\\n },\\n themes: [\\n \'@docusaurus/theme-mermaid\'\\n ],\\n};\\n```\\n\\nthemeConfig\uc5d0\uc11c mermaid\uc758 \ud14c\ub9c8\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nthemeConfig:\\n /** @type {import(\'@docusaurus/preset-classic\').ThemeConfig} */\\n ({\\n ...\\n mermaid: {\\n theme: {\\n light: \'neutral\', \\n dark: \'dark\'\\n },\\n },\\n }),\\n```\\n\\n### \uad6d\uc81c\ud654 \uc124\uc815\\n\\n\uad6d\uc81c\ud654 \uc124\uc815\uc744 \ud55c\ub2e4\uba74 `Older Entries` \ud615\ud0dc\uc758 \uc124\uba85\uc774 `\ub2e4\uc74c \ud398\uc774\uc9c0` \ub85c \ubcc0\uacbd\ub41c\ub2e4. \\n\uc124\uc815\ud30c\uc77c\uc5d0\uc11c i18n\uc5d0 \uc788\ub294 \ub85c\ucf00\uc77c \uc124\uc815\uc744 ko\ub85c \ubcc0\uacbd\ud558\uba74 \ub41c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\ni18n: {\\n defaultLocale: \\"ko\\",\\n locales: [\\"ko\\"],\\n},\\n```\\n\\n### \ube14\ub85c\uadf8 \uae00 author\\n\\n\ud300\uc6d0 \ubcc4\ub85c \ubb38\uc11c\ub97c \uad00\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc5b4\ub5a4 \ud300\uc6d0\uc774 \uae00\uc744 \uc791\uc131\ud588\ub294\uc9c0 \uc124\uc815\ud574\uc57c \ud55c\ub2e4. \\n\\n![author](./author.png)\\n\\n`authors.yml` \ud30c\uc77c\uc744 \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \uae30\ubcf8 \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n```yml title=\\"/blog/authors.yml\\"\\nherb:\\n name: \ud5c8\ube0c\\n title: Backend\\n url: https://github.com/greeng00se\\n image_url: https://github.com/greeng00se.png\\n\\nmallang:\\n name: \ub9d0\ub791\\n title: Backend\\n url: https://github.com/shin-mallang\\n image_url: https://github.com/shin-mallang.png\\n```\\n\\n\ube14\ub85c\uadf8 \uae00\uc744 \uc791\uc131\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc774 authors\uc5d0 \ub123\uc5b4\uc8fc\uae30\ub9cc \ud558\uba74 \ub41c\ub2e4. \\n\\n```mdx\\n---\\nslug: 1\\ntitle: Hello World\\nauthors: [herb, mallang]\\ntags: [hello, docusaurus]\\n---\\n\\n\uccab \ubc88\uc9f8 \ubb38\uc11c \ub0b4\uc6a9\\n```"},{"id":"websocket","metadata":{"permalink":"/websocket","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-26-WebSocket.mdx","source":"@site/blog/2023-2/2023-06-26-WebSocket.mdx","title":"\uc6f9\uc18c\ucf13","description":"\uc6f9\uc18c\ucf13","date":"2023-06-26T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 26\uc77c","tags":[{"label":"WebSocket","permalink":"/tags/web-socket"}],"readingTime":4.165,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9\uc18c\ucf13","slug":"websocket","tags":["WebSocket"]},"unlisted":false,"prevItem":{"title":"Docusaurus","permalink":"/docusaurus"},"nextItem":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","permalink":"/java-spring-springboot"}},"content":"### \uc6f9\uc18c\ucf13\\n\\n\ub2e8\uc77c TCP \uc5f0\uacb0\uc744 \ud1b5\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04 \uc804\uc774\uc911 \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\ud1a0\ucf5c \\n\uc6f9 \ud658\uacbd\uc5d0\uc11c \uc5f0\uc18d\ub41c \ub370\uc774\ud130\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4. \\n\\n\uc6f9\uc18c\ucf13\uc740 HTTP\uc758 \ud3ec\ud2b8\ub97c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud558\uace0 \uac01\uac01 \ud3ec\ud2b8 80\uacfc \ud3ec\ud2b8 443\uc744 \uc0ac\uc6a9\ud558\uc5ec HTTP(ws://) \ubc0f HTTPS(wss://)\ub85c \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud55c\ub2e4. \\n\\n### \uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd\\n\\n\uc6f9\uc18c\ucf13\uc774 \ub4f1\uc7a5\ud558\uae30 \uc774\uc804, \uc2e4\uc2dc\uac04\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 Polling, Long polling, Streaming \uac19\uc740 \uae30\uc220\uc744 \uc0ac\uc6a9\ud588\uc5b4\uc57c \ud588\ub2e4. \\n\uc774\ub294 \uc2e4\uc2dc\uac04\uc131\uc774\ub098 \uc591\ubc29\ud5a5\uc131\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \ubabb\ud588\uace0, HTTP\ub97c \uc774\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uacfc\ub3c4\ud55c \uc624\ubc84\ud5e4\ub4dc\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\\n:::note polling, long polling, streaming\\n\\nPolling: \uc8fc\uae30\uc801\uc73c\ub85c \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ubcf4\ub0b4 \uc218\uc2e0\ud560 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubc29\ubc95\\n- \uc11c\ubc84\uc5d0\uc11c \ubcf4\ub0bc \ub0b4\uc6a9\uc774 \uc5c6\uc5b4\ub3c4 \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc54c \uc218 \uc5c6\ub2e4. \\n- \uacc4\uc18d\ud574\uc11c \uc694\uccad\uc744 \ubcf4\ub0b4 \ud655\uc778\uc744 \ud574\uc57c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ubd88\ud544\uc694\ud55c \ubd80\ud558\ub97c \uc8fc\uc5b4\uc57c \ud55c\ub2e4. \\n\\nLong Polling: \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc5d0 \ub300\ud574 \uc751\ub2f5\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uace0 \uc788\ub2e4\uac00 \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud588\uc744\ub54c \uc751\ub2f5\ud558\ub294 \ubc29\ubc95\\n- \ud3f4\ub9c1 \ubc29\uc2dd\ubcf4\ub2e4 \uc11c\ubc84\uc5d0 \uc801\uc740 \ubd80\ud558\ub97c \uc904 \uc218 \uc788\uc9c0\ub9cc, \uc694\uccad\uc758 \uc8fc\uae30\uac00 \uc9e7\uc73c\uba74 \ud3f4\ub9c1\uacfc \ucc28\uc774\uac00 \uc5c6\uc5b4\uc9c4\ub2e4.\\n\\nStreaming: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 request\ub97c \ubcf4\ub0b4\uba74 \ucee4\ub125\uc158\uc744 \ub9fa\uace0, \uc774 \ucee4\ub125\uc158\uc744 \uc720\uc9c0\ud558\uba74\uc11c \uc11c\ubc84\uac00 \uacc4\uc18d \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95\\n- \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ud558\uace0 \uc2f6\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ucee4\ub125\uc158\uc744 \ub9fa\uc5b4\uc57c \ud55c\ub2e4. \\n:::\\n\\n### \uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791\\n\\n```mermaid\\nsequenceDiagram\\n participant Client\\n participant Server\\n Client->>Server: Handshake - Upgrade\ub97c \uc774\uc6a9\ud55c WebSocket \uc804\ud658 \uc694\uccad\\n Server->>Client: Handshake - HttpStatus 101(Switching Protocols)\\n\\n Client->>Server: \uc591\ubc29\ud5a5 \ud1b5\uc2e0\\n Server->>Client: \\n\\n Client->>Server: \uc885\ub8cc\\n Server->>Client: \\n```\\n\\n### 1. Upgrade \uc694\uccad\\n\\nWebSocket \ud504\ub85c\ud1a0\ucf5c\ub85c \uc804\ud658\ud558\ub294 HTTP \uc694\uccad\uc744 \ubcf4\ub0b8\ub2e4. \\n\uc774\ub294 HTTP\uc640 \uac19\uc774 80, 443 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud55c\ub2e4. \\n\uc6f9\uc18c\ucf13\uc73c\ub85c \uc804\ud658\ud558\uae30 \uc704\ud574\uc11c\ub294 Upgrade: websocket, Connection: Upgrade \ud5e4\ub354\uac00 \ud544\uc694\ud558\ub2e4. \\nSec-WebSocket-Key\ub294 \uc11c\ubc84\uc5d0\uc11c Sec-WebSocket-Accept\ub97c \uacc4\uc0b0\ud558\uc5ec \uc751\ub2f5\ud558\uace0 \uc774 \uac12\uc774 \uc608\uc0c1\ud55c \uac12\uacfc \ub2e4\ub974\uba74 \uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uc9c0 \uc54a\ub294\ub2e4. \\nSec-WebSocket-Protocol\uc758 \uacbd\uc6b0 \uc11c\ube0c\ud504\ub85c\ud1a0\ucf5c\uc758 \ubaa9\ub85d\uc73c\ub85c \uc11c\ubc84 \uce21\uc5d0\uc11c\ub294 \ud574\ub2f9 \ubaa9\ub85d \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud558\uc5ec \ubc18\ud658\ud574\uc57c \ud55c\ub2e4. \\n\ub9cc\uc57d \uc11c\ubc84\uce21\uc5d0\uc11c \uc5ec\ub7ec \uac1c \uc9c0\uc6d0\uc774 \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc9c0\uc6d0 \uac00\ub2a5\ud55c \ud504\ub85c\ud1a0\ucf5c \uc911 \uccab\ubc88\uc9f8 \ud504\ub85c\ud1a0\ucf5c\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc73c\ub85c \ubcf4\ub0b8\ub2e4. \\n\\n```\\nGET /chats HTTP/1.1\\nHost: localhost:8080\\nUpgrade: websocket\\nConnection: Upgrade\\nSec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==\\nSec-WebSocket-Protocol: v10.stomp, v11.stomp\\nSec-WebSocket-Version: 13\\nOrigin: http://localhost:8080\\n```\\n\\n### 2. Switching Protocols\\n\\n\uc11c\ubc84\ub294 101 Switching Protocols \uc751\ub2f5\uc744 \ubc18\ud658\ud55c\ub2e4. \\nSec-WebSocket-Accept\uc740 Sec-WebSocket-Key \ub4a4\uc5d0 `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`\ub97c \ubd99\uc774\uace0 SHA1\ub85c \ud574\uc2f1 \ud6c4 Base64\ub85c \uc778\ucf54\ub529\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4. \\n\uc774\ub294 \uc11c\ubc84 \uc6f9\uc18c\ucf13 \ud504\ub85c\ud1a0\ucf5c\uc758 \uc9c0\uc6d0 \uc5ec\ubd80\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uba85\ud655\ud788 \uc54c\ub9ac\uae30 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4. \\n\\n```\\nHTTP/1.1 101 Switching Protocols \\nUpgrade: websocket\\nConnection: Upgrade\\nSec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=\\nSec-WebSocket-Protocol: v10.stomp\\n```\\n\\n### 3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc\\n\\n\uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uba74 \uc6f9\uc18c\ucf13 \ud504\ub808\uc784 \ub2e8\uc704\ub85c \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \ud55c\ub2e4. \\n\uc5f0\uacb0 \uc885\ub8cc\ub97c \uc6d0\ud558\ub294 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8, \uc11c\ubc84 \ubaa8\ub450 \uc5f0\uacb0 \uc885\ub8cc\ub97c \uc694\uccad\ud560 \uc218 \uc788\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\nhttps://datatracker.ietf.org/doc/html/rfc6455 \\nhttps://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications \\nhttps://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers \\nhttps://docs.spring.io/spring-framework/reference/web/websocket.html"},{"id":"java-spring-springboot","metadata":{"permalink":"/java-spring-springboot","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx","source":"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx","title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","description":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","date":"2023-07-24T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 24\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Spring Boot","permalink":"/tags/spring-boot"},{"label":"Spring","permalink":"/tags/spring"}],"readingTime":4.725,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","slug":"java-spring-springboot","tags":["Java","Spring Boot","Spring"]},"unlisted":false,"prevItem":{"title":"\uc6f9\uc18c\ucf13","permalink":"/websocket"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","permalink":"/route-image-intro"}},"content":"## \uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\\n\\n\ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\uc744 \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\ub2e4. \\n2.7 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc5c8\uc9c0\ub9cc LTS \uae30\uac04\uacfc \ucde8\uc57d\uc810 \ud328\uce58\ub85c \uc778\ud55c \ubc84\uc804\uc5c5 \ub4f1\uc744 \uace0\ub824\ud588\uc744 \ub54c 3.1\uacfc \uc790\ubc14 17\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \ub354 \ud6a8\uc728\uc801\uc774\ub77c\uace0 \ud310\ub2e8\ud588\ub2e4.\\n\\n## \uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2\uae4c\uc9c0\ub294 \uc790\ubc14 11\uc744 \uc0ac\uc6a9\ud588\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \uc790\ubc14 11\ubd80\ud130 \uc790\ubc14 17\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d\uc744 \uc815\uc2dd \ub9b4\ub9ac\uc988 \uae30\uc900\uc73c\ub85c \uc815\ub9ac\ud574\ubcf4\ub824\uace0 \ud55c\ub2e4.\\n\\n### Switch Expressions(Java 14)\\n\\nJava 14\uc5d0\uc11c\ub294 \uae30\uc874\uc758 Switch \ubb38\uc744 \uac04\uacb0\ud558\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub294 Switch \uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n```java\\nenum RESULT {\\n WIN, LOSE, DRAW\\n}\\n\\nRESULT result = RESULT.WIN;\\n\\nint prize = switch (result) {\\n case WIN -> 10_000_000;\\n case LOSE, DRAW -> 5_000_000;\\n\\tdefault -> 0;\\n};\\n```\\n\\n\uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.\\n\\n- `->` \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 case\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc14\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub2e4.\\n- case\ub97c \ucf64\ub9c8(`,`)\ub85c \uc5f0\uacb0\ud558\uc5ec \ud558\ub098\uc758 case\uc5d0 \uc5ec\ub7ec \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n- break \ubb38\uc774 \ud544\uc694 \uc5c6\ub2e4.\\n- default \ube14\ub85d\uc744 \ud1b5\ud574 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n\\n### Text Block(Java 15)\\n\\nJava 15\uc5d0\ub294 \uc0c8\ub85c\uc6b4 \ubb38\uc790\uc5f4 \ud45c\ud604\ubc29\uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\uae34 \ubb38\uc790\uc5f4\uc744 + \uc5f0\uc0b0\uc790\uc758 \ub3c4\uc6c0 \uc5c6\uc774 \uac00\ub3c5\uc131\uc788\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n@Repository\\npublic interface PostRepository extends JpaRepository {\\n @Query(\\"\\"\\"\\n SELECT p FROM Post p\\n WHERE p.title LIKE %:keyword%\\n OR p.content LIKE %:keyword%\\n \\"\\"\\")\\n List findPostsByTitleOrContentContainingKeyword(String keyword);\\n}\\n```\\n\\n### NPE \uba54\uc2dc\uc9c0(Java 15)\\n\\n```java\\nString name = null;\\nname.chars();\\n\\n/** \\n# before\\njava.lang.NullPointerException\\n\\tat com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)\\n\\n# after\\nCannot invoke \\"String.chars()\\" because \\"name\\" is null\\njava.lang.NullPointerException: Cannot invoke \\"String.chars()\\" because \\"name\\" is null\\n*/\\n```\\n\\n### Record(Java 16)\\n\\nLombok\uc758 `@Data`, kotlin\uc758 data \ud074\ub798\uc2a4\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4. \\nRecord\ub97c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0 \uc811\uadfc\uc790, \uc0dd\uc131\uc790, equals & hashcode, toString\uc774 \uc81c\uacf5\ub41c\ub2e4. \\n\ub370\uc774\ud130 \uc804\uc1a1 \uc6a9\ub3c4\ub85c \uc801\ud569\ud574 \ubcf4\uc778\ub2e4. \\n\\n```java\\npublic record PostDto(String title, String content) {\\n}\\n```\\n\\n### \ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d\\n\\n\uc774\uc678\uc5d0\ub3c4 stream\uc758 toList, \uc778\uc2a4\ud134\uc2a4\uc758 \ud0c0\uc785\uc744 \uac04\ud3b8\ud558\uac8c \uccb4\ud06c\ud558\ub294 Pattern Matching Instanceof, Sealed class \ub4f1\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n## \uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d\\n\\n\uc2a4\ud504\ub9c1\uacfc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\ub3c4 \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \ud544\uc694\ud574\ubcf4\uc774\ub294 \uba87\uac1c \uc815\ub3c4\ub9cc \uc815\ub9ac\ud588\ub2e4. \\n\\n### \uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d\\n\\nJava 17, Jakarta EE 9 \uc774\uc0c1\uc774\uc5b4\uc57c \ud55c\ub2e4.\\n\\n### \ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd\\n\\nJakarta EE 9\uac00 \uc801\uc6a9\ub418\uba74\uc11c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub3c4 \uc804\ubc18\uc801\uc73c\ub85c javax -> jakarta\ub85c \ubcc0\uacbd\ub418\uc5c8\ub2e4. \\n\\n### PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c\\n\\n6.0 \uc774\uc804\uc758 \uacbd\uc6b0 \uae30\ubcf8 \uc124\uc815 \uae30\uc900\uc73c\ub85c `@GetMapping(\\"/hello\\")`\uc640 `@GetMapping(\\"/hello/\\")`\uac00 \ub3d9\uc77c\ud588\ub2e4. \\n6.0 \uc774\ud6c4\uc758 PathPatternParser\uac00 \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0, `/hello`\uc640 `/hello/`\ub294 \uc11c\ub85c \ub2e4\ub978 URL\ub85c \ub9e4\uce6d\ub41c\ub2e4. \\n\\n> PathPatternParser used by default (with the ability to opt into PathMatcher). \\n\\n### HTTP interface client\\n\\n\uc790\ubc14 \uc778\ud130\ud398\uc774\uc2a4\uc640 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc774\uc6a9\ud558\uc5ec HTTP \uc694\uccad\uc744 \uc704\ud55c \uc11c\ube44\uc2a4\ub97c \uc815\uc758\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [\ud1a0\ube44\ub2d8\uc758 \uac15\uc758](https://www.youtube.com/watch?v=Kb37Q5GCyZs)\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n### \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d\\n\\nGradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6 \\n\uc774\uc678\uc5d0\ub3c4 \uc11c\ub4dc\ud30c\ud2f0\ub4e4\uc758 \ucd5c\uc2e0 \ub9b4\ub9ac\uc988 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud568\uc73c\ub85c, \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ubc84\uc804\uc5d0 \ub9de\ub294 \ub9b4\ub9ac\uc988 \ub178\ud2b8\ub97c \ucc38\uace0\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[\uc5b4\ub290\xa0\uc6d4\uae09\uc7c1\uc774\uac1c\ubc1c\uc790\xa0\uc758 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ub530\ub77c\uc7a1\uae30](https://www.youtube.com/watch?v=1WT6oxchM9M) \\n[\uc790\ubc14 9-16 \uc8fc\uc694 \ud2b9\uc9d5 \ubcf5\uc2b5\ud558\uae30](https://www.youtube.com/watch?v=7SlDdzVk6GE) \\n[Java EE\uc5d0\uc11c Jakarta EE\ub85c\uc758 \uc804\ud658](https://www.samsungsds.com/kr/insights/java_jakarta.html) \\n[Spring 6\uc758 \uc0c8\ub85c\uc6b4 HTTP Interface\uc640 3 \uac00\uc9c0 REST Clients \ub77c\uc774\ube0c \ucf54\ub529](https://www.youtube.com/watch?v=Kb37Q5GCyZs) \\n[What\'s New in Spring Framework 6.x](https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-6.x) \\n[Spring Boot 3.0 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes) \\n[Spring Boot 3.1 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes)"},{"id":"route-image-intro","metadata":{"permalink":"/route-image-intro","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx","source":"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","description":"./route.png","date":"2023-07-27T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 27\uc77c","tags":[{"label":"image","permalink":"/tags/image"},{"label":"awt","permalink":"/tags/awt"}],"readingTime":5.865,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","slug":"route-image-intro","tags":["image","awt"]},"unlisted":false,"prevItem":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","permalink":"/java-spring-springboot"},"nextItem":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","permalink":"/mock-static-method"}},"content":"![./route.png](./route.png)\\n\\n### \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784\\n\\n\uc704 \uc640\uc774\uc5b4 \ud504\ub808\uc784\uc5d0\uc11c `\uc5ec\ud589 \ud788\uc2a4\ud1a0\ub9ac`\uc640 `\uc5ec\ud589\uc5d0 \ub300\ud55c \uac10\uc0c1\uc744 \uc704\ud55c \uacbd\ub85c \uc774\ubbf8\uc9c0`\uc758 \uacbd\uc6b0 \ub124\uc774\ubc84 \uc9c0\ub3c4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \uc218 \uc5c6\uc73c\ub2c8 \ub2f9\uc5f0\ud788 \ub9f5 API\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub3c4\ud615 \uadf8\ub9ac\uae30 API(\ub124\uc774\ubc84 \ub9f5 API \uae30\uc900 Polyline)\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4. \\n\ub530\ub77c\uc11c \uc774\ubbf8\uc9c0\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uac70\ub098, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c1\uc811 \uc704\uacbd\ub3c4\ub97c \uc774\uc6a9\ud558\uc5ec \uadf8\ub824\uc57c \ud55c\ub2e4.\\n\\n\ud574\ub2f9 \uc694\uad6c\uc0ac\ud56d\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uae30\ub2a5\uc744 \uac00\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud544\uc694\ud558\ub2e4.\\n\\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n- \uc120\uacfc \uc810 \ud45c\ud604\\n- \ud22c\uba85\ud55c \ubc30\uacbd\uc0c9\\n\\n\ud604\uc7ac \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ubc14\uc05c \uc77c\uc815\uacfc \uae30\ub2a5 \uad6c\ud604\uc5d0 \uc788\uc5b4 \uc57d\uac04\uc758 \uc5f0\uc0b0\uc774 \ub4e4\uc5b4\uac04\ub2e4\ub294 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uc5ec \ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30\ub85c \uacb0\uc815\uc744 \ub0b4\ub838\ub2e4.\\n\\n### \uace0\ub824\ud55c \uae30\uc220\\n\\n\ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uae30 \uc704\ud574 \ub2e4\uc74c\uacfc \uac19\uc740 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 \uae30\uc220\ub4e4\uc744 \ud655\uc778\ud574 \ubcf4\uc558\ub2e4. \\n\\n- Python\uc758 Matplotlib\\n- **AWT(Abstract Window Toolkit) [\ucd5c\uc885 \uc120\ud0dd]**\\n- \uc774\ubbf8\uc9c0 \ucc98\ub9ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ubc0f Java\uc5d0\uc11c \ub0b4\ubd80\uc801\uc73c\ub85c Matplotlib \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac (\uc6d0\ud558\ub294 \uae30\ub2a5 \uc5c6\uc74c)\\n- Java Swing, Java FX (\ub2e8\uc21c\ud55c \uc120 \uadf8\ub9ac\uae30 + \uc810 \ucc0d\uae30\ub77c \ubd88\ud544\uc694)\\n\\n## Python & Matplotlib\\n\\n\ub370\uc774\ud130 \uc2dc\uac01\ud654 \ub77c\uc774\ube0c\ub7ec\ub9ac \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 0.2\ucd08 \\n\\n- \ucf54\ub4dc\uac00 \uac04\ub2e8\ud574\uc11c \uc720\uc9c0 \ubcf4\uc218\uc131\uc774 \uc88b\ub2e4. \\n- AWS Lambda \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ucef4\ud4e8\ud305 \uc11c\ube44\uc2a4\ub098 FastAPI\uc640 \uac19\uc740 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\ub85c \ucd94\uac00\uc801\uc778 API\ub97c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4.\\n- Spring Boot\uc5d0\uc11c \ucd94\uac00\uc801\uc778 API \ud638\ucd9c\uc744 \ud574\uc57c\ud558\uace0, \ud655\uc7a5\uc131\uacfc \ube44\ub3d9\uae30 \ucc98\ub9ac \ub4f1 \uace0\ub824 \ud574\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\ub2e4.\\n\\n### Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\\n\\nPython\uc774 \uc544\ub2cc Java\uc5d0\uc11c\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub3c4 \uace0\ub824\ub97c \ud574\ubd24\uc9c0\ub9cc \uc694\uad6c\uc0ac\ud56d\uc5d0 \uc801\ud569\ud558\uc9c0 \uc54a\uac70\ub098, \uc801\uc740 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac70\uc6b4 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\uc678\ud588\ub2e4.\\n\\n\ub77c\uc774\ube0c\ub7ec\ub9ac | \uc124\uba85 | \uc81c\uc678 \uc774\uc720\\n-- | -- | --\\nSwing | AWT \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, \ub124\uc774\ud2f0\ube0c UI\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubaa8\ub4e0 \uc6b4\uc601\uccb4\uc81c \uc0c1\uc5d0\uc11c \ub3d9\uc77c\ud55c UI\ub97c \uac00\uc9c0\ub3c4\ub85d \ud568 | \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c\\nJavaFX | Swing \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, 3\ucc28\uc6d0 \uadf8\ub798\ud53d\uc744 \uc9c0\uc6d0\ud568 | \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c\\n[simple-java-plot](https://github.com/yuriy-g/simple-java-plot) | AWT\ub85c \uad6c\ud604\ub41c \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac | AWT \uae30\ubc18\uc774\uae34 \ud558\uc9c0\ub9cc \uc9c1\uc811 AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc5d0 \ube44\ud574 \uba54\ub9ac\ud2b8\uac00 \uc5c6\uc74c, \ucee4\uc2a4\ud140 \uc124\uc815 \uae30\ub2a5\uc774 \uc5c6\uc74c\\n[matplotlib4j](https://github.com/sh0nk/matplotlib4j) | Matplotlib\ub97c Java\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud558\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac | \ub0b4\ubd80\uc801\uc73c\ub85c \ud30c\uc774\uc36c \uc0ac\uc6a9\ud558\uae30\uc5d0 \ubb34\uac70\uc6c0, \ubc30\uacbd \ud22c\uba85\ud654 \uae30\ub2a5 \uc5c6\uc74c\\n\\n### Java & AWT(Abstract Window Toolkit)\\n\\n\uadf8\ub798\ud53d\uacfc \uc774\ubbf8\uc9c0\ub97c \uadf8\ub9ac\uae30 \uc704\ud55c \ub3c4\uad6c \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 1.75\ucd08 \\n\\n- \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ubcf4\ub2e4 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc874\uc7ac\ud55c\ub2e4.\\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub2e4\uc18c \uc18c\uc694\ub418\uae30 \ub54c\ubb38\uc5d0 \ube60\ub978 \uc751\ub2f5 \ubc18\ud658\uc744 \uc704\ud574 \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.\\n- \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.\\n\\n### \uae30\uc220 \uc120\ud0dd\\n\\nAWT\uc758 \uacbd\uc6b0 Matplotlib\uc5d0 \ube44\ud574 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc788\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub354 \ub9ce\uc774 \uac78\ub9ac\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub418\ub294 \ubd80\ubd84, Python\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc778 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uace0\ub824\ud558\uc5ec AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.\\n\\n### \uc720\uc9c0 \ubcf4\uc218\\n\\nAWT\ub77c\ub294 \uc0dd\uc18c\ud55c \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc720\uc9c0 \ubcf4\uc218\uc131\uc744 \uc704\ud574 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub530\ub77c\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\ubc95\uc73c\ub85c \uacf5\uc720\ud558\uae30\ub85c \ud588\ub2e4. \\n\\n1. \ucf54\ub4dc \ub9ac\ubdf0\uc640 PR\uc744 \ud1b5\ud574 \uc791\uc131\ud55c AWT \ucf54\ub4dc\uc5d0 \ub300\ud55c \uc124\uba85 \ubc0f \ub9ac\ubdf0 \ubc1b\ub294\ub2e4. \\n2. AWT\ub97c \uc0ac\uc6a9\ud55c \ubd80\ubd84\uc744 \ubb38\uc11c\ud654\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4.\\n\\n### \ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00\\n\\n\uae30\uc220 \uc120\ud0dd\uc744 \ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815\uc5d0 \uc624\ub958\uac00 \uc788\uc5c8\ub2e4. \\nAWT\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589 \uc2dc\uac04\uc744 \uc81c\uc678\ud558\uba74 \ud30c\uc774\uc36c\uacfc \ube44\uc2b7\ud55c \uc2dc\uac04\uc548\uc5d0 \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud560 \uc218 \uc788\uc5c8\ub2e4."},{"id":"mock-static-method","metadata":{"permalink":"/mock-static-method","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx","source":"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx","title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","description":"\uac1c\uc694","date":"2023-07-30T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 30\uc77c","tags":[{"label":"Mockito","permalink":"/tags/mockito"},{"label":"static","permalink":"/tags/static"}],"readingTime":2.635,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","slug":"mock-static-method","tags":["Mockito","static"]},"unlisted":false,"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","permalink":"/route-image-intro"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","permalink":"/route-image-python"}},"content":"### \uac1c\uc694\\n\\n\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud55c\ub2e4\ub294 \uac83\uc740 \uac1d\uccb4\uc9c0\ud5a5\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ubcfc \ub54c \uc548\ud2f0\ud328\ud134\uc774\ub2e4. \\n\ud558\uc9c0\ub9cc \ud2b9\uc218\ud55c \uacbd\uc6b0\uc5d0\ub294 \uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc774 \ud544\uc694\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n\uc608\ub97c \ub4e4\uc5b4 \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud55c\ub2e4\ub358\uc9c0, IO \uad00\ub828\ud55c \ubd80\ubd84\uc744 \ud14c\uc2a4\ud2b8 \ud560 \ub54c \uc815\ub9d0 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\ub9cc \uc801\uc6a9\ud560 \uc218 \uc788\uc744 \uac83\uc774\ub2e4. \\n\\n\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba70 ImageIo.write \uba54\uc11c\ub4dc\uac00 \ud638\ucd9c\ub418\ub294 \uc9c0 \uac80\uc99d\uc774 \ud544\uc694\ud588\ub2e4. \\n\ud574\ub2f9 static \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294 \ubd80\ubd84\uc744 \ub530\ub85c RouteImageUploader \ud074\ub798\uc2a4\ub85c \ucd5c\ub300\ud55c \ubd84\ub9ac\ud588\ub2e4. \\n\uc774\ubbf8\uc9c0 \uc800\uc7a5 \uae30\ub2a5 \uc790\uccb4\uac00 \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc774\uace0, \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294\ub370\ub294 mock\uc744 \uc0ac\uc6a9\ud558\ub294\uac8c \uc801\uc808\ud558\ub2e4\uace0 \ud310\ub2e8\ud588\ub2e4. \\n\\n```java\\npublic void upload(BufferedImage bufferedImage) {\\n File file = new File(\ud30c\uc77c\uacbd\ub85c);\\n try {\\n ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);\\n } catch (IOException e) {\\n throw new DrawException(IMAGE_SAVE_FAIL);\\n }\\n}\\n```\\n\\n### Mocking static methods\\n\\nMockito 3.4.0 \uc774\ud6c4\uc5d0\ub294 static method\ub97c \ubaa8\ud0b9\ud560 \uc218 \uc788\ub294 Mockito.mockStatic \uba54\uc11c\ub4dc\ub97c \uc9c0\uc6d0\ud55c\ub2e4. \\nmockStatic\uc744 \uc0ac\uc6a9\ud558\uba74 `MockedStatic`\uc774 \ubc18\ud658\ub418\ub294\ub370 \uc0ac\uc6a9 \ud6c4 \uaf2d close\ub97c \ud574\uc918\uc57c \ud55c\ub2e4. \\n\\nJUnit\uc758 @BeforeAll\ub85c \uc124\uc815\ud558\uace0 @AfterAll \uba54\uc11c\ub4dc\ub85c \uc885\ub8cc\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\uc9c0\ub9cc `MockedStatic`\uc758 \uc0c1\uc704 \uc778\ud130\ud398\uc774\uc2a4\uc778 ScopedMock\uc774 AutoCloseable\uc744 \uad6c\ud604\ud558\uace0 \uc788\uae30\uc5d0 try-with-resources\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \ub354\uc6b1 \uc88b\uc740 \uac83 \uac19\ub2e4. \\n\\n```java\\n// given\\nBufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);\\nRouteImageUploader routeImageUploader = new RouteImageUploader();\\n\\n// expect\\ntry (MockedStatic imageIO = Mockito.mockStatic(ImageIO.class)) {\\n routeImageUploader.upload(bufferedImage);\\n imageIO.verify(\\n () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),\\n times(1)\\n );\\n}\\n```\\n\\n### \ub9c8\uce58\uba70\\n\\n\uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc740 \uc548\ud2f0\ud328\ud134\uc774\uc73c\ub85c \uc801\uc808\ud55c \ucd94\uc0c1\ud654\ub97c \uc774\uc6a9\ud574 \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc88b\uc740 \ucf54\ub4dc\ub97c \ub9cc\ub4dc\ub294 \uc5f0\uc2b5\uc744 \ud558\uc790. \\n\ud558\uc9c0\ub9cc \ucd94\uc0c1\ud654\ub97c \ud558\uba74 \ud560 \uc218\ub85d \ucf54\ub4dc\uc758 \ubcf5\uc7a1\ub3c4\ub294 \uc99d\uac00\ud55c\ub2e4. \\n\ud56d\uc0c1 \uc0c1\ud669\uc744 \uace0\ub824\ud558\uace0 \uac04\uacb0\ud568\uc744 \ud3ec\uae30\ud560 \ub9cc\ud07c \uc911\uc694\ud55c \ubd80\ubd84\uc778\uc9c0 \uc801\uc808\ud55c \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uace0\ub824\ud558\uc790. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Mocking static methods](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks) \\n[Mockito mock static methods](https://www.baeldung.com/mockito-mock-static-methods) \\n[Enable mocking static methods in Mockito](https://github.com/mockito/mockito/issues/1013)"},{"id":"route-image-python","metadata":{"permalink":"/route-image-python","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx","source":"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","description":"\uac1c\uc694","date":"2023-07-31T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 31\uc77c","tags":[{"label":"Image","permalink":"/tags/image"},{"label":"Python","permalink":"/tags/python"}],"readingTime":6.185,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","slug":"route-image-python","tags":["Image","Python"]},"unlisted":false,"prevItem":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","permalink":"/mock-static-method"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","permalink":"/route-image-implementation"}},"content":"### \uac1c\uc694\\n\\n\uc774\uc804\uc5d0 \uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\uc0ac\ud558\uba74\uc11c \ud30c\uc774\uc36c\uc744 \uc0ac\uc6a9\ud55c \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud55c \ub0b4\uc6a9\uc774\ub2e4. \\n\\n### \uc0ac\uc6a9 \uae30\uc220\\n\\n\uc5b8\uc5b4: Python 3.10 \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131: matplotlib \\n\uc11c\ube44\uc2a4: AWS Lambda, AWS API Gateway \\n\uc774\ubbf8\uc9c0 \uc800\uc7a5 \ubc0f URL: AWS S3, AWS CloudFront \\n\\n\ud50c\ub85c\uc6b0\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```mermaid\\ngraph LR\\n Server -- \uc0dd\uc131 \uc694\uccad --\x3e AG[API Gateway] --\x3e Lambda --\x3e S3\\n Client --\x3e CloudFront --\x3e S3\\n```\\n\\n### \uc694\uad6c\uc0ac\ud56d\\n\\n![./route.png](./route.png)\\n\\n\uc6b0\uce21 \uc0c1\ub2e8\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub824\uace0 \ud55c\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.\\n\\n- \uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \ubc30\uc5f4\uc744 \uc785\ub825\ubc1b\ub294\ub2e4. \\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n- \uc120\uacfc \uc810 \ud45c\ud604\\n- \ud22c\uba85\ud55c \ubc30\uacbd\uc0c9\\n- \uc704\uacbd\ub3c4 \ucc28\uc774\uac00 \ud06c\ub4e0 \uc791\ub4e0 \uc81c\uacf5\ud558\ub294 \uc774\ubbf8\uc9c0 \ub0b4\uc5d0 \uacbd\ub85c\uac00 \ub2e4 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### \uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\\n\\n1. \uc704\uacbd\ub3c4\ub97c \ucc98\ub9ac\ud55c \uac12\uc73c\ub85c \uc9c1\uc811 \uacbd\ub85c\ub97c \uadf8\ub9b0 \ub2e4\uc74c \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5\\n2. \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc0ac\uc6a9\ud558\uc5ec \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5\\n\\n\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\uc758 \uacbd\uc6b0 1\ubc88\uacfc 2\ubc88\uc744 \uace0\ubbfc\ud588\uc5c8\ub2e4. \\n\ud30c\uc774\uc36c\uc73c\ub85c\ub294 \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc778 matplotlib\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604\\n\\n```python\\nimport time\\n\\nimport matplotlib.pyplot as plt\\n\\n\\ndef draw(point):\\n start = time.time()\\n x, y = zip(*point)\\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\\n draw_lines(pixel_x, pixel_y)\\n end = time.time()\\n print(end - start)\\n \\ndef convert_to_pixel_values(x, y):\\n max_diff = max(max(x) - min(x), max(y) - min(y))\\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\\n\\n\\ndef scale_to_pixel_values(points, max_diff):\\n min_value = min(points)\\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\\n return scaled_coordinates\\n\\n\\ndef draw_lines(x, y):\\n figure = plt.gcf()\\n figure.set_size_inches(5, 5)\\n plt.plot(x, y, c = \'w\',linewidth=5)\\n plt.scatter(x[3],y[3], c = \'w\', s = 125)\\n plt.axis(\'off\')\\n plt.savefig(\'name.png\', transparent=True, format=\'png\')\\n\\npoint = [\\n [126.96352960597338, 37.590841000217125],\\n [126.96987292787792, 37.58435564234159],\\n [126.98128481452298, 37.58594375113966],\\n [126.99360339342958, 37.58248524741927],\\n [126.99867565340067, 37.56778118088622],\\n [127.001935378366117, 37.55985240444085],\\n [126.9831048919687, 37.548030119488665],\\n [126.97189273528845, 37.5119879225856],\\n [127.02689859997221, 37.48488593333883]\\n]\\n\\ndraw(point)\\n```\\n\\n\uc0dd\uc131 \uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4. (\uc608\uc2dc\ub97c \uc704\ud574 \uac80\uc740\uc0c9\uc73c\ub85c \ucd9c\ub825)\\n\\n![./routeImage.png](./routeImage.png)\\n\\n### AWS Lambda\\n\\n\uc378\ub124\uc77c \uc0dd\uc131 \uc11c\ubc84\ub97c \ub530\ub85c \ub450\uae30\ub294 \uae30\ub2a5 \ub300\ube44 \ube44\uc6a9\uc774 \ub108\ubb34 \ud074 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub530\ub77c\uc11c \uc11c\ubc84\ub9ac\uc2a4\ub85c \ud30c\uc77c\uc744 \ucc98\ub9ac\ud588\ub2e4. \\n\ucd94\uac00\ub85c s3 \uc811\uadfc\uc740 boto3\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131\\n\\nAmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy \ub450\uac00\uc9c0\ub97c \ucd94\uac00\ud574\uc11c Lambda \uc804\uc6a9 \uc5ed\ud560\uc744 \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc\\n\\n\uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \ud655\uc778\ud560 \ub550 \uc704\uce58 \uc810\uc744 \ucc0d\ub294 \uae30\ub2a5\uc744 \ub78c\ub2e4\uc5d0 \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\\n```python\\n\\nimport io\\nimport uuid\\n\\nimport boto3\\nimport matplotlib.pyplot as plt\\n\\nPIXEL = 255\\nBUCKET_NAME = \'image-plot\'\\nS3 = \'s3\'\\n\\ndef lambda_handler(event, context):\\n x = event[\'x\']\\n y = event[\'y\']\\n image_name = str(uuid.uuid4())\\n\\n img_data = draw(x, y)\\n s3 = boto3.client(S3)\\n s3.put_object(Body=img_data.getvalue(), ContentType=\'image/png\', Bucket=BUCKET_NAME, Key=image_name)\\n url = f\'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}\'\\n\\n return {\\n \'statusCode\': 200,\\n \'body\': url\\n }\\n\\ndef draw(x, y):\\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\\n img_data = draw_lines(pixel_x, pixel_y)\\n plt.close()\\n return img_data\\n\\ndef convert_to_pixel_values(x, y):\\n max_diff = max(max(x) - min(x), max(y) - min(y))\\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\\n\\ndef scale_to_pixel_values(points, max_diff):\\n min_value = min(points)\\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\\n pixel_values = [int(p * PIXEL) for p in scaled_coordinates]\\n return pixel_values\\n\\ndef draw_lines(x, y):\\n plt.plot(x, y, \'k-\', linewidth=10)\\n plt.axis(\'off\')\\n img_data = io.BytesIO()\\n plt.savefig(img_data, transparent=True, format=\'png\')\\n img_data.seek(0)\\n return img_data\\n\\n```\\n\\n### Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131\\n\\nmatplotlib\uc758 \uacbd\uc6b0 \uc678\ubd80 \ub77c\uc774\ube0c\ub7ec\ub9ac\uae30 \ub54c\ubb38\uc5d0 \ub530\ub85c Layer\ub97c \ucd94\uac00\ud574\uc57c \ud55c\ub2e4. \\nzip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \uc5c5\ub85c\ub4dc\ud574\uc57c\ud55c\ub2e4. \\n\uc774\ub54c python\uc758 Lambda \ub7f0\ud0c0\uc784\uc5d0 \ub300\ud55c \uacc4\uce35 \uacbd\ub85c\ub294 python\uc774\ub2e4. \\n\ub530\ub77c\uc11c \uc555\ucd95\ud55c zip \ud30c\uc77c\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \ub744\uc5b4\uc57c \ud55c\ub2e4. \\n\\n```\\npillow.zip\\n\u2502 python/PIL\\n\u2514 python/Pillow-5.3.0.dist-info\\n```\\n\\nUbuntu \uae30\uc900 \ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc0dd\uc131\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\\n```\\nsudo apt update\\nsudo apt install zip\\nsudo apt install python3-pip\\n\\nmkdir python\\npip3 install matplotlib -t python # pip3 install \uc124\uce58\ud560_\ud328\ud0a4\uc9c0 -t \uc124\uce58_\uacbd\ub85c\\nzip -r my_layer.zip python # zip -r \uc555\ucd95_\ud30c\uc77c\uba85 \uc555\ucd95_\ud30c\uc77c\uc774_\uc874\uc7ac\ud558\ub294_\uacbd\ub85c\\n```\\n\\n### `No module named \'numpy.core._multiarray_umath\'` \uc5d0\ub7ec\\n\\nLayer \ucd94\uac00 \ud6c4 \ub78c\ub2e4 \uc2e4\ud589 \uc2dc \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\uc600\ub2e4. \\n\ucc98\uc74c\uc5d0 mac\uc5d0\uc11c zip \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc5c5\ub85c\ub4dc\ud588\ub294\ub370 \ud574\ub2f9 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\uc774\ub294 lambda\uac00 \ub3cc\uc544\uac00\ub294 \ub3d9\uc77c\ud55c \ud658\uacbd\uc5d0\uc11c layer\ub97c \uc704\ud55c zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc9c0 \uc54a\uc544\uc11c \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub2e4. \\n\uac04\ub2e8\ud558\uac8c ec2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c \ub530\ub85c Layer\ub97c \uc0dd\uc131\ud558\uba74 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\n### \uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01\\n\\n\ud504\ub85c\uc81d\ud2b8\uc5d0 Lambda\uc640 Python\uc744 \uc0ac\uc6a9\ud558\ub824\uace0 \ud588\uc9c0\ub9cc \uc544\uc27d\uac8c\ub3c4 \ubc18\ub824\ub2f9\ud588\ub2e4. \\nAWS Lambda\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc778\uc2a4\ud134\uc2a4\uc5d0 \ud574\ub2f9 \ucf54\ub4dc\ub97c \ubc30\ud3ec\ud558\ub294 \uac83\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc77c \uc218 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uac00\uc6a9 \uac00\ub2a5\ud55c \uc790\uc6d0, \uae30\uc220\uc758 \ub09c\uc774\ub3c4, \uc0ac\uc6a9\ud558\ub294 \ud300\uc6d0\uc744 \uace0\ub824\ud55c\ub2e4\uba74 Lambda\ub294 \uc801\uc815\uae30\uc220\uc774 \uc544\ub2d0 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ud574\ub2f9 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\ub97c \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud560\uc9c0 \uc870\uae08 \ub354 \uace0\ub824\ub97c \ud574\uc57c \ub420 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4. \\n\\n**\ucd5c\uc885\uc801\uc73c\ub85c Java AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.**\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[AWS Lambda](https://aws.amazon.com/ko/lambda/) \\n[Lambda Layer](https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html) \\n[Python Lambda \ud568\uc218\uc5d0 \ub300\ud55c .zip \ud30c\uc77c \uc544\uce74\uc774\ube0c \uc791\uc5c5](https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html) \\n[No module named \'numpy.core._multiarray_umath\'](https://gist.github.com/ksmin23/0f3f243408a8497f766b43cf589fea7b) \\n[\uc0ac\ub840\ubcc4\ub85c \uc54c\uc544\ubcf8 \uc548\uc804\ud55c S3 \uc0ac\uc6a9 \uac00\uc774\ub4dc](https://techblog.woowahan.com/6217/)"},{"id":"route-image-implementation","metadata":{"permalink":"/route-image-implementation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx","source":"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","description":"\uac1c\uc694","date":"2023-08-02T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 2\uc77c","tags":[{"label":"image","permalink":"/tags/image"},{"label":"awt","permalink":"/tags/awt"}],"readingTime":11.665,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","slug":"route-image-implementation","tags":["image","awt"]},"unlisted":false,"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","permalink":"/route-image-python"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","permalink":"/route-image-async-with-event"}},"content":"## \uac1c\uc694\\n\\n\uc5ec\ud589\uc5d0 \ub300\ud55c \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\uae30 \uc704\ud574 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d \ubc0f \uae30\uc220 \uc120\ud0dd\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 [\ub9c1\ud06c](./route-image-intro)\uc5d0 \uc788\ub2e4.\\n\\n### \uad6c\ud604 \uacb0\uacfc\\n\\n![./result.png](./result.png)\\n\\n\uc608\uc2dc \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n**\uc11c\uc6b8\uc5ed(\uc810)** \u2192 \uc2e0\uc0ac\uc5ed \u2192 \ub178\ub7c9\uc9c4\uc5ed \u2192 \ud64d\ub300\uc785\uad6c\uc5ed \u2192 \uc885\ub85c3\uac00\uc5ed \u2192 \uc625\uc218\uc5ed \u2192 **\uad6c\ub85c\uc5ed(\uc810)** \u2192 \uc2e0\ub9bc\uc5ed \u2192 \ubc1c\uc0b0\uc5ed\\n\\n```java title=\\"\uc608\uc2dc \ub370\uc774\ud130\\"\\nList x = List.of(\\n 126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,\\n 126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639\\n);\\nList y = List.of(\\n 37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,\\n 37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184\\n);\\nList xPoints = List.of(126.97094933811682, 126.88474839801178);\\nList yPoints = List.of(37.55302829553499, 37.50129417536773);\\n```\\n\\n### IMAGE_SIZE & ROUTE_SIZE\\n\\n```java title=\\"RouteImageGenerator.java\\"\\nprivate static final int IMAGE_SIZE = 800;\\nprivate static final int ROUTE_SIZE = 600;\\n```\\n\\n\ucf54\ub4dc\ub97c \ubcf4\uba74 IMAGE_SIZE\uc640 ROUTE_SIZE\uac00 \uc788\ub2e4. \\nIMAGE_SIZE\ub294 \ub9d0 \uadf8\ub300\ub85c \uc774\ubbf8\uc9c0\uc758 width\uc640 height\ub97c \uc758\ubbf8\ud55c\ub2e4. \\nROUTE_SIZE\uc758 \uacbd\uc6b0 \uc0c1\ud558\uc88c\uc6b0 100px \ub9cc\ud07c\uc758 \uac04\uaca9\uc744 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \uc2e4\uc81c \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub294 600 * 600 \uc0ac\uc774\uc988\ub85c \uc0dd\uc131\ub41c\ub2e4. \\n\\n![./600.png](./600.png)\\n\\n**\uc0ac\uc774\uc988 \ubcc0\uacbd\uc758 \uc774\uc720**\\n\\n255 * 255 \uc815\ub3c4\uc758 \uc791\uc740 \uc0ac\uc774\uc988\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud574\ubcf4\ub824\uace0 \ud588\ub294\ub370, \uc774\ubbf8\uc9c0\uc758 \uc120\uba85\ub3c4\uac00 \uc88b\uc9c0 \uc54a\uc544 800 * 800 \uc0ac\uc774\uc988\ub85c \ubcc0\uacbd\ud588\ub2e4.\\n\\n## \uc8fc\uc694 \ud074\ub798\uc2a4\\n\\n### \uc694\uc57d\\n\\n| \ud074\ub798\uc2a4\uba85 | \uc124\uba85 | \ud2b9\uc774\uc0ac\ud56d |\\n| --- | --- | --- |\\n| Coordinate | \uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \uc704\uce58 \uac12 | \uc88c\ud45c\ub97c \ub73b\ud558\uc9c0\ub9cc \uc5ec\ud589 \ub3c4\uba54\uc778\uc5d0 \ud3ec\ud568\ub41c Point \ud074\ub798\uc2a4\uc640 \uad6c\ubd84\ud558\uae30 \uc704\ud574 longitude, latitude\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 x, y \uc0ac\uc6a9 |\\n| Coordinates | Coordinate\uc758 \uc77c\uae09 \uceec\ub809\uc158 | - |\\n| Position | \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58 \uac12 | Integer \ud0c0\uc785\uc758 x, y \uc0ac\uc6a9 |\\n| Positions | Positions\uc758 \uc77c\uae09 \uceec\ub809\uc158 | - |\\n| RouteImageDrawer | \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4 BufferedImage, Graphics2D\ub97c \uac00\uc9c0\uace0 \uc788\uc74c | \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc0c1\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc74c |\\n| RouteImageUploader | BufferedImage\ub97c \ubc1b\uc544 \uc11c\ubc84\uc5d0 \uc5c5\ub85c\ub4dc \ud558\ub294 \ud074\ub798\uc2a4 | \ud604\uc7ac \uc5c5\ub85c\ub4dc \uc704\uce58\uac00 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc544 \uc77c\ub2e8 \uae30\ubcf8(\ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8) \uc704\uce58\uc5d0 \uc0dd\uc131 |\\n| RouteImageGenerator | \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uace0 \uc5c5\ub85c\ub4dc\ud558\ub294 \uc11c\ube44\uc2a4 | \uc5ec\ud589 \uc885\ub8cc, \uac10\uc0c1 \uc800\uc7a5\uc2dc \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad |\\n| BufferedImage(AWT) | \uc774\ubbf8\uc9c0 \ub370\uc774\ud130\ub97c \ucc98\ub9ac\ud558\uace0 \uc870\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9 | \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c\uac00 (0, 0) |\\n| Graphics2D(AWT) | \uc120 \uadf8\ub9ac\uae30, \uc0c9\uc0c1 \uad00\ub9ac \ub4f1\uc744 \uc9c0\uc6d0\ud558\ub294 \ud074\ub798\uc2a4 \uc2e4\uc81c \ud574\ub2f9 \ud074\ub798\uc2a4\uc758 draw \uba54\uc11c\ub4dc\ub97c \uacbd\ub85c\ub97c \uadf8\ub9bc | JDK 1.2 \uc774\ud6c4\uc5d0 \ucd94\uac00\ub428, 2D(\ud3c9\uba74) \uadf8\ub798\ud53d \ud658\uacbd\uc744 \uc9c0\uc6d0, bufferedImage.createGraphics \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \uc0dd\uc131 |\\n\\n### \uc758\uc874\uad00\uacc4\\n\\n```mermaid\\ngraph TD\\n C1[Coordinates] --\x3e C[Coordinate]\\n P1[Positions] --\x3e P[Position]\\n\\n\\tRID[RouteImageDrawer] -- \\"\uc911\uc559 \uc815\ub82c\ub41c Positions\ub97c \ubc1b\uc544 \uc774\ubbf8\uc9c0 \uc0dd\uc131\\" --\x3e P1\\n\\tRID --\x3e B[BufferedImage]\\n\\tRID --\x3e G[Graphics2D]\\n\\n\\tC1 -- \\"calculatePositions \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc704\uce58 \uacc4\uc0b0\\" --\x3e P1\\n\\n\\tRIU[RouteImageUploader] --\x3e B\\n\\tRIG[RouteImageGenerator] --\x3e RID\\n\\tRIG --\x3e RIU\\n\\tRIG --\x3e C1\\n\\tRIG --\x3e P1\\n```\\n\\n### Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)\\n\\n`List` 2\uac1c(\uc704\ub3c4, \uacbd\ub3c4)\uc778 \ud615\ud0dc\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uc5c8\uc9c0\ub9cc, \uc704\uce58 \uc810\uc744 \uc5ec\ub7ec\uac1c \ucc0d\ub294 \ubd80\ubd84\uc5d0\uc11c \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud574 \uc9c8 \uac83 \uac19\uc544\uc11c Coordinate(x, y)\uc640 \uc77c\uae09 \uceec\ub809\uc158\uc778 Coordinates\ub85c \uad00\ub9ac\ud558\uae30\ub85c \ud588\ub2e4. \\nCoordinates \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub450 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- calculatePositions: \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub97c \ubc1b\uc544 \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \uc0ac\uc6a9\ub420 Positions\ub97c \ubc18\ud658\\n- indexOf: \ub2e4\ub978 Coordinates\ub97c \ubc1b\uc544 \ub3d9\uc77c\ud55c \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4\ub97c \ubc18\ud658\ud558\ub294 \\n\\nPositions \uacc4\uc0b0 \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\uc704\ub3c4, \uacbd\ub3c4 \uac01\uac01\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \ud544\uc694\ud55c \uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4.\\n\\n```java title=\\"Coordinates.java\\"\\n// \ud638\ucd9c\\n// List xPositions = toPositions(xValues, maxDifference, routeImageSize);\\n// List yPositions = toPositions(yValues, maxDifference, routeImageSize);\\n\\nprivate List toPositions(List values, Double maxDifference, Integer routeImageSize) {\\n Double minValue = Collections.min(values);\\n return values.stream()\\n .map(value -> normalizeCoordinate(value, maxDifference, minValue))\\n .map(value -> mapToPosition(value, routeImageSize))\\n .toList();\\n}\\n\\nprivate double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {\\n return (coordinate - minValue) / maxDifference;\\n}\\n\\nprivate int mapToPosition(Double coordinate, Integer routeImageSize) {\\n return (int) (coordinate * routeImageSize);\\n}\\n```\\n\\n\uc704\ub3c4\ub85c \uc608\uc2dc\ub4e0 \ub0b4\uc6a9\uc774\ub2e4.\\n\\n1. Collections.min(values) \u2192 \uc704\ub3c4 \ub9ac\uc2a4\ud2b8\uc758 \ucd5c\uc18c\uac12\uc744 \uad6c\ud55c\ub2e4.\\n2. normalizeCoordinate \u2192 \uac01\uac01\uc758 \uc704\ub3c4 \uac12\uc5d0\uc11c \ucd5c\uc18c\uac12\uc744 \ube7c\uace0 0 ~ 1 \uc0ac\uc774 \uac12\uc73c\ub85c \ubcc0\ud658 \ud6c4 **\uc704\uacbd\ub3c4\uc758 \ucd5c\ub300 \ucc28\uc774**\ub85c \ub098\ub208\ub2e4.\\n3. mapToPosition \u2192 \uadf8\ub798\ud504 \ud06c\uae30\ub97c \ubc1b\uc544 0 ~ 1 \uc0ac\uc774 \uac12\uc744 \uc2e4\uc81c \uc774\ubbf8\uc9c0\ub97c \uc704\ud55c \uc704\uce58\uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4.\\n\\n### Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)\\n\\nPositions \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub2e4\uc12f \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- align: \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\uc640 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\ub97c \ubc1b\uc544 Position \uac12\ub4e4\uc744 \uc911\uc559 \uc815\ub82c\ud55c\ub2e4.\\n- getPositionsByIndexes: \uc778\ub371\uc2a4 \ub9ac\uc2a4\ud2b8\ub97c \ubc1b\uc544 \uc785\ub825\ubc1b\uc740 \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n- size: \ud06c\uae30\ub97c \ubc18\ud658\ud55c\ub2e4.\\n- xPositions: x \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n- yPositions: y \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n\uc911\uc559 \uc815\ub82c \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```java title=\\"Positions.java\\"\\npublic Positions align(int imageSize, int routeSize) {\\n int xOffset = calculateOffset(Position::x, imageSize);\\n int yOffset = calculateOffset(Position::y, imageSize);\\n\\n return items.stream()\\n .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))\\n .collect(collectingAndThen(toList(), Positions::new));\\n}\\n\\nprivate int calculateOffset(ToIntFunction positionToInteger, int imageSize) {\\n List positions = items.stream()\\n .mapToInt(positionToInteger)\\n .boxed()\\n .toList();\\n\\n int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;\\n return imageSize / 2 - midValue;\\n}\\n```\\n\\n\uc0c1\ud558\uc88c\uc6b0 \uc5ec\ubc31\uc744 \ub3d9\uc77c\ud558\uac8c \uc8fc\uae30 \uc704\ud574\uc11c offset \uac12\uc744 \uad6c\ud574\uc11c x, y \uac12\uc5d0 \uac01\uac01 \ub354\ud558\ub294 \ud615\ud0dc\ub85c \uc911\uc559 \uc815\ub82c\uc744 \uc218\ud589\ud588\ub2e4. \\nBufferedImage\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c (0, 0) \uae30\uc900\uc73c\ub85c \uc544\ub798\ub85c \ub0b4\ub824\uac08\uc218\ub85d y \uac12\uc774 \ucee4\uc9c0\uace0, \uc624\ub978\ucabd\uc73c\ub85c \uac08 \uc218\ub85d x \uac12\uc774 \ucee4\uc9c4\ub2e4. \\n\\n![./800.png](./800.png)\\n\\n\ub530\ub77c\uc11c \ucd5c\uc885\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c \uac12\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud588\ub2e4.\\n\\nx \uac12 \u2192 \uacc4\uc0b0\ud55c offset \uadf8\ub300\ub85c \ub354\ud55c\ub2e4. \\ny \uac12 \u2192 imageSize(800)\uc5d0\uc11c y + offset \uac12\uc744 \ube80\ub2e4. \\n\\n### RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)\\n\\nBufferedImage, Graphics2D\ub97c \ud544\ub4dc\ub85c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub2e4. \\n\uadf8\ub9bc\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \uc124\uc815\ud55c \uc0c1\uc218\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4.\\n\\n```java title=\\"RouteImageDrawer.java\\"\\n// RGB\uc5d0 \uac01\uac01 8\ube44\ud2b8\uc529 \ud560\ub2f9\ud55c \uac12\uc744 24\ube44\ud2b8 \ud2b8\ub8e8\uceec\ub7ec\ub77c \ubd80\ub978\ub2e4.\\n// \ud574\ub2f9 \uc124\uc815\uc740 24\ube44\ud2b8 + 8\ube44\ud2b8(alpha, \ud22c\uba85\ub3c4)\ub97c \ucd94\uac00\ud55c 32\ube44\ud2b8 \uc774\ubbf8\uc9c0 \ud0c0\uc785\uc774\ub2e4.\\n// \uc774\ub97c RGBA\ub77c\uace0 \ubd80\ub978\ub2e4.\\nprivate static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;\\n// \ubc30\uacbd \ud22c\uba85\uc0c9\\nprivate static final Color TRANSPARENT = new Color(0, 0, 0, 0);\\n// \uacbd\ub85c\ub97c \uc704\ud55c STROKE\\nprivate static final int LINE_STROKE_WIDTH = 7;\\nprivate static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\\n// \uc704\uce58 \uc810\uc744 \uc704\ud55c STROKE\\nprivate static final int POINT_STROKE_WIDTH = 20;\\nprivate static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\\n// \uc548\ud2f0\uc568\ub9ac\uc5b4\uc2f1 \ub4f1 \ud654\uc9c8 \uac1c\uc120\uc744 \uc704\ud55c \uc124\uc815\\nprivate static final Map renderingHints = Map.of(\\n RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,\\n RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,\\n RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC\\n);\\n```\\n\\nRouteImageDrawer \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \uc138 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- drawLine: \uc120\uc744 \uadf8\ub9b0\ub2e4.\\n- drawPoint: \uc810\uc744 \ucc0d\ub294\ub2e4.\\n- dispose: \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud55c\ub2e4. \\n\\ndispose\uc758 \uacbd\uc6b0 \ub0b4\ubd80\uc5d0\uc11c \uc0dd\uc131\ub41c graphics2D\uc5d0 \ub300\ud55c \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud558\ub294 \uba54\uc11c\ub4dc\uc778 graphics2D.dispose\ub97c \ud638\ucd9c\ud55c\ub2e4.\\n\\n## \uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow\\n\\n### 1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44\\n\\n```mermaid\\nsequenceDiagram\\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\\n\\n```\\n\\n### 2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\\n```\\n\\n### 3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\\n\\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n```\\n\\n### 4. \uc5c5\ub85c\ub4dc \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n \\tRouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\\n \\tRouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n \\tRouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n```\\n\\n### \uc804\uccb4 Flow\\n\\n```mermaid\\nsequenceDiagram\\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\\n\\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\\n RouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n RouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n\\t\\n```"},{"id":"route-image-async-with-event","metadata":{"permalink":"/route-image-async-with-event","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx","source":"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","description":"\uc774\uc804 \uae00","date":"2023-08-13T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 13\uc77c","tags":[{"label":"async","permalink":"/tags/async"},{"label":"event","permalink":"/tags/event"}],"readingTime":11.2,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","slug":"route-image-async-with-event","tags":["async","event"]},"unlisted":false,"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","permalink":"/route-image-implementation"},"nextItem":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","permalink":"/cloudwatch"}},"content":"## \uc774\uc804 \uae00\\n\\n[\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd](./route-image-intro) \\n[\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604](./route-image-implementation)\\n\\n## \uac1c\uc694\\n\\n\ud604\uc7ac \uc5ec\ud589\uc744 \ub9c8\uce58\ub294 \uacbd\uc6b0, \uac10\uc0c1\uc744 \uc0dd\uc131\ud558\ub294 \uacbd\uc6b0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \uc704\uce58 \uc815\ubcf4\uc758 \uac1c\uc218\uc5d0 \uc815\ube44\ub840\ud558\uc5ec \uc0dd\uc131 \uc2dc\uac04\uc774 \uc99d\uac00\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ube44\ub3d9\uae30\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uc5ec \uc0ac\uc6a9\uc790\uc758 \uacbd\ud5d8\uc744 \uac1c\uc120\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n### \uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120\\n\\n\uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc774 \uc8fc\uae30\ub2a5\uc774\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ubd80\uae30\ub2a5\uc774\ub2e4. \\n\ud558\uc9c0\ub9cc \ud604\uc7ac \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc758 \uc751\ub2f5 \uc18d\ub3c4\uac00 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uace0 \uc788\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uc5ec\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4. \\n\uc18c\uc694 \uc2dc\uac04\uc774 1\ucd08 \uc774\uc0c1 \uac78\ub9ac\ub294 \uacbd\uc6b0\uac00 \uc874\uc7ac\ud558\uae30\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uace0 \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131 \uae30\ub2a5\uc758 \uc751\ub2f5 \uc2dc\uac04\uc744 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc911\uc694\ud558\ub2e4. \\n\\n### \ud655\uc7a5\uc131 \ub300\ube44\\n\\n\ud604\uc7ac 10\ubd84 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc11c\ubc84\uc5d0 \uc800\uc7a5\ud558\uace0 \uc788\ub2e4. \\n\uc870\uae08 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uadf8\ub9ac\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 \uc5ec\ud589\uc5d0 \ub9ce\uc740 \uc704\uce58 \uc815\ubcf4\uac00 \uc800\uc7a5\ub420 \uc218\ubc16\uc5d0 \uc5c6\uace0 \ub530\ub77c\uc11c \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uac78\ub9ac\ub294 \uc2dc\uac04\uc774 \ub354 \uae38\uc5b4\uc9c8 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ucd94\ud6c4\uc5d0 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0\ub97c \ub300\ube44\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \ud569\ub2f9\ud558\ub2e4. \\n\\n## \ube44\ub3d9\uae30 \ucc98\ub9ac\\n\\n@Async\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uba54\uc11c\ub4dc\ub97c \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \\n\\n### \ube44\ub3d9\uae30 \uc124\uc815\\n\\n\uc0ac\uc6a9\ud558\uae30 \uc804\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c EnableAsync \uc124\uc815\uc744 \ud574\uc57c\ud55c\ub2e4. \\n\ud574\ub2f9 \uc124\uc815\uc744 \uc801\uc6a9\ud558\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc\uc5d0 @Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uae30\ub9cc \ud558\uba74 \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud55c\ub2e4. \\n\\n```java title=\\"AsyncConfig\\"\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig {\\n}\\n```\\n\\n\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud560 \ub54c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ub808\ub4dc \ud480 \uc124\uc815\uc744 \ub530\ub85c \ud574\uc918\uc57c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ThreadPoolTaskExecutor\ub97c \ub530\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \uae30\ubcf8\uc801\uc73c\ub85c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uac00 \uc0dd\uc131\uc744 \ub3c4\uc640\uc900\ub2e4. \\n\\n> In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.\\n> 7.7. Task Execution and Scheduling, Spring Boot Docs\\n\\n### @Async \uc801\uc6a9\\n\\n\uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\uc5d0 Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud55c\ub2e4. \\n\\n```java title=\\"RouteImageGenerator\\"\\n@Async\\npublic void generate(\\n List latitudes,\\n List longitudes,\\n List pointedLatitudes,\\n List pointedLongitudes,\\n Long tripId\\n) {\\n // \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);\\n Coordinates coordinates = Coordinates.of(latitudes, longitudes);\\n Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);\\n drawImage(coordinates, routeImageDrawer, pointedCoordinates);\\n\\n // \uc774\ubbf8\uc9c0 \uc800\uc7a5\\n String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());\\n\\n // \uc790\uc6d0 \ud560\ub2f9 \ud574\uc81c\\n routeImageDrawer.dispose();\\n\\n // \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac12 \ubcc0\uacbd\\n Trip trip = tripRepository.findById(tripId)\\n .orElseThrow();\\n trip.changeRouteImageUrl(imageUrl);\\n tripRepository.save(trip);\\n}\\n```\\n\\n### \ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810\\n\\n\ud604\uc7ac \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uace0 \uc800\uc7a5 \ud6c4, \uc800\uc7a5 \uacbd\ub85c\ub97c DB\uc5d0 \ubc18\uc601\ud574\uc57c \ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ud615\ud0dc\uac00 \ub418\uba70 \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4. \\n\\n```mermaid\\ngraph LR\\n trip[trip: \uc5ec\ud589 \uad00\ub828 \ud328\ud0a4\uc9c0] --\x3e draw[draw: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294 \ud328\ud0a4\uc9c0]\\n draw --\x3e trip\\n```\\n\\n\uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uacfc \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph draw\\n\\t\\tdirection LR\\n\\t\\tRG[RouteImageGenerator] -- DB \ubc18\uc601 \uc694\uccad --\x3e ILR[ImageLinkTripRepository]\\n\\tend\\n subgraph trip\\n\\t\\tdirection LR\\n\\t\\tTS[TripService] -- \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e RG\\n\\t\\tILRI[ImageLinkTripRepositoryImpl] -- \uad6c\ud604 --\x3e ILR\\n\\tend\\n\\n\\ttrip --\x3e draw\\n```\\n\\n\ud328\ud0a4\uc9c0 \uac04 \uc758\uc874\uc131\uc740 \ud574\uacb0\ub418\uc5c8\uc9c0\ub9cc, \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5\uc744 \uc704\ud574 tripId\ub97c \ubc1b\uc544\uc57c\ud558\ub294 \ub4f1\uc758 \ub17c\ub9ac\uc801\uc778 \uc758\uc874\uc131\uc740 \uc544\uc9c1 \ud574\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4. \\n\ub530\ub77c\uc11c \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\n\\n## \uc774\ubca4\ud2b8 \uc0ac\uc6a9\\n\\n\uc2a4\ud504\ub9c1\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uba74 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ube44\uad00\uc2ec\uc0ac(ex. \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131)\uc744 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4.\\n\\n### \uc774\ubca4\ud2b8 \ubc1c\ud589\\n\\n\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud574\uc57c \ud55c\ub2e4. \\n\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 ApplicationEventPublisher \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \uc218 \uc788\ub2e4. \\n\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c ApplicationContext\uac00 \uad6c\ud604\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud55c\ub2e4. \\n\\n```java title=\\"TripService & TripUpdateEvent\\"\\npublic void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {\\n ...\\n\\n // \uc774\ubca4\ud2b8 \ubc1c\ud589\\n applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));\\n}\\n\\npublic record TripUpdateEvent(Long tripId) {\\n}\\n```\\n\\n\uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \ub54c \ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc774 \uc911\uc694\ud558\ub2e4. \\n\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\ub294 \ub3c4\uba54\uc778\uc758 \ud589\uc704\ub97c \ub2f4\uace0 \uc788\ub294 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589(ex. RouteImageGenerateEvent)\ud55c\ub2e4\uba74 \ub17c\ub9ac\uc801\uc778 \uc758\uc874 \uad00\uacc4\uac00 \ub0a8\uc544\uc788\uae30\uc5d0 \uc774\ubca4\ud2b8\ub97c \uc801\uc808\ud788 \uc0ac\uc6a9\ud588\ub2e4\uace0 \ubcf4\uae30 \uc5b4\ub835\ub2e4. \\n\ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc740 \uc8fc\uae30\ub2a5\uc774 \uc5b4\ub5a4 \ud589\uc704(ex. TripUpdateEvent)\ub97c \ud588\ub294\uc9c0\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 \uc774\ubca4\ud2b8\uba85\uc73c\ub85c \ubc1c\ud589\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4. \\n\\n### \uc774\ubca4\ud2b8 \uad6c\ub3c5\\n\\n\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc2e4\ud589\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\uae30 \uc704\ud558\uc5ec `@Async` \uc560\ub108\ud14c\uc774\uc158\uc744 \uc801\uc6a9\ud588\ub2e4. \\n\uc774\ubca4\ud2b8\uc758 \uad6c\ub3c5\uc740 \uc5ec\ud589\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc\ub420 \ub54c \uc5ec\ud589\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 `@TransactionalEventListener`\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\\n:::note TransactionPhase \uc124\uc815\\nTransactionPhase\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \uc774\ubca4\ud2b8\ub97c \uc5b4\ub5a4 \ub2e8\uacc4\uc5d0\uc11c \uc218\uc2e0\ud558\uace0 \ucc98\ub9ac\ud560\uc9c0\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n\\nAFTER_COMMIT(\uae30\ubcf8\uac12): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ucee4\ubc0b \ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nAFTER_ROLLBACK: \ud2b8\ub79c\uc7ad\uc158\uc774 \ub864\ubc31\ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nAFTER_COMPLETION: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub610\ub294 \ub864\ubc31 \ub418\uc5c8\uc744 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nBEFORE_COMMIT: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub418\uae30 \uc804 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\n:::\\n\\n\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uae30 \uc704\ud574 @Transactional \uc560\ub108\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\\n```java title=\\"TripUpdateEventHandler\\"\\n@Component\\npublic class TripUpdateEventHandler {\\n\\n private final RouteImageGenerator routeImageGenerator;\\n private final TripRepository tripRepository;\\n\\n public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {\\n this.routeImageGenerator = routeImageGenerator;\\n this.tripRepository = tripRepository;\\n }\\n\\n @Async\\n @TransactionalEventListener(phase = AFTER_COMMIT)\\n public void handle(TripUpdateEvent tripUpdateEvent) {\\n Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());\\n\\n String imageUrl = routeImageGenerator.generate(\\n trip.getLatitudes(),\\n trip.getLongitudes(),\\n trip.getPointedLatitudes(),\\n trip.getPointedLongitudes()\\n );\\n\\n trip.changeRouteImageUrl(imageUrl);\\n tripRepository.save(trip);\\n }\\n}\\n```\\n\\n\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c\uc368 \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ubb38\uc81c\uac00 \ub2e4\uc74c\uacfc \uac19\uc774 \ud574\uacb0\ub418\uc5c8\ub2e4. \\n\ub610\ud55c \uc8fc\uae30\ub2a5\uacfc \ubd80\uae30\ub2a5\uc744 \ubd84\ub9ac\ud568\uc73c\ub85c\uc368 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uc5c8\ub2e4.\\n\\n```mermaid\\ngraph LR\\n subgraph trip\\n TripServcie -- \ubc1c\ud589 --\x3e TripUpdateEvent\\n TripRepository\\n end\\n\\n subgraph draw\\n TripUpdateEventHandler -- \uad6c\ub3c5 \ud6c4 \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e TripUpdateEvent\\n TripUpdateEventHandler -- \uc0dd\uc131\ub41c \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5 --\x3e TripRepository\\n end\\n```\\n\\n### \ud14c\uc2a4\ud2b8\\n\\n\ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```java\\n@SpringBootTest\\npublic class TripUpdateEventHandlerIntegrationTest {\\n\\n ...\\n\\n @Test\\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\\n // given\\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\\n .willReturn(\uc5ec\ud589());\\n\\n // when\\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\\n\\n // then\\n then(routeImageGenerator)\\n .should(Mockito.timeout(5000).times(1))\\n .generate(any(), any(), any(), any());\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\n@ContextConfiguration(classes = TestSyncConfig.class)\\n@SpringBootTest\\npublic class TripUpdateEventHandlerIntegrationTest {\\n\\n ...\\n\\n @Test\\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\\n // given\\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\\n .willReturn(\uc5ec\ud589());\\n\\n // when\\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\\n\\n // then\\n then(routeImageGenerator)\\n .should(times(1))\\n .generate(any(), any(), any(), any());\\n }\\n}\\n```\\n\\n\\n\\n\\n\ucc98\uc74c\uc5d0\ub294 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub9cc \ub3d9\uae30\ub85c \uc124\uc815 \ud6c4 \uac80\uc99d\ud558\ub824\uace0 \ud588\ub2e4. \\n\ud1b5\ud569 \ud14c\uc2a4\ud2b8\uc5d0\uc120 `\ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1 \uc885\ub8cc\ub418\uc5c8\uc744 \ub54c \ube44\ub3d9\uae30\ub85c \uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0` \uac80\uc99d\uc774 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc885\uc801\uc73c\ub85c `Mockito.timeout` \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \ud1b5\uacfc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4. \\n\\n## \uacb0\uacfc\\n\\n![./time.png](./time.png)\\n\\n\uc704 \uc751\ub2f5 \uc2dc\uac04\uc740 \uc704\uce58 \uc815\ubcf4 1000\uac1c\ub97c \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud55c \uac12\uc774\ub2e4. \\n\uc751\ub2f5 \uc2dc\uac04\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ud3ec\ud568\ub418\uc9c0 \uc54a\uc544\uc11c \uc131\ub2a5\uc774 \uac1c\uc120\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4. \\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[7.7. Task Execution and Scheduling, Spring Boot Docs](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.task-execution-and-scheduling) \\n[Spring Events, Baeldung](https://www.baeldung.com/spring-events) \\n[\ud68c\uc6d0\uc2dc\uc2a4\ud15c \uc774\ubca4\ud2b8\uae30\ubc18 \uc544\ud0a4\ud14d\ucc98 \uad6c\ucd95\ud558\uae30](https://techblog.woowahan.com/7835/)"},{"id":"cloudwatch","metadata":{"permalink":"/cloudwatch","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md","source":"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md","title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","description":"CloudWatch","date":"2023-08-17T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 17\uc77c","tags":[{"label":"cloudwatch","permalink":"/tags/cloudwatch"},{"label":"log","permalink":"/tags/log"},{"label":"monitoring","permalink":"/tags/monitoring"}],"readingTime":5.35,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","slug":"cloudwatch","tags":["cloudwatch","log","monitoring"]},"unlisted":false,"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","permalink":"/route-image-async-with-event"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"}},"content":"## CloudWatch\\n\\nAWS \ub9ac\uc18c\uc2a4\uc640 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc9c0\ud45c\uc640 \ub85c\uadf8\uc5d0 \ub300\ud55c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc81c\uacf5\ud558\ub294 \uc11c\ube44\uc2a4\ub2e4. \\n\uc9c0\ud45c\ub97c \uac10\uc2dc\ud558\uc5ec \uc54c\ub9bc\uc744 \ubcf4\ub0b4\ub294 \uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4. \\n\ud504\ub9ac\ud2f0\uc5b4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \ub300\uc2dc\ubcf4\ub4dc\ub2f9 3$/M \uc758 \ube44\uc6a9\uc774 \uccad\uad6c\ub418\uace0, \uc9c0\ud45c\ub098 \ub85c\uadf8\uc758 \uc591\uc5d0 \ub530\ub77c \ube44\uc6a9\uc774 \ucd94\uac00\uc801\uc73c\ub85c \uccad\uad6c\ub41c\ub2e4. \\n\uc694\uae08 \uc815\ubcf4\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \uc815\ubcf4\ub294 [\ub2e4\uc74c \ub9c1\ud06c](https://aws.amazon.com/ko/cloudwatch/pricing/)\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n## CloudWatch Metrics\\n\\n\uae30\ubcf8\uc801\uc73c\ub85c 5\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc218\uc9d1\ub41c\ub2e4. \\n\uc138\ubd80 \ubaa8\ub2c8\ud130\ub9c1(Detailed Monitoring)\uc744 \ud65c\uc131\ud654\ud558\uba74 1\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\ub97c \uc218\uc9d1\ud55c\ub2e4. \\n\ub300\uc2dc\ubcf4\ub4dc\uc5d0\uc11c InstanceId\ub85c \uac80\uc0c9\ud558\uc5ec \uc218\uc9d1\ub41c \uc9c0\ud45c\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.\\n\\n![./cloudwatch1.png](./cloudwatch1.png)\\n\\nCPUUtilization, NetworkIn, NetworkOut\uacfc \uac19\uc740 \uae30\ubcf8\uc801\uc778 \uc9c0\ud45c\ub97c \uc81c\uacf5\ud558\uace0, \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud06c \uacf5\uac04\uacfc \uac19\uc740 \uc9c0\ud45c\ub97c \ud655\uc778\ud558\ub824\uba74 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\ub97c \uc124\uc815\ud574\uc57c \ud55c\ub2e4.\\n\\n## CloudWatch Agent \uc124\uce58\\n\\nCloudWatch Agent \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\uc640 \ub85c\uadf8\ub97c \uc218\uc9d1\ud560 \uc218 \uc788\ub2e4. \\n\\n### IAM \uc5ed\ud560 \uc124\uc815\\n\\n\uae30\ubcf8\uc801\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4\uac00 CloudWatchAgentServerPolicy\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4. \\nIAM \u2192 \uc5ed\ud560\uc5d0\uc11c \uc5ed\ud560 \uc0dd\uc131\uc744 \ud074\ub9ad\ud55c\ub2e4.\\n\\n![./cloudwatch2.png](./cloudwatch2.png)\\n\\nCloudWatchAgentServerPolicy \uad8c\ud55c \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uace0, \uc801\ub2f9\ud55c \uc5ed\ud560 \uc774\ub984\uc744 \uc785\ub825\ud574\uc11c \uc5ed\ud560\uc744 \uc0dd\uc131\ud55c\ub2e4.\\n\\n![./cloudwatch3.png](./cloudwatch3.png)\\n\\nEC2 \uc778\uc2a4\ud134\uc2a4 \ubaa9\ub85d\uc73c\ub85c \ub4e4\uc5b4\uac00\uc11c, CloudWatch Agent\ub97c \uc124\uce58\ud560 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud074\ub9ad\ud55c\ub2e4. \\n\uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc5d0\uc11c \uc774\uc804\uc5d0 \uc0dd\uc131\ud55c \uc5ed\ud560\uc744 \uc9c0\uc815\ud55c\ub2e4.\\n\\n![./cloudwatch4.png](./cloudwatch4.png)\\n\\n### \uc124\uce58\\n\\n\ud658\uacbd\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\nOS: ubuntu 22.04 \\n\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small (ARM64) \\n\\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uce58\ud55c\ub2e4.\\n\\n```bash\\nwget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb\\nsudo dpkg -i -E ./amazon-cloudwatch-agent.deb\\n```\\n\\n[\uc0ac\uc6a9 \uc124\uba85\uc11c](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html)\uc5d0 \uac01 \uc778\uc2a4\ud134\uc2a4 \uc720\ud615\ub9c8\ub2e4 \ub2e4\uc6b4\ub85c\ub4dc \ub9c1\ud06c\uac00 \uc790\uc138\ud558\uac8c \uc548\ub0b4\ub418\uc5b4 \uc788\ub2e4.\\n\\n### Wizard\\n\\nCloudWatch Wizard\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uc124\uc815 \ud30c\uc77c \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4. \\n\ub85c\uadf8\ub97c \uc218\uc9d1\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub294 \uacbd\uc6b0 Wizard \uc2e4\ud589 \uba85\ub839\uc5b4 \uc785\ub825 \uc804 log \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \ubcf5\uc0ac\ud574\ub450\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec Wizard\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nsudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard\\n```\\n\\n\uc124\uc815\uc744 \uc9c4\ud589\ud558\ub2e4 \ubcf4\uba74 \uc124\uc815 \ud30c\uc77c\uc774 \uc5b4\ub5bb\uac8c \uad6c\uc131\ub420\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\ub85c\uadf8\ub97c \ucd94\uac00\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \uc785\ub825\ucc3d\uc774 \ub098\uc624\uba74 \uc900\ube44\ud574\ub480\ub358 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \uc785\ub825\ud55c\ub2e4. \\n\\n![./cloudwatch5.png](./cloudwatch5.png)\\n\\n\uc911\uac04\uc5d0 SSM parameter store\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4. \\n\\n```bash\\nDo you want to store the config in the SSM parameter store?\\n1. yes\\n2. no\\n```\\n\\n\ucd94\uac00\uc801\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 2\ubc88\uc744 \uc120\ud0dd\ud55c\ub2e4. \\nParameter Store \uad00\ub9ac\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc758 [\ubb38\uc11c](https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/)\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac70 \uac19\ub2e4. \\n\uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 `/opt/aws/amazon-cloudwatch-agent/bin/config.json` \uc5d0 \uc124\uc815\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774 \uc800\uc7a5\ub41c\ub2e4. \\n\\n### \uc124\uc815 \ud30c\uc77c \uc801\uc6a9\\n\\n\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uc815\ud30c\uc77c\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4. \\nfile \ub4a4\uc5d0\ub294 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \uc808\ub300\uacbd\ub85c(\uc544\ub798 \uba85\ub839\uc5b4 \uae30\uc900 \uae30\ubcf8 \uc0dd\uc131 \uc704\uce58)\ub97c \uc785\ub825\ud558\uba74 \ub41c\ub2e4. \\n\\n```bash\\nsudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json\\n```\\n\\n### types.db: no such file or directory \uc5d0\ub7ec\\n\\n\ub2e4\uc74c\uacfc \uac19\uc740 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 types.db \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4.\\n\\n```bash\\nError running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory\\n```\\n\\ntypes.db \ud30c\uc77c \uc0dd\uc131\\n\\n```bash\\nsudo mkdir /usr/share/collectd\\nsudo touch /usr/share/collectd/types.db\\n```\\n\\n### \uc9c0\ud45c \ud655\uc778\\n\\nCloudWatch Metrics\uc5d0 \uac00\ubcf4\uba74 CWAgent\ub77c\ub294 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uac00 \ucd94\uac00\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4. \\n\\n![./cloudwatch6.png](./cloudwatch6.png)\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ucd94\uac00\ud558\uc5ec \uc9c0\ud45c\uc5d0 \ub300\ud55c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. \\n\\n```json\\n{\\n \\"metrics\\": {\\n \\"namespace\\": \\"2023-hello-world\\",\\n ......\\n },\\n} \\n```\\n\\n### \ub85c\uadf8\\n\\nCloudWatch \u2192 \ub85c\uadf8 \uadf8\ub8f9\uc73c\ub85c \uac00\uba74 Wizard\ub85c \ucd94\uac00\ud55c \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.\\n\\n![./cloudwatch7.png](./cloudwatch7.png)\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[CloudWatch\ub780 \ubb34\uc5c7\uc785\ub2c8\uae4c?](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) \\n[Amazon CloudWatch \uc694\uae08](https://aws.amazon.com/ko/cloudwatch/pricing/) \\n[Linux \uc778\uc2a4\ud134\uc2a4 \uc9c0\ud45c](https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) \\n[\uc11c\ubc84\uc5d0 CloudWatch \uc5d0\uc774\uc804\ud2b8 \uc124\uce58 \ubc0f \uc2e4\ud589](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html) \\n[CloudWatch Agent\ub97c Parameter Store\uc5d0\uc11c \uad00\ub9ac\ud574 \ubcf4\uae30](https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/) \\n[CloudWatch\uc5d0\uc774\uc804\ud2b8 \uad6c\uc131 \ud30c\uc77c](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html)"},{"id":"woowacourse-level3-retrospective","metadata":{"permalink":"/woowacourse-level3-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx","source":"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","description":"\ud68c\uace0","date":"2023-08-19T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 19\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.945,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","slug":"woowacourse-level3-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","permalink":"/cloudwatch"},"nextItem":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"}},"content":"import logo from \'./logo.png\';\\n\\n### \ud68c\uace0\\n\\n\uc9c0\ub09c 8\uc8fc\ub294 \ub808\ubca8 1, 2 \ub54c\ubcf4\ub2e4 5\ubc30 \uc815\ub3c4 \ube60\ub974\uac8c \uc9c0\ub098\uac04 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub808\ubca8 3\uc5d0\ub294 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4, \uae30\uc220 \uc678\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4 \ubd80\uc871\ud568\uc774 \ub9ce\uc774 \ubcf4\uc600\ub358 \uac83 \uac19\ub2e4. \\n\ubd80\uc871\ud55c \ubd80\ubd84\uc744 \uc54c\uc558\uae30\uc5d0, \uc55e\uc73c\ub85c \ub354\uc6b1 \uc131\uc7a5\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ub0b4\uac00 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \ud300\uc6d0\ub4e4\uc774 \uc798 \ubcf4\ucda9\ud574 \uc918\uc11c \ub4e0\ub4e0\ud588\ub2e4. \\n\\n### \uc544\uc26c\uc6b4 \uc810\\n\\n**\ubb38\uc11c\ud654**\\n\\n\uac1c\uc778\uc801\uc73c\ub85c\ub294 \uae30\uc220 \uc678\uc801\uc73c\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ub0b4\uac00 \ud55c \ubd80\ubd84\uc744 \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c, \uc774\ud574\ud558\uae30 \uc27d\uac8c \ubb38\uc11c\ud654\ub97c \ud588\ub354\ub77c\uba74 \ud300\uc6d0\ub4e4\uc5d0\uac8c \ub354\uc6b1 \ub3c4\uc6c0\uc774 \ub418\uc5c8\uc744 \ud150\ub370 \uc774 \ubd80\ubd84\uc5d0 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ud22c\uc790\ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc5d0\uc11c \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\ubc29\ud559 \uae30\uac04 \ub3d9\uc548 \ubb38\uc11c\ud654\ub97c \ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc778 \ube14\ub85c\uadf8 \uc62c\ub9ac\uba74\uc11c \uc870\uae08 \ub354 \ucc44\uc6cc\ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n**\ub0b4\uac00 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc774\uc790**\\n\\n\uc798 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc5ec\uc11c\ub77c\ub3c4 \uc911\uac04\uc740 \uac00\ub3c4\ub85d \ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub9d0\uc744 \ud558\uae30 \uc804\uc5d0 \uc815\ub9ac\ud574\uc11c \uc758\uacac\uc744 \ub0b4\ub294 \uac83, \ubc1c\ud45c \uc900\ube44, \uac10\uc815 \uc870\uc808 \ub4f1\ub4f1\\n\ubabb\ud558\ub294 \ubd80\ubd84\uc744 \uc778\uc9c0\ud558\uace0, \uac1c\uc120\ud558\uc790. \\n\\n**\ucef4\ud3ec\ud2b8 \uc874 \ubc97\uc5b4\ub098\uae30**\\n\\n\uc870\uae08 \ub354 \ub3c4\uc804\uc801\uc73c\ub85c \ubaa9\ud45c\ub97c \uc7a1\uc558\uc73c\uba74 \uc88b\uc558\uc744 \uac83 \uac19\ub2e4. \\n\ub9e4\ubc88 \uadfc\uac70\ub97c \uac00\uc9c0\uace0 \uae30\uc220\uc744 \ub3c4\uc785\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub824\uace0 \ud558\ub294 \ubd80\ubd84\uc774 \ub2e4\uc18c \ubd80\uc871\ud588\ub2e4. \\n\\n### \uc88b\uc558\ub358 \uc810\\n\\n**\uc88b\uc558\ub358 \uc810\ub3c4 \ubb38\uc11c\ud654**\\n\\n[\ud300 \ube14\ub85c\uadf8](https://tripdraw.blog)\ub3c4 \uba3c\uc800 \ub3c4\uc785\ud558\uc790\uace0 \uc81c\uc548\ud558\uace0, \ub0b4\uac00 \ud588\ub358 \ubd80\ubd84\uc740 \ubb38\uc11c\ud654\ub97c \uaf64 \ub9ce\uc774 \ud574\uc11c \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubc31\uc5d4\ub4dc \ud06c\ub8e8 4\uba85\uc774\uc11c \uac19\uc774 \ud55c \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c\ub294 \uae30\ub2a5 \uad6c\ud604\ud55c\ub2e4\uace0 \ubb38\uc11c\ud654\uac00 \uc870\uae08 \ubbf8\ud761\ud574\uc11c \ubcf4\ucda9\uc744 \ud574\uc57c\uaca0\ub2e4. \\n\\n**\ub0b4\uac00 \ub514\uc790\uc778\ud55c \ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0**\\n\\n\\n\\n\ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. \\n\ud300\uc6d0\ub4e4\uc774 \ub300\ud45c \uc0c9\uc0c1(\ud30c\ub780\uc0c9)\uc744 \uc815\ud574\uc92c\uace0, \uc8fc\ub9d0 \ub3d9\uc548 \uc2e0\ub098\uac8c \ub85c\uace0 \ub514\uc790\uc778\uc744 \ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc544\ub798\uc758 D \ubd80\ubd84\uc740 \uc720\ud29c\ube0c \uac15\uc758 \ub4e4\uc73c\uba74\uc11c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\uc11c \ubfcc\ub4ef\ud558\ub2e4. \\n\\n**\uae30\uc220 \uc120\ud0dd\uc758 \uc774\uc720**\\n\\n\uae30\uc220\uc758 \ud559\uc2b5 \ube44\uc6a9, \ud604\uc7ac \uad6c\uc870\uc5d0 \uc801\ud569\ud55c\uc9c0, \uc2e4\uc81c \uac00\uc9c0\uace0 \uc788\ub294 \ub9ac\uc18c\uc2a4\ub97c \uace0\ub824\ud574\uc11c \uae30\uc220 \uc120\ud0dd\uc744 \ud558\uace0, \ub3c4\uc785\ud588\ub358 \ubd80\ubd84\uc774 \uc88b\uc558\ub2e4. \\n100% \uc88b\uc740 \uc120\ud0dd\uc77c \uc21c \uc5c6\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \uc120\ud0dd\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \uc874\uc7ac\ud55c\ub2e4\uba74 \ud655\ub960\uc744 \ub192\ud600\uc8fc\ub294 \uac83 \uac19\ub2e4. \\n\\n### \ub9c8\uce58\uba70\\n\\n\ud50c\ub808\uc774\uc2a4\ud1a0\uc5b4\uc5d0 \uc571\uc774 \uc62c\ub77c\uac00 \uc788\ub294 \uac70 \ub108\ubb34 \uc2e0\uae30\ud558\ub2e4. \\n\uc548\ub4dc\ub85c\uc774\ub4dc \ube0c\ub808\uba58 \uc74c\uc545\ub300(\uba67\ub3fc\uc9c0, \uc218\ub2ec, \ud551\uad6c), \uadf8\ub9ac\uace0 \ubc31\uc5d4\ub4dc \ud300\uc6d0\ub4e4(\uccb4\uc778\uc800, \ud6c4\ucd94, \ub9ac\uc624) \ub108\ubb34 \uace0\uc0dd\uc774 \ub9ce\uc558\ub2e4."},{"id":"db-replication","metadata":{"permalink":"/db-replication","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx","source":"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx","title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","description":"\ubcf5\uc81c(Replication)","date":"2023-08-22T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 22\uc77c","tags":[{"label":"mysql","permalink":"/tags/mysql"},{"label":"replication","permalink":"/tags/replication"}],"readingTime":21,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","slug":"db-replication","tags":["mysql","replication"]},"unlisted":false,"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"},"nextItem":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"}},"content":"## \ubcf5\uc81c(Replication)\\n\\n\ud55c \uc11c\ubc84\uc5d0\uc11c \ub2e4\ub978 \uc11c\ubc84\ub85c \ub370\uc774\ud130\ub97c \ub3d9\uae30\ud654\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4. \\n\uc6d0\ubcf8 \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Primary \ub610\ub294 Source \ub77c\uace0 \ubd80\ub974\uace0, \ubcf5\uc81c\ub41c \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Secondary \ub610\ub294 Replica \ub77c\uace0 \ubd80\ub978\ub2e4. \\n\\n### \ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720\\n\\n**1. \uc2a4\ucf00\uc77c \uc544\uc6c3**\\n\\n\uc0ac\uc6a9\uc790\uc758 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uac00\ud574\uc9c0\ub294 \ubd80\ud558\ub3c4 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc99d\uac00\ud55c\ub2e4. \\n\uc774\ub97c \ucc98\ub9ac\ud558\uae30 \uc704\ud574 \ubcf5\uc81c\ub97c \ud1b5\ud55c \uc2a4\ucf00\uc77c \uc544\uc6c3\uc744 \uc801\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucffc\ub9ac\ub4e4\uc744 \uac01\uac01\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c \ubd84\uc0b0 \uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\\n**2. \ub370\uc774\ud130 \ubc31\uc5c5**\\n\\n\uc2e4\uc81c \uc6b4\uc601\ub418\ub294 \uc11c\ube44\uc2a4\uac00 \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 DB\uc5d0\uc11c \ubc31\uc5c5\uc744 \uc9c4\ud589\ud558\ub294 \uacbd\uc6b0, \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc774 \uac00\uc9c0 \uc54a\ub3c4\ub85d \ubcf5\uc81c\ub97c \ud1b5\ud574 Replica \uc11c\ubc84\ub97c \uad6c\ucd95\ud558\uc5ec, Replica \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ub97c \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\uc73c\ub85c \uc601\ud5a5\uc744 \ucd5c\uc18c\ud654 \ud560 \uc218 \uc788\ub2e4. \\n\\n**3. \ub370\uc774\ud130 \ubd84\uc11d**\\n\\n\ubc31\uc5c5\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc7a1\ud558\uace0 \ubb34\uac70\uc6b4 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\uc758 \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4. \\n\ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc81c\ub97c \uc0ac\uc6a9\ud574 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \\n\\n**4. \ub370\uc774\ud130\uc758 \uc9c0\ub9ac\uc801 \ubd84\uc0b0**\\n\\n\ube60\ub978 \uc751\ub2f5\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc11c\ubc84\uc5d0 \uac00\uae5d\uac8c \uc11c\ubc84\ub97c \uad6c\uc131\ud558\uac70\ub098, \uace0\uac00\uc6a9\uc131(High Availability)\uc744 \uc704\ud574\uc11c\ub3c4 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c\\n\\nMySQL \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub85c\uadf8 \ud30c\uc77c\uc744 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub77c\uace0 \ud55c\ub2e4. \\n\ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ud1b5\ud574 \ub370\uc774\ud130 \ubcc0\uacbd, \ud14c\uc774\ube14 \uad6c\uc870 \ubcc0\uacbd, \uacc4\uc815\uc774\ub098 \uad8c\ud55c \ubcc0\uacbd\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc800\uc7a5\ub41c\ub2e4. \\nMySQL\uc758 \ubcf5\uc81c\ub294 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. \uc774\ub97c Replica \uc11c\ubc84\ub85c \uc804\ub2ec\ud558\uace0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph Replica\\n\\t\\tdirection TB\\n\\t\\tIO[Replication I/O thread] -- save --\x3e RL[Relay Log]\\n\\t\\tSQL[Replication SQL Thread] -- read --\x3e RL\\n\\tend\\n\\n\\tsubgraph Source\\n\\t\\tdirection TB\\n\\t\\tBLD[Binary Log Dump Thread] -- Send Binary Log Dump--\x3e IO\\n\\tend\\n\\n```\\n\\n:::note \uc2a4\ub808\ub4dc\ubcc4 \uc5ed\ud560\\n\\nBinary Log Dump Thread: \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc758 \ub0b4\uc6a9\uc744 Replica \uc11c\ubc84\ub85c \uc804\ub2ec \\nReplication I/O Thread: Binary \ub85c\uadf8 \uc774\ubca4\ud2b8\ub97c \uac00\uc838\uc640 \ub85c\uceec \uc11c\ubc84\uc758 \ud30c\uc77c(Relay Log)\ub85c \uc800\uc7a5 \\nReplication SQL Thread: \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc774\ubca4\ud2b8\ub97c \uc77d\uace0 \uc2e4\ud589\\n\\n:::\\n\\n### \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810\\n\\n\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc740 \uc11c\ubc84\uc5d0 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0 \ubcc0\uacbd\uc774 \uae4c\ub2e4\ub86d\ub2e4. \\n\ud1a0\ud3f4\ub85c\uc9c0\ub780 \ub124\ud2b8\uc6cc\ud06c\uc758 \uc694\uc18c\ub4e4\uc744 \ubb3c\ub9ac\uc801\uc73c\ub85c \uc5f0\uacb0\ud574 \ub193\uc740 \uac83, \ub610\ub294 \uadf8 \uc5f0\uacb0 \ubc29\uc2dd\uc744 \ub9d0\ud55c\ub2e4.\\n\\n```mermaid\\ngraph TD\\n\\tA[A binary-log:300] --\x3e B[B Binary-log:300]\\n\\tA[A binary-log:300] --\x3e C[C Binary-log:200]\\n```\\n\\n\uc704\uc640 \uac19\uc774 Source \uc11c\ubc84, Replica 2\ub300\uac00 \uc874\uc7ac\ud558\uace0, C \uc11c\ubc84\uc5d0 \ubcf5\uc81c \uc9c0\uc5f0\uc774 \ub418\uc5c8\uc744 \ub54c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\tA[A binary-log:300]\\n\\tB[B Binary-log:300] --\x3e C[C Binary-log:200 \ubb38\uc81c \ubc1c\uc0dd]\\n```\\n\\nA \uc11c\ubc84\uc5d0\uc11c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 B \uc11c\ubc84\ub97c Source \uc11c\ubc84\ub85c \uc2b9\uaca9\ud558\uace0, C\uc5d0\uac8c \uc870\ud68c \ucffc\ub9ac\ub97c \ubd84\uc0b0\uc2dc\ud0a8\ub2e4. \\n\ud558\uc9c0\ub9cc \uc5ec\uae30\uc11c C \uc11c\ubc84\uc5d0\ub294 A \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\uac00 \uc548\ub418\uc5c8\uc73c\ub2c8 \uc870\ud68c \uc2dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\ub4a4\ub2a6\uac8c B \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\ub97c \ud558\ub824\uace0 \ud574\ub3c4, \uc5b4\ub5a4 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8, \uc5b4\ub5a4 \uc704\uce58\uc640 \ub3d9\uae30\ud654\ud574\uc57c\ud558\ub294\uc9c0 \uc54c\uae30 \uc5b4\ub835\ub2e4. \\n\\n### \uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c\\n\\nGTID \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ubc1c\uc0dd\ud55c \uc774\ubca4\ud2b8\uc5d0 \uace0\uc720\ud55c \uc2dd\ubcc4\uac12\uc744 \ubd80\uc5ec\ud55c\ub2e4\uba74, \ub3d9\uae30\ud654\uc5d0 \ub300\ud55c \ubb38\uc81c\ub97c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4. \\n\uc704\uc758 \uc608\uc2dc\uc640 \uac19\uc774 \ubcf5\uc81c \uc9c0\uc5f0\uacfc \ud568\uaed8 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ud574\ub3c4 \ud2b9\uc815 GTID \ubd80\ud130 \ubcf5\uc81c\ub97c \uc7ac\uac1c\ud558\uba74 \ub41c\ub2e4. \\n\\n:::note GTID\\n\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\uc5d0 \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \uc11c\ubc84\uc5d0\uc11c \uace0\uc720\ud558\ub3c4\ub85d \uac01 \uc774\ubca4\ud2b8\uc5d0 \ubd80\uc5ec\ub41c \uc2dd\ubcc4\uac12 \\n[source_id]:[transaction_id]\ub85c \uad6c\uc131\ub418\uba70, source_id\ub294 \uc11c\ubc84\ub97c \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc774\uace0 transaction_id\ub294 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc73c\ub85c 1\uc529 \uc99d\uac00\ud558\ub294 \ud615\ud0dc\ub85c \ubc1c\uae09\ub41c\ub2e4. \\n:::\\n\\n### \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\\n\\n**\uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131**\\n\\n\uac00\uc7a5 \uac04\ub2e8\ud55c \uad6c\uc131\uc73c\ub85c \uc81c\uc77c \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4. \\nreplica \uc11c\ubc84\ub97c \uc77d\uae30 \uc804\uc6a9, \uc608\ube44 \uc11c\ubc84, \ubc31\uc5c5 \uc6a9\ub3c4\ub85c \ub9ce\uc774 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R\\n S[Source] --\x3e R[Replica]\\n```\\n\\n**\uba40\ud2f0 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131**\\n\\n2\uac1c\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4. \\n\ud558\ub098\uc758 replica\ub294 \uc608\ube44 \uc6a9\ub3c4\ub85c \ub0a8\uaca8\ub450\ub294 \ud615\ud0dc\ub2e4. \\n\ucd94\ud6c4\uc5d0 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 \uc608\ube44 \uc6a9\ub3c4\uc758 replica\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c \uc77d\uae30 \uc694\uccad\uc758 \ubd80\ud558 \ubd84\uc0b0\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R1\\n S[Source] --\x3e R1[Replica1]\\n S --\x3e R2[Replica2]\\n```\\n\\n**\uccb4\uc778 \ubcf5\uc81c \uad6c\uc131**\\n\\nreplica \uc11c\ubc84\uac00 \ub9ce\uc740 \uacbd\uc6b0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \uc804\ub2ec\ud558\ub294 \uc791\uc5c5 \uc790\uccb4\uac00 \ubd80\ud558\uac00 \ub420 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c 1:M:M \uad6c\uc870\ub85c \uccb4\uc778 \ubcf5\uc81c \uad6c\uc131\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R1\\n S[Source] --\x3e R1[Replica1]\\n S --\x3e R2[Replica2]\\n S --\x3e R3[Replica3]\\n\\n R3 --\x3e R3-1[Replica 3-1]\\n R3 --\x3e R3-2[Replica 3-2]\\n\\n B[Batch Server] --\x3e R3-2\\n```\\n\\n**\ub4c0\uc5bc \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131**\\n\\n2\uac1c\uc758 MySQL \uc11c\ubc84 \ubaa8\ub450 \uc77d\uae30\uc640 \uc4f0\uae30\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d \ud558\ub294 \uad6c\uc131\uc774\ub2e4. \\n\uac01 \uc11c\ubc84\uc5d0\uc11c \ubcc0\uacbd\ub41c \ub370\uc774\ud130\ub294 \ub2e4\ub978 \uc11c\ubc84\uc5d0 \ubc18\uc601\ub41c\ub2e4. \\n\ubaa9\uc801\uc5d0 \ub530\ub77c ACTIVE-ACTIVE \ud615\ud0dc \ub610\ub294 ACTIVE-PASSIVE \ud615\ud0dc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\nACTIVE-PASSIVE \ud615\ud0dc\uc778 \uacbd\uc6b0 \uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131\uacfc \ub3d9\uc77c\ud574\ubcf4\uc774\uc9c0\ub9cc, ACTIVE \uc11c\ubc84\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uba74 \uc124\uc815\uc758 \ubcc0\uacbd\uc5c6\uc774 PASSIVE \uc11c\ubc84\ub85c \uc4f0\uae30 \uc791\uc5c5\uc744 \uc804\ud658\ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc774 \uc7a5\uc810\uc774\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR1\\n W -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR2\\n SR1[Source/Replica 1] --\x3e SR2[Source/Replica 2]\\n```\\n\\n:::note ACTIVE-ACTIVE, ACTIVE-PASSIVE\\nACTIVE-ACTIVE: 2\uac1c\uc758 \uc11c\ubc84 \ubaa8\ub450 \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc \\nACTIVE-PASSIVE: \ud558\ub098\uc758 \uc11c\ubc84\uc5d0\uc11c\ub9cc \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc\\n:::\\n\\n**\uba40\ud2f0 \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131**\\n\\n\uc5ec\ub7ec\uac1c\uc758 source \uc11c\ubc84\uc640 \ud558\ub098\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \uad6c\uc131\uc774\ub2e4. \\n\uc774\ub294 source \uc11c\ubc84\uc758 \ub370\uc774\ud130\ub97c \ud55c \uacf3\uc5d0 \ubc31\uc5c5\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9, \uc5ec\ub7ec \uc11c\ubc84\uc5d0 \uc874\uc7ac\ud558\ub294 \ub370\uc774\ud130\ub97c \ud1b5\ud569, \uc0e4\ub529\ub418\uc5b4\uc788\ub294 \ud14c\uc774\ube14 \ub370\uc774\ud130\ub97c \ud1b5\ud569\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n S1[Source 1] --\x3e R[Replica]\\n S2[Source 2] --\x3e R\\n```\\n\\n## \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30\\n\\nmysql 2\ub300\ub97c \uc774\uc6a9\ud558\uc5ec replication\uc744 \uad6c\uc131\ud558\uace0, spring boot application\uc73c\ub85c source, replica \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\ubcf4\ub294 \uc608\uc81c\uc774\ub2e4. \\n[https://github.com/bbiac/db-replication](https://github.com/bbiac/db-replication) \\n\\n### MySQL \ud658\uacbd \uad6c\uc131\\n\\nMySQL \ubc84\uc804\uc740 8.1\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n13306, 13307 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud574\uc11c MySQL \uc11c\ubc84 2\ub300\ub97c \ub744\uc6e0\ub2e4. \\n\ub610\ud55c \uc0ac\uc2e4 IP \ub300\uc5ed\uc73c\ub85c \ud1b5\uc2e0\ud560 \uc218 \uc788\ub3c4\ub85d \ucee4\uc2a4\ud140 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud588\ub2e4. \\n\\n```yml\\nversion: \'3.8\'\\n\\nservices:\\n source:\\n platform: linux/x86_64\\n image: mysql:latest\\n restart: always\\n container_name: mysql-source\\n environment:\\n TZ: \'Asia/Seoul\'\\n MYSQL_DATABASE: \'db\'\\n MYSQL_USER: \'user\'\\n MYSQL_PASSWORD: \'password\'\\n MYSQL_ROOT_PASSWORD: \'password\'\\n ports:\\n - \\"13306:3306\\"\\n volumes:\\n - db-source:/var/lib/mysql\\n - db-source:/var/lib/mysql-files\\n - ./docker/source.cnf:/etc/mysql/my.cnf\\n networks:\\n - mysql_network\\n\\n replica:\\n platform: linux/x86_64\\n image: mysql:latest\\n restart: always\\n container_name: mysql-replica\\n environment:\\n TZ: \'Asia/Seoul\'\\n MYSQL_DATABASE: \'db\'\\n MYSQL_USER: \'user\'\\n MYSQL_PASSWORD: \'password\'\\n MYSQL_ROOT_PASSWORD: \'password\'\\n ports:\\n - \\"13307:3306\\"\\n volumes:\\n - db-replica:/var/lib/mysql\\n - db-replica:/var/lib/mysql-files\\n - ./docker/replica.cnf:/etc/mysql/my.cnf\\n networks:\\n - mysql_network\\n\\nvolumes:\\n db-source:\\n db-replica:\\n\\nnetworks:\\n mysql_network:\\n driver: bridge\\n```\\n\\n\ub610\ud55c source, replica \uac01\uac01 \ub2e4\uc74c\uacfc \uac19\uc774 db \uc124\uc815\uc744 \ud588\ub2e4. \\n\\n| \uc124\uc815 | \uc124\uba85 |\\n| --- | --- |\\n| server_id | \uac01\uac01\uc758 mysql \ub9c8\ub2e4 \uace0\uc720\ud55c \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4. |\\n| log_bin | \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815\uc73c\ub85c \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 /var/lib/mysql \uc544\ub798 \ud574\ub2f9 log_bin\uc5d0 \uc124\uc815\ub41c \uac12\uc73c\ub85c \ub85c\uadf8\uac00 \uc0dd\uc131\ub41c\ub2e4. |\\n| sync_binlog | N\uac1c\uc758 \ud2b8\ub79c\uc7ad\uc158 \ub2f9 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ub514\uc2a4\ud06c\uc640 \ub3d9\uae30\ud654 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d \ud55c\ub2e4.\xa01\uc740 \uae30\ubcf8\uac12\uc73c\ub85c \uc548\uc815\uc801\uc774\uc9c0\ub9cc, \uac00\uc7a5 \ub290\ub9ac\ub2e4. |\\n| relay_log | \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815 |\\n| relay_log_purge | \ud544\uc694 \uc5c6\ub294 \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \uc0ad\uc81c\ud558\ub294 \uc635\uc158 |\\n| read_only | \uc77d\uae30 \uc804\uc6a9 \uc124\uc815 |\\n| log_replica_updates | Replication SQL Thread\ub85c \uc778\ud574 \uc2e4\ud589\ub418\ub294 \uc815\ubcf4\ub97c \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc5d0 \uae30\ub85d \ucd94\ud6c4\uc5d0 \uc18c\uc2a4 \uc11c\ubc84\ub85c \uc2b9\uaca9\ub418\ub294 \uacbd\uc6b0\ub97c \uace0\ub824\ud558\uba74 \uc124\uc815\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. |\\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```cnf title=\\"/docker/source.cnf\\"\\n[mysqld]\\nserver_id=1\\nlog_bin=mysql-bin\\nsync_binlog=1\\n```\\n\\n\\n\\n\\n\\n```cnf title=\\"/docker/replica.cnf\\"\\n[mysqld]\\nserver_id=2\\nrelay_log=mysql-relay-bin\\nrelay_log_purge=ON\\nread_only\\nlog_replica_updates\\n```\\n\\n\\n\\n\\n### \ub3c4\ucee4 \uc2e4\ud589\\n\\ndocker-compose up \uba85\ub839\uc5b4\ub85c docker-compose \uc124\uc815\uc73c\ub85c docker\ub97c \ub744\uc6b4\ub2e4. \\n-d \uc635\uc158\uc744 \ubd99\uc774\uba74 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ubaa8\ub4dc\ub85c \uc2e4\ud589\ub41c\ub2e4. \\n\\n```\\ndocker-compose up -d\\n```\\n\\n### replication slave \uad8c\ud55c \uc124\uc815\\n\\nREPLICATION SLAVE \uad8c\ud55c\uc774 \uc124\uc815\ub418\uc5b4 \uc788\uc5b4\uc57c replica \uc11c\ubc84\uc5d0\uc11c source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec \ub85c\uadf8\ub97c \uc77d\uc5b4\uc62c \uc218 \uc788\ub2e4. \\nsource \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec user \uacc4\uc815\uc5d0 \ud574\ub2f9 \uad8c\ud55c\uc744 \uc124\uc815\ud574\uc900\ub2e4. \\n\\nSOURCE \uc811\uc18d\\n\\n```bash\\ndocker exec -it mysql-source mysql -u root -p\\n```\\n\\nuser \uacc4\uc815\uc5d0 REPLICATION SLAVE \uad8c\ud55c \ucd94\uac00\\n\\n```mysql\\nGRANT REPLICATION SLAVE ON *.* TO \'user\'@\'%\';\\nFLUSH PRIVILEGES;\\n```\\n\\n### SOURCE DB \uc815\ubcf4 \ud655\uc778\\n\\nreplica \uc124\uc815\uc5d0 \ud544\uc694\ud55c source db\uc758 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c\uba85\uacfc Position\uc744 \ud655\uc778\ud55c\ub2e4. \\nPosition \uac12\uc740 \uc2e4\uc81c \ud30c\uc77c\uc758 \ubc14\uc774\ud2b8 \uc218\ub97c \uc758\ubbf8\ud55c\ub2e4. \\n\ud655\uc778\ud55c File(SOURCE_LOG_FILE)\uacfc Position(SOURCE_LOG_POS) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n```mysql\\nSHOW MASTER STATUS;\\n\\n+------------------+----------+--------------+------------------+-------------------+\\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |\\n+------------------+----------+--------------+------------------+-------------------+\\n| mysql-bin.000003 | 1082 | | | |\\n+------------------+----------+--------------+------------------+-------------------+\\n```\\n\\n### SOURCE ip \uc8fc\uc18c \ud655\uc778\\n\\ndocker inspect -f \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ud574\ub2f9 \ucee8\ud14c\uc774\ub108\uc758 \uc138\ubd80 \uc815\ubcf4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud574 docker-compose \ud30c\uc77c\uc5d0 \uc124\uc815\ud574\ub454 mysql_network\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc124 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4. \\n\\n```bash\\ndocker inspect -f \\"{{with index .NetworkSettings.Networks \\\\\\"db-replication_mysql_network\\\\\\"}}{{.IPAddress}}{{end}}\\" mysql-source\\n```\\n\\nip \uc8fc\uc18c\uac00 \ub098\uc624\uc9c0 \uc54a\ub294 \uacbd\uc6b0 docker inspect mysql-source\ub85c \ud655\uc778\ud55c\ub2e4. \\n\ud655\uc778\ud55c IP\uc8fc\uc18c(SOURCE_HOST) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n### replica mysql \uc811\uc18d\\n\\nsource db\uc5d0 \uc811\uc18d\ud588\ub358 \ubc29\ubc95\uacfc \ub3d9\uc77c\ud558\uac8c replica db\uc5d0 \uc811\uc18d\ud55c\ub2e4. \\n\\n```bash\\ndocker exec -it mysql-replica mysql -u root -p\\n```\\n\\n### replica \uc124\uc815\\n\\n\uc774\uc804\uc5d0 source db\uc5d0\uc11c \uc5bb\uc5c8\ub358 \uc815\ubcf4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc5ec replica \uc124\uc815\uc744 \uc9c4\ud589\ud55c\ub2e4. \\n\uc2e4\uc81c DB \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc73c\ub85c source DB\uc758 \ud30c\uc77c\uc744 \ubcf5\uc81c\ud574\uc57c\ud558\uc9c0\ub9cc \ud604\uc7ac \ubcf5\uc81c\ud560 \ub370\uc774\ud130\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ubd80\ubd84\uc740 \uc0dd\ub7b5\ud588\ub2e4. \\nSOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS \ub97c \uc801\uc808\ud788 \ubcc0\uacbd\ud55c\ub2e4.\\n\\n```mysql\\nSTOP REPLICA;\\n\\nCHANGE REPLICATION SOURCE TO \\nSOURCE_HOST=\'172.29.0.2\', \\nSOURCE_USER=\'user\', \\nSOURCE_PASSWORD=\'password\', \\nSOURCE_LOG_FILE=\'mysql-bin.000001\', \\nSOURCE_LOG_POS=0, \\nGET_SOURCE_PUBLIC_KEY=1;\\n\\nSTART REPLICA;\\n```\\n\\n### \uc124\uc815 \ud655\uc778\\n\\n```mysql\\nSHOW REPLICA STATUS;\\n\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n| Waiting for source to send event | 172.25.0.3 | user | 3306 | 60 | mysql-bin.000003 | 1082 | mysql-relay-bin.000002 | 868 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 1082 | 1078 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | | | 1 | |\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n```\\n\\nReplica_IO_Running, Replica_SQL_Running \uac12\uc774 YES\ub77c\uba74 \uc815\uc0c1\uc801\uc73c\ub85c replication \uad6c\uc131\uc774 \uc644\ub8cc\ub41c \uac83\uc774\ub2e4. \\n\\n\uc124\uc815\uc744 \ub9c8\uce5c \ud6c4 source db\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 create table \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud55c\ub2e4. \\nreplica db\uc5d0 \ub3d9\uc77c\ud55c member table\uc774 \uc0dd\uc131\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\nCREATE TABLE member\\n(\\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\\n name VARCHAR(255)\\n);\\n```\\n\\n## \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30\\n\\n\uc77c\ubc18\uc801\uc778 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 source, \uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158\uc778 \uacbd\uc6b0 replica\ub85c \uc694\uccad\uc774 \uac00\ub3c4\ub85d \uad6c\uc131\ud574\ubcf4\uc790. \\n\\n### Environment \uc124\uc815\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 source, replica\ub85c \uad6c\ubd84\ud558\uc5ec \uc124\uc815\ud55c\ub2e4. \\n\\n```yml title=\\"application.yml\\"\\nspring:\\n datasource:\\n source:\\n username: user\\n password: password\\n driver-class-name: com.mysql.cj.jdbc.Driver\\n jdbc-url: jdbc:mysql://localhost:13306/db\\n replica:\\n username: user\\n password: password\\n driver-class-name: com.mysql.cj.jdbc.Driver\\n jdbc-url: jdbc:mysql://localhost:13307/db\\n```\\n\\n### DataSourceType \uc124\uc815\\n\\n\ub2e8\uc21c \ubb38\uc790\uc5f4\ub85c\ub3c4 \uad6c\ubd84\ud560 \uc218 \uc788\uc9c0\ub9cc, enum\uc744 \uc774\uc6a9\ud574\uc11c \ud2b8\ub79c\uc7ad\uc158\uc744 \uad6c\ubd84\ud558\ub3c4\ub85d \uc0dd\uc131\ud55c\ub2e4. \\nKey\ub294 \ucd94\ud6c4\uc5d0 \ube48 \uc124\uc815\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```java title=\\"DataSourceType\\"\\npublic enum DataSourceType {\\n SOURCE(SOURCE_NAME),\\n REPLICA(REPLICA_NAME),\\n ;\\n\\n private final String key;\\n\\n DataSourceType(String key) {\\n this.key = key;\\n }\\n\\n public static class Key {\\n public static final String ROUTING_NAME = \\"ROUTING\\";\\n public static final String SOURCE_NAME = \\"SOURCE\\";\\n public static final String REPLICA_NAME = \\"REPLICA\\";\\n }\\n}\\n```\\n\\n### AbstractRoutingDataSource \uc124\uc815\\n\\n\uc2a4\ud504\ub9c1\uc774 \uc9c0\uc6d0\ud574\uc8fc\ub294 AbstractRoutingDataSource\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSource\ub97c \ud5a5\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub294 `Map`\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\uc744 \ubc1b\uc544 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4. \\n- setDefaultTargetDataSource: \uae30\ubcf8 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4. \\n- setTargetDataSources: \ub9f5 \ud615\ud0dc\ub85c \ubc1b\uc740 \ub370\uc774\ud130 \uc18c\uc2a4 \uac12\ub4e4\uc744 \uc124\uc815\ud55c\ub2e4. \\n\\ndetermineCurrentLookupKey\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n- isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \ud2b8\ub79c\uc7ad\uc158\uc774 \uc77d\uae30 \uc804\uc6a9\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n- DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uace0, \ubc18\ud658\ud55c \uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ub370\uc774\ud130 \uc18c\uc2a4\uac00 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n```java title=\\"RoutingDataSource\\"\\npublic class RoutingDataSource extends AbstractRoutingDataSource {\\n\\n private final Logger log = LoggerFactory.getLogger(getClass());\\n\\n public static RoutingDataSource from(Map dataSources) {\\n RoutingDataSource routingDataSource = new RoutingDataSource();\\n routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));\\n routingDataSource.setTargetDataSources(dataSources);\\n return routingDataSource;\\n }\\n\\n @Override\\n protected Object determineCurrentLookupKey() {\\n boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();\\n\\n if (readOnly) {\\n log.info(\\"readOnly = true, request to replica\\");\\n return DataSourceType.REPLICA;\\n }\\n log.info(\\"readOnly = false, request to source\\");\\n return DataSourceType.SOURCE;\\n }\\n}\\n```\\n\\n### DataSource \uc124\uc815\\n\\n\uc704\uc5d0\uc11c\ubd80\ud130 \uc21c\uc11c\ub300\ub85c Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy \uc124\uc815\uc774\ub2e4. \\n\uc2a4\ud504\ub9c1\uc740 \ud2b8\ub79c\uc7ad\uc158 \uc2dc\uc791\uc2dc\uc5d0 \ucee4\ub125\uc158\uc758 \uc0ac\uc6a9\uc5ec\ubd80\uc640 \uc0c1\uad00\uc5c6\uc774 \ucee4\ub125\uc158\uc744 \ud655\ubcf4\ud55c\ub2e4. \\n\ub530\ub77c\uc11c readOnly \ud2b8\ub79c\uc7ad\uc158\uc774 \uc124\uc815\ub41c \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ubbf8\ub9ac \ud655\ubcf4\ub41c \ucee4\ub125\uc158\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 replica db\ub85c \uc694\uccad\uc744 \ud558\uc9c0 \uc54a\uace0 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4. \\n\\nTransactionSynchronizationManager.isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc \ud638\ucd9c \uc2dc currentTransactionReadOnly\ub77c\ub294 `ThreadLocal`\uc5d0 \uc124\uc815\ub41c \uac12\uc744 \ubc18\ud658\ud558\ub294\ub370 readOnly \uc124\uc815\uc774 \ub418\uba74 \uc774 \uac12\uc744 true\ub85c \uc124\uc815\ud55c\ub2e4. \ud558\uc9c0\ub9cc determineCurrentLookupKey\ub97c \ud638\ucd9c\ud558\uc5ec key \uac12\uc744 \uac00\uc838\uc624\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc774\ud6c4\uc5d0 \uc124\uc815\ub418\uae30 \ub54c\ubb38\uc5d0 determineCurrentLookupKey \uba54\uc11c\ub4dc\uc5d0\uc11c \ud56d\uc0c1 DataSourceType.SOURCE\uac00 \ubc18\ud658\ub418\uc5b4 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4. \\n\\nLazyConnectionDataSourceProxy\ub97c \uc124\uc815\ud558\ub294 \uacbd\uc6b0 \uc2e4\uc81c DataSource\ub97c \uc0ac\uc6a9\ud558\ub294 \uc2dc\uc810\uc5d0 \ucee4\ub125\uc158\uc744 \ud68d\ub4dd\ud574\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc124\uc815\ud55c\ub300\ub85c replica db\ub85c \uc870\ud68c \uc694\uccad\uc744 \ud55c\ub2e4. \\n\\n```java title=\\"DataSourceConfiguration\\"\\n@Configuration\\npublic class DataSourceConfiguration {\\n\\n @Bean\\n @Qualifier(SOURCE_NAME)\\n @ConfigurationProperties(prefix = \\"spring.datasource.source\\")\\n public DataSource sourceDataSource() {\\n return DataSourceBuilder.create().build();\\n }\\n\\n @Bean\\n @Qualifier(REPLICA_NAME)\\n @ConfigurationProperties(prefix = \\"spring.datasource.replica\\")\\n public DataSource replicaDataSource() {\\n return DataSourceBuilder.create().build();\\n }\\n\\n @Bean\\n @Qualifier(ROUTING_NAME)\\n public DataSource routingDataSource(\\n @Qualifier(SOURCE_NAME) DataSource sourceDataSource,\\n @Qualifier(REPLICA_NAME) DataSource replicaDataSource\\n ) {\\n return RoutingDataSource.from(Map.of(\\n DataSourceType.SOURCE, sourceDataSource,\\n DataSourceType.REPLICA, replicaDataSource\\n ));\\n }\\n\\n @Bean\\n @Primary\\n public DataSource dataSource(\\n @Qualifier(ROUTING_NAME) DataSource routingDataSource\\n ) {\\n return new LazyConnectionDataSourceProxy(routingDataSource);\\n }\\n}\\n```\\n\\n\ucd5c\uc885\uc801\uc73c\ub85c DataSource \ube48\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ud615\ud0dc\uac00 \ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n DSP[LazyConnectionDataSourceProxy] --\x3e RDS[RoutingDataSource]\\n\\tRDS --\x3e S[SourceDataSource]\\n\\tRDS --\x3e R[ReplicaDataSource]\\n```\\n\\n### \ub3d9\uc791 \ud655\uc778\\n\\n\uac04\ub2e8\ud558\uac8c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\uc11c \uc124\uc815\ud55c\ub300\ub85c \ub3d9\uc791\uc774 \ub418\ub294\uc9c0 \ud655\uc778\ud574\ubcf4\uc558\ub2e4. \\nsave \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 `@Transactional`, findById \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 `@Transactional(readOnly = true)`\uac00 \uc124\uc815\ub418\uc5b4\uc788\ub2e4. \\n\ub85c\uadf8\ub97c \ud1b5\ud574 save\uc758 \uacbd\uc6b0 source db\ub85c findById\uc758 \uacbd\uc6b0 replica db\ub85c \uc694\uccad\uc744 \ud558\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub2e4. \\n\\n```java title=\\"MemberServiceTest\\"\\n@SpringBootTest\\nclass MemberServiceTest {\\n\\n @Autowired\\n private MemberService memberService;\\n\\n @Test\\n void \uc0ac\uc6a9\uc790\ub97c_\uc800\uc7a5\ud55c\ub2e4() {\\n // RoutingDataSource log: readOnly = false\\n memberService.save(\\"bbiac\\");\\n }\\n\\n @Test\\n void \uc0ac\uc6a9\uc790\ub97c_\uc870\ud68c\ud55c\ub2e4() {\\n // RoutingDataSource log: readOnly = true\\n assertThatThrownBy(() -> memberService.findById(MAX_VALUE))\\n .isInstanceOf(NoSuchElementException.class);\\n }\\n}\\n```\\n\\nDB\uc5d0\uc11c\ub294 \ud655\uc778\ud558\ub824\uba74 root \uacc4\uc815\uc73c\ub85c \uc811\uc18d\ud55c \ud6c4 general log\ub97c \ud65c\uc131\ud654 \uc2dc\ud0a8\ub2e4. \\n\\n```sql\\nSET GLOBAL log_output = \'table\';\\nSET GLOBAL general_log = 1;\\n```\\n\\ngeneral log\ub97c \ud65c\uc131\ud654 \ud55c \ud6c4 \uc77d\uae30 \uc804\uc6a9 \uba54\uc11c\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4. \\nserver_id, \uc2e4\ud589\ud55c \ucffc\ub9ac\ubb38\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\nSELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like \'%select%\';\\n\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n| user_host | thread_id | server_id | convert(argument using utf8) |\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n| user[user] @ [172.25.0.1] | 277 | 2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n```\\n\\n\ud655\uc778 \ud6c4 general log\ub97c \ube44\ud65c\uc131\ud654 \ud55c \ud6c4 \ube44\ud65c\uc131\ud654 \ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\n```sql\\nSET GLOBAL general_log = 0;\\nSHOW VARIABLES LIKE \'%general%\';\\n\\n+------------------+---------------------------------+\\n| Variable_name | Value |\\n+------------------+---------------------------------+\\n| general_log | OFF |\\n| general_log_file | /var/lib/mysql/4b6b9db98290.log |\\n+------------------+---------------------------------+\\n```\\n\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n16\uc7a5 \ubcf5\uc81c, Real MySQL 8.0 - \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Replication, MySQL Docs](https://dev.mysql.com/doc/refman/8.1/en/replication.html) \\n[MySql - Master Slave Replication \uad6c\uc870 \ub9cc\ub4e4\uc5b4\ubcf4\uae30](https://huisam.tistory.com/entry/mysql-replication) \\n[Spring \ub808\ud50c\ub9ac\ucf00\uc774\uc158 \ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac \ubc29\uc2dd](https://cheese10yun.github.io/spring-transaction/) \\n[replication-datasource](https://github.com/kwon37xi/replication-datasource) \\n[Simplified Guide to MySQL Replication with Docker Compose](https://www.linkedin.com/pulse/simplified-guide-mysql-replication-docker-compose-rakesh-shekhawat/) \\n[Dockerfile\uc5d0\uc11c \uc790\uc8fc \uc4f0\uc774\ub294 \uba85\ub839\uc5b4](https://www.daleseo.com/dockerfile/) \\n[CHANGE REPLICATION SOURCE TO Statement](https://dev.mysql.com/doc/refman/8.1/en/change-replication-source-to.html) \\n[LazyConnectionDataSourceProxy](https://kwonnam.pe.kr/wiki/springframework/lazyconnectiondatasourceproxy) \\n[\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ub808\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ud1b5\ud55c \ucffc\ub9ac \uc131\ub2a5 \uac1c\uc120 (feat. Mysql, SpringBoot)](https://hudi.blog/database-replication-with-springboot-and-mysql/) \\n[\ubd80\ud558 \ubd84\uc0b0\uc744 \uc704\ud55c MySQL Replication \uad6c\uc131 \ubc0f \ucffc\ub9ac \uc694\uccad \ubd84\uae30](https://chagokx2.tistory.com/100) \\n[Use Docker Compose, Docker](https://docs.docker.com/get-started/08_using_compose/)"},{"id":"performance-test-type","metadata":{"permalink":"/performance-test-type","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx","source":"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx","title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","description":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8","date":"2023-09-10T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 10\uc77c","tags":[{"label":"performance test","permalink":"/tags/performance-test"}],"readingTime":5.8,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","slug":"performance-test-type","tags":["performance test"]},"unlisted":false,"prevItem":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"},"nextItem":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"}},"content":"## \uc131\ub2a5 \ud14c\uc2a4\ud2b8\\n\\nAPI\uc758 \uc694\uccad\uc774 \ub9ce\uc740 \uc0c1\ud669\uc5d0\uc11c \uc11c\ubc84\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\\n\\n\uc2dc\uc2a4\ud15c\uc5d0 \ubd80\ud558\uac00 \uac78\ub9ac\uba74 \ubb38\uc81c \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\uc591\ud55c \uc0c1\ud669\uc5d0 \ub300\ube44\ud574\uc11c \uc131\ub2a5 \ud14c\uc2a4\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4. \\n\\n![./test.png](./test.png)\\n\\n### \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)\\n\\n\ucd5c\uc18c\ud55c\uc758 \ubd80\ud558\ub97c \uc8fc\uc5b4 \uc2dc\uc2a4\ud15c\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\nVU\ub97c \ucd5c\uc18c\ud55c\uc73c\ub85c \ub450\uace0, \uc9e7\uc740 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \ud14c\uc2a4\ud2b8\ud55c\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud568\uc73c\ub85c\uc368 \ud14c\uc2a4\ud2b8 \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc624\ub958\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uace0, \uc131\ub2a5 \uc9c0\ud45c\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc9d1, \ubaa8\ub2c8\ud130\ub9c1 \ub418\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \uac00\uc0c1 \uc0ac\uc6a9\uc790(VU)\\n\uac00\uc0c1 \uc0ac\uc6a9\uc790\ub294 \uc11c\ubc84 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ub300\ud574 \ud2b9\uc815 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c\ub2e4. \\n\uc774\ub294 \ub2e4\ub978 \uac00\uc0c1 \uc0ac\uc6a9\uc790\uc640 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uba70, \uc5ec\ub7ec \uac00\uc0c1 \uc0ac\uc6a9\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc2dc \uc5f0\uacb0\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\uc2a4\ub808\ub4dc\ub77c\uace0 \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4. \\n:::\\n\\n### \uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)\\n\\n\uc0ac\uc6a9\ub7c9\uc774 \uae09\uc99d\ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uacac\ub514\uace0 \uc131\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\ud2f0\ucf13 \ubc1c\uae09, \ud560\uc778 \ucfe0\ud3f0 \ubc1c\uae09\uacfc \uac19\uc740 \uc774\ubca4\ud2b8\ub97c \ud558\ub294 \uacbd\uc6b0 \ub300\uaddc\ubaa8 \ud2b8\ub798\ud53d\uc774 \ub4e4\uc5b4\uc628\ub2e4. \\n\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uae09\uc99d\ud558\ub294 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\uace0, \ubd80\ud558\ub97c \uc798 \ubc84\ud2f0\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n### \ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)\\n\\n\ubaa9\ud46f\uac12\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \uacac\ub51c \uc218 \uc788\uc744\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\uc77c\ubc18\uc801\uc778 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\ub2e4. \\n\ub7a8\ud504\uc5c5 \ub610\ub294 \ubb19\ud46f\uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ubd80\ud558 \uae30\uac04\ub3d9\uc548 \uc131\ub2a5\uc774 \ubb38\uc81c\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uace0, \uc2dc\uc2a4\ud15c \ubcc0\uacbd \ud6c4\uc5d0\ub3c4 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ub3d9\uc77c\ud558\uac8c \ubaa9\ud46f\uac12\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \ub7a8\ud504 \uc5c5(Ramp-up)\\n\ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574 \uc124\uc815\ud55c \uac00\uc0c1 \uc0ac\uc6a9\uc790 \uc218\uc5d0 \ub3c4\ub2ec\ud558\ub294 \ub370 \uac78\ub9ac\ub294 \uc2dc\uac04\\n:::\\n\\n### \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test) \\n\\n\uc2dc\uc2a4\ud15c\uc758 \ucd5c\ub300\uce58\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \ubc1b\uc558\uc744 \ub54c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\uadf8\ub798\ud504\ub97c \ubd24\uc744 \ub54c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc640 \uc720\uc0ac\ud55c \ud615\ud0dc\ub85c \ubcf4\uc774\uc9c0\ub9cc, \ubd80\ud558\ub7c9\uc774 \ub2e4\ub974\ub2e4. \\n\uc77c\ubc18\uc801\uc73c\ub85c \ud3c9\uade0\uc801\uc778 \ubaa9\ud46f\uac12 \ub300\ube44 \uc791\uac8c\ub294 50% \uc774\uc0c1, \ud544\uc694\uc758 \uacbd\uc6b0 \uadf8 \uc774\uc0c1\uc73c\ub85c \ubd80\ud558\ub97c \uc900\ub2e4. \\n\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub294 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c \ud6c4\uc5d0\ub9cc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4. \ubd80\ud558 \ud14c\uc2a4\ud2b8\uac00 \uc774\ub8e8\uc5b4\uc9c0\uc9c0 \uc54a\uc740 \uc0c1\ud669\uc5d0\uc11c \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \ubcd1\ubaa9 \uc9c0\uc810\uc774\ub098 \ubb38\uc81c \uc0c1\ud669\uc744 \ucc3e\uae30 \uc5b4\ub824\uc6cc\uc9c4\ub2e4. \\n\ub610\ud55c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c VU\uac12(\uc2a4\ub808\ub4dc \uc218)\ub9cc \uc218\uc815\ud558\uc5ec \uc7ac\uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\\n### \ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test) \\n\\n\ud3c9\uade0 \uc0ac\uc6a9\ub960\ub85c \uc77c\uc815 \ubd80\ud558\ub97c \uc9c0\uc18d\uc801\uc73c\ub85c \uc8fc\uba70 \uc2dc\uc2a4\ud15c\uc774 \ubb38\uc81c\ub418\ub294 \uc9c0\uc810\uc744 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\ud761\uc218 \ud14c\uc2a4\ud2b8(Soak Test)\ub77c\uace0\ub3c4 \ud558\uba70, \uae30\ubcf8\uc801\uc778 \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc758 \ubcc0\ud615\uc774\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc640 \ub2ec\ub9ac \uae34 \uc2dc\uac04\ub3d9\uc548 \ud14c\uc2a4\ud2b8\ub97c \ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\uba70, \uba54\ubaa8\ub9ac \ub204\uc218 \ubb38\uc81c\uc640 \uac19\uc774 \uc7a5\uc2dc\uac04 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud560 \ub54c \uc2dc\uc2a4\ud15c\uc758 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \ubd80\ubd84\uc744 \ud655\uc778\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4. \\n\\n### \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)\\n\\n\uc784\uacc4 \uc9c0\uc810\uc744 \ucc3e\uae30 \uc704\ud574 \ubd80\ud558\ub97c \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a4\uba70 \uc9c4\ud589\ud558\ub294 \ud14c\uc2a4\ud2b8\\n\\n\ubb38\uc81c\ub418\ub294 \ubd80\ubd84\uc744 \ub354 \ube68\ub9ac \ucc3e\uae30 \uc704\ud574 \ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\ud55c \ub2e4\uc74c\uc5d0 \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud558\uace0, \uc774 \ub54c \uc810\uc9c4\uc801\uc73c\ub85c \ubd80\ud558\ub97c \ub298\ub824\ub098\uac00\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc131\ub2a5 \ud29c\ub2dd\uacfc \ubc18\ubcf5\ud574\uc11c \uc9c4\ud589\ud55c\ub2e4\uba74, \uc2dc\uc2a4\ud15c\uc744 \ub354\uc6b1 \ubc1c\uc804\uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\ub2e4\ub9cc Auto Scaling\uc774 \uc801\uc6a9\ub41c \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c\ub294 \uc9c4\ud589\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Load test types, k6](https://k6.io/docs/test-types/load-test-types/) \\n\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc \\n\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"},{"id":"tomcat-retrospective","metadata":{"permalink":"/tomcat-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","description":"1, 2\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-http/pull/302","date":"2023-09-11T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 11\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":12.345,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","slug":"tomcat-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"},"nextItem":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","permalink":"/log-async-exception"}},"content":":::note PR \ub9c1\ud06c \\n1, 2\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-http/pull/302 \\n3, 4\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-http/pull/431\\n:::\\n\\n### \ud1b0\ucea3 \uad6c\ud604\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4. \\n\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4. \\n\\n\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616/)\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4. \\n\\n### \ub2e4\uc774\uc5b4\uadf8\ub7a8\\n\\nCatalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4. \\n\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4. \\n\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph coyote\\n\\t\\tHP[Http11Processor] --\x3e A\\n\\t\\tHP --\x3e HttpRequestParser\\n\\t\\tHP --\x3e HttpResponseGenerator\\n\\t\\tA[Adapter]\\n end\\n\\n subgraph catalina\\n\\t\\tRA[RequestAdapter] -.-> A\\n\\t\\tAC[AbstractController] -.-> C[Controller]\\n\\t\\tStaticController -.-> AC\\n\\t\\tSM[SessionManger] -.-> Manager\\n\\t\\tTC[Tomcat] --\x3e RA\\n\\t\\tRA --\x3e C\\n\\t\\tRA --\x3e Manager\\n\\t\\tRA --\x3e RM\\n\\t\\tRM[RequestMapper] --\x3e C\\n end\\n\\n subgraph jwp\\n\\t\\tLC[LoginController] -.-> AC\\n\\t\\tApplication --\x3e TC\\n end\\n\\n```\\n\\n### \ucf54\ub4dc \ub9ac\ubdf0 \\n\\n\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4. \\n\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4. \\n\\n\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4. \\n\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### SessionConfig\\n\\n\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 [\ucee8\ud2b8\ub9ac\ubdf0\ud2b8](https://github.com/apache/tomcat/pull/660)\ub97c \uc2dc\ub3c4\ud588\ub2e4. \\n\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4. \\n\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4. \\n\\n\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4. \\n\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4. \\n\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n\\n String result = getConfiguredSessionCookieName(context);\\n\\n if (result == null) {\\n result = DEFAULT_SESSION_COOKIE_NAME;\\n }\\n\\n return result;\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n\\n String result = getConfiguredSessionCookieName(context);\\n\\n if (result == null) {\\n result = DEFAULT_SESSION_PARAMETER_NAME;\\n }\\n\\n return result;\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context) {\\n\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n if (context != null) {\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc =\\n context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n }\\n\\n return null;\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n if (context == null) {\\n return DEFAULT_SESSION_COOKIE_NAME;\\n }\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n if (context == null) {\\n return DEFAULT_SESSION_PARAMETER_NAME;\\n }\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n return defaultName;\\n}\\n```\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n if (context != null) {\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n }\\n return defaultName;\\n}\\n```\\n\\n\\n\\n\\n### HTTP \uc218\uc5c5\\n\\n\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. \\n\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4. \\nHTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. \\n\\n\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4. \\n\\n```yml\\nserver:\\n compression:\\n enabled: true\\n```\\n\\n\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4. \\n\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 [issue](https://github.com/spring-projects/spring-boot/issues/21369)\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4. \\n\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4. \\n\\n> If you\'re developing a public-facing application then it\'s probably likely gzip compression would be worthwhile. If, however, you\'re a microservice application and you\'re in a dataceter, you may well prefer to reduce CPU load because you know you\'ll only be talking to other microservices and you have a reliable gigabit network.\\n\\nPhil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4. \\n\\n\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4. \\n\\n:::note ETag\\nETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4. \\n\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4. \\nMDN\\n:::\\n\\n### Thread \uc218\uc5c5\\n\\n\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4. \\n\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4. \\n\\n\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4. \\n\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n`threads.max`: Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218 \\n`max-connections`: Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218 \\n`accept-count`: \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n C(\\"Client\\") -- request --\x3e ACQ(\\"\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \\n size = accept-count\\") --\x3e TCQ(\\"Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\\n size = max-connections\\") --\x3e TP(\\"Thread Pool\\n size = threads.max\\")\\n```\\n\\n### \ub9c8\uce58\uba70\\n\\n\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4. \\n\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4. \\n\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616/) \\n[ETag, mdn](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag) \\n[Apache Tomcat 8 Configuration Reference](https://tomcat.apache.org/tomcat-8.5-doc/config/http.html) \\n[Apache Tomcat Tuning, Terry Cho](https://bcho.tistory.com/788) \\n[maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30](https://dev-ws.tistory.com/96)"},{"id":"log-async-exception","metadata":{"permalink":"/log-async-exception","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx","source":"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx","title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","description":"\ubb38\uc81c \uc0c1\ud669","date":"2023-09-18T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 18\uc77c","tags":[{"label":"async","permalink":"/tags/async"},{"label":"exception","permalink":"/tags/exception"}],"readingTime":3.615,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","slug":"log-async-exception","tags":["async","exception"]},"unlisted":false,"prevItem":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"},"nextItem":{"title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","permalink":"/web-application-evolution"}},"content":"### \ubb38\uc81c \uc0c1\ud669\\n\\n\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 `@Async`\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 `@ControllerAdvice` + `@ExceptionHandler`\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4. \\n\\n### \ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815\\n\\n\uc2a4\ud504\ub9c1 4.1 \ubd80\ud130 \uc81c\uacf5\ub418\ub294 [AsyncUncaughtExceptionHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html)\uc758 \uacbd\uc6b0 \ubc18\ud658 \ud0c0\uc785\uc774 void\uc778 \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\ub97c \uc608\uc678 \ucc98\ub9ac\ud558\uae30 \uc27d\ub3c4\ub85d \ub3c4\uc640\uc900\ub2e4. \\n\\n\ub530\ub77c\uc11c AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ud578\ub4e4\ub9c1\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4. \\n\uae30\uc874\uc758 \ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4. \\n\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\ub3c4 \ub9c8\ucc2c\uac00\uc9c0\ub85c MDC\uc758 \uc815\ubcf4\ub97c \uac00\uc838\uc640\uc11c \ub85c\uadf8\ub97c \ucd9c\ub825\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4. \\n\\n```java title=AsyncExceptionHandler\\n@Slf4j\\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\\n\\n private static final String LOG_FORMAT = \\"[%s] %s\\";\\n\\n @Override\\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\\n }\\n}\\n```\\n\\nAsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4. \\ngetAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4. \\n\\n```java title=AsyncConfig\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig implements AsyncConfigurer {\\n\\n @Override\\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\\n return new AsyncExceptionHandler();\\n }\\n}\\n```\\n\\n\uc774\uc81c \ube44\ub3d9\uae30 \uc0c1\ud669\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544 \ucc98\ub9ac\ud55c\ub2e4. \\n\\n### MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c\\n\\n\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\\n![./mdc-null.png](./mdc-null.png)\\n\\n\uc2a4\ud504\ub9c1 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 [TaskDecorator](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html)\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n```java title=MdcTaskDecorator\\npublic class MdcTaskDecorator implements TaskDecorator {\\n\\n @Override\\n public Runnable decorate(final Runnable runnable) {\\n Map threadContext = MDC.getCopyOfContextMap();\\n return () -> {\\n MDC.setContextMap(threadContext);\\n runnable.run();\\n };\\n }\\n}\\n```\\n\\n\uc0dd\uc131\ud55c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4.\\n\\n```java title=AsyncConfig\\n@RequiredArgsConstructor\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig implements AsyncConfigurer {\\n\\n private final AsyncConfigurationProperties properties;\\n\\n @Bean\\n public ThreadPoolTaskExecutor taskExecutor() {\\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\\n executor.setCorePoolSize(properties.coreSize());\\n executor.setMaxPoolSize(properties.maxSize());\\n executor.setQueueCapacity(properties.queueCapacity());\\n \\n // highlight-next-line\\n executor.setTaskDecorator(new MdcTaskDecorator());\\n executor.setWaitForTasksToCompleteOnShutdown(true);\\n executor.initialize();\\n return executor;\\n }\\n\\n @Override\\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\\n return new AsyncExceptionHandler();\\n }\\n}\\n```\\n\\n\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4.\\n\\n![./mdc-not-null.png](./mdc-not-null.png)\\n\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[spring async, baeldung](https://www.baeldung.com/spring-async) \\n[@Async will not call by @ControllerAdvice for global exception](https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception) \\n[Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8](https://blog.gangnamunni.com/post/mdc-context-task-decorator/) \\n[TaskDecorator, Spring docs](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html) \\n[AsyncUncaughtExceptionHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html)"},{"id":"web-application-evolution","metadata":{"permalink":"/web-application-evolution","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx","source":"@site/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx","title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","description":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","date":"2023-09-30T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 30\uc77c","tags":[{"label":"web application","permalink":"/tags/web-application"}],"readingTime":7.5,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","slug":"web-application-evolution","tags":["web application"]},"unlisted":false,"prevItem":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","permalink":"/log-async-exception"},"nextItem":{"title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","permalink":"/spring-test-isolation"}},"content":"### \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815\\n\\n\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4. \\n\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4. \\n\uc6d0\ub798 \ud68c\uace0\uc5d0 \uc791\uc131\ud558\ub824\uace0 \ud588\uc9c0\ub9cc, \uc815\ub9ac\ud558\ub2e4 \ubcf4\ub2c8 \uc870\uae08 \uae38\uc5b4\uc838\uc11c \ub530\ub85c \ubd84\ub9ac\ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking\\n```\\n\\n### WWW(1989)\\n\\n\uc815\uc801 \ud398\uc774\uc9c0\ub97c \uc81c\uacf5\ud558\ub294 \uc6f9 \uc11c\ubc84\ub97c \uc2dc\uc791\uc73c\ub85c \ub3d9\uc801 \ud398\uc774\uc9c0\uac00 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 CGI\uac00 \ub4f1\uc7a5\ud588\ub2e4. \\n\\n### CGI(1993) \\n\\nCGI\ub294 \ub3d9\uc801 \ucf58\ud150\uce20\ub97c \uc81c\uacf5\ud558\uae30 \uc704\ud55c \uaddc\uc57d\uc73c\ub85c, \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc774\uc6a9\ud574\uc11c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ucf1c \uc815\ubcf4\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ub9ce\uc740 \ubd80\ud558\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc774\ub7ec\ud55c \ub2e8\uc810\uc744 \uadf9\ubcf5\ud558\uae30 \uc704\ud574 \ub098\uc628 \uac83\uc774 Servlet\uc774\ub2e4. \\n\\n### Servlet(1996)\\n\\nServlet\uc740 \uc6f9 \uc11c\ubc84\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uc790\ubc14 \ud504\ub85c\uadf8\ub7a8\uc73c\ub85c HTTP\ub97c \uc774\uc6a9\ud558\uc5ec \uc6f9 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc744 \uc218\uc2e0\ud558\uace0 \uc751\ub2f5\ud55c\ub2e4. CGI\uc640 \ub2e4\ub974\uac8c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\uac00 \uc544\ub2cc \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uc5ec \uc751\ub2f5\ud55c\ub2e4. \\n\ud558\uc9c0\ub9cc View \uc601\uc5ed\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uae30 \uc704\ud574 Servlet\uc758 \uc18c\uc2a4 \ucf54\ub4dc\ub97c \uc54c\uc544\uc57c \ud558\ub294 \ub4f1 \ubcf5\uc7a1\ub3c4\uac00 \ub108\ubb34 \ub192\uc558\ub2e4. \ub530\ub77c\uc11c \ud574\ub2f9 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 JSP\uac00 \ub4f1\uc7a5\ud588\ub2e4. \\n\\n### JSP(1999)\\n\\nJSP\ub294 HTML\uc5d0 \uc790\ubc14 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ub3d9\uc801 \uc6f9 \ud398\uc774\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\uc220\ub85c, \uc720\uc0ac\ud55c \uae30\uc220\ub85c\ub294 ASP, PHP\uac00 \uc788\ub2e4. \\nJSP\ub9cc \uc0ac\uc6a9\ud558\uc5ec \ud504\ub85c\uadf8\ub798\ubc0d\ud55c\ub2e4\uba74 Model 1, \uc544\ub798 \uad6c\uc131\ub3c4\uc640 \uac19\uc774 JSP\uac00 View \uc601\uc5ed\ub9cc \ub2f4\ub2f9\ud55c\ub2e4\uba74 Model 2\ub77c\uace0 \ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: JSP Model 2\\n---\\ngraph LR\\n Client -- Request --\x3e Servlet <-- JDBC --\x3e Database\\n\\tServlet --\x3e Bean\\n\\tServlet --\x3e JSP\\n\\tBean <--\x3e JSP\\n\\tJSP -- Response --\x3e Client\\n```\\n\\n### MVC(2000)\\n\\n\uc704 JSP\uc758 \uad6c\uc131\ub3c4\ub97c \ubcf4\uba74 \ud604\uc7ac MVC\uc640 \ub9e4\uc6b0 \uc720\uc0ac\ud55c\ub370, Govind Seshadri\ub77c\ub294 \uc0ac\ub78c\uc774 JSP Model 2\ub97c MVC \ud328\ud134\uc73c\ub85c \uacf5\uc2dd\ud654\ub97c \uc81c\uc548\ud588\ub2e4. \\n\\n> I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern. \\n> Govind Seshadri\\n\\n\uc774\ub54c MVC \ud328\ud134\uc774 \ucc98\uc74c \ud0c4\uc0dd\ud55c \uac83\uc740 \uc544\ub2c8\uace0, \uc11c\ubc84 \uce21 \uad6c\ud604\uc774\ub77c\uace0 \ud558\ub294 \uac83\uc744 \ubcf4\ub2c8 MVC\uac00 \ucc98\uc74c \ub4f1\uc7a5\ud55c \uac74 \uc544\ub2cc \uac83 \uac19\ub2e4. \\n[\ud574\ub2f9 \ubb38\uc11c](https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html)\ub97c \ubcf4\uba74 MVC\ub77c\ub294 \uc6a9\uc5b4\uc758 \ub4f1\uc7a5\uc740 1978\ub144\uc5d0 \ub4f1\uc7a5\ud55c \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4. \\n\\n### Spring Framework(2003)\\n\\nSpring\uc740 \ubcf5\uc7a1\ud588\ub358 J2EE\uc744 \ub300\uccb4\ud558\uae30 \uc704\ud574 2003\ub144\uc5d0 \ub4f1\uc7a5\ud588\ub2e4. \\nJ2EE\ub294 \uc6f9 \uae30\ubc18\uc758 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\uae30 \uc704\ud55c \ud50c\ub7ab\ud3fc\uc73c\ub85c \uc704\uc5d0\uc11c \uc124\uba85\ud55c Servlet, JSP, EJB \ub4f1\uc758 \uae30\uc220\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \uc774\uc911 EJB\ub77c\ub294 \uae30\uc220\uc774 J2EE\uc758 \ud575\uc2ec \uae30\uc220\uc774\uc5c8\ub294\ub370, \ud574\ub2f9 \uae30\uc220\uc774 \ub9e4\uc6b0 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub9ce\uc558\ub2e4\uace0 \ud55c\ub2e4. \\n2002\ub144\uc5d0 Rod Johnson\uc774 EJB\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 J2EE \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc800\uc220\ud55c `Expert One-to-One J2EE Development`\ub77c\ub294 \ucc45\uc744 \ubc1c\ud589\ud588\uace0, \ucd9c\uac04 \ud6c4 Juergen Hoeller, Yann Caroff\uac00 Rod Johnson\uc5d0\uac8c \uc624\ud508\uc18c\uc2a4 \uc81c\uc548\uc744 \ud558\uc5ec \uc2a4\ud504\ub9c1\uc774 \ud0c4\uc0dd\ud588\ub2e4\uace0 \ud55c\ub2e4. \\n\\n\uc2a4\ud504\ub9c1\uc740 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc11c\ube44\uc2a4 \uae30\ub2a5\uc744 POJO\uc5d0 \uc81c\uacf5\ud558\uba70, \uc774 \ub355\ubd84\uc5d0 \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\ub2e4. \\n\\n### WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)\\n\\nTomcat\uc758 NIO \ub3d9\uc791 \ubc29\uc2dd\uc744 \ubcf4\uba74 Poller\uac00 \uc18c\ucf13 \ucee4\ub125\uc158\uc744 \ub4e4\uace0 \uc788\ub2e4\uac00 \ucc98\ub9ac\uac00 \uac00\ub2a5\ud560 \ub54c \uc2a4\ub808\ub4dc\ub97c \ud560\ub2f9\ud558\ub294 \uc2dd\uc73c\ub85c \ucc98\ub9ac\ub97c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ud560\ub2f9 \ud6c4 Servlet\uacfc \ud1b5\uc2e0\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \uc694\uccad\uc774 \ub05d\ub0a0 \ub54c\uae4c\uc9c0 \uc2a4\ub808\ub4dc\ub97c \uc810\uc720\ud558\uace0 \uc788\uc5c8\uace0, \uc2a4\ub808\ub4dc \uc810\uc720\ub85c \uc778\ud574 \uc694\uccad\uc774 max thread\uc5d0 \ub3c4\ub2ec\ud558\uba74 \uc694\uccad\uc744 \ucc98\ub9ac\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uadf8\ub798\uc11c \ube44\ub3d9\uae30 \ubc29\uc2dd\uc758 Servlet\uc774 Servlet 3.0\uc5d0 \ub4f1\uc7a5\ud588\ub2e4. \ud558\uc9c0\ub9cc \uc804\ud1b5\uc801\uc778 I/O \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \ub3d9\uc791\ud588\ub2e4. Servlet 3.1\uc5d0\uc11c \ub17c\ube14\ub85c\ud0b9 I/O\uac00 \ucd94\uac00\ub418\uc5c8\uc9c0\ub9cc, \ub9ce\uc774 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc558\ub2e4\uace0 \ud55c\ub2e4. \\n\\n### Spring WebFlux(2017)\\n\\n\uc801\uc740 \uc218\uc758 \uc2a4\ub808\ub4dc\ub85c \ub3d9\uc2dc\uc131\uc744 \ucc98\ub9ac\ud558\uace0, \uc801\uc740 \ub9ac\uc18c\uc2a4\ub85c \ud655\uc7a5\uc774 \uac00\ub2a5\ud55c \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd\uc758 \uc6f9 \uae30\uc220\uc774 \ud544\uc694\ud588\uace0, \uae30\uc874\uc758 Servlet\uc758 \uacbd\uc6b0 \ube44\ub3d9\uae30\ub97c \uc9c0\uc6d0\ud55c\ub2e4 \ud574\ub3c4 \ub3d9\uae30\uc2dd API\ub4e4\uc774 \ub9ce\uc774 \ub0a8\uc544\uc788\uc5c8\uae30 \ub54c\ubb38\uc5d0 \uc774\ub7ec\ud55c Servlet\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294 \uae30\uc220\uc774 \ud544\uc694\ud588\ub2e4. \ub610\ud55c \uae30\uc874\uc5d0 Netty\uc640 \uac19\uc774 \ube44\ub3d9\uae30, \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd \uc11c\ubc84\ub85c \uc790\ub9ac\ub97c \uc798 \uc7a1\uc740 \uc11c\ubc84\ub97c \uc704\ud574 Spring WebFlux\uac00 \ub4f1\uc7a5\ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub370\uc774\ud130 \uc811\uadfc\uc744 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 JDBC\uc758 \uacbd\uc6b0 Blocking API\ub77c, Spring Webflux\uc5d0\uc11c\ub294 R2DBC\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uace0 \ud55c\ub2e4. \\n\\n### \ub9c8\uce58\uba70\\n\\n\ud574\ub2f9 \uc815\ub9ac \ub0b4\uc6a9\uc758 \uacbd\uc6b0 Async, Non Blocking \uad00\ub828\ub41c \ub0b4\uc6a9\uc744 \uae4a\uac8c \uacf5\ubd80\ud55c \uc801\uc774 \uc5c6\uc5b4\uc11c \uc815\ud655\ud558\uc9c0 \uc54a\uc744 \uc218 \uc788\ub2e4. \\n\uadf8\ub798\ub3c4 \uae30\uc220\uc758 \ub4f1\uc7a5 \ubc30\uacbd\uc774\ub098 \uacfc\uc815\uc744 \uc54c\uace0 \uc788\ub2e4\uba74 \uc870\uae08 \ub354 \uae4a\uc774 \uc788\ub294 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815, \uad6c\uad6c \uac15\uc758 \\n[Dynamic Content with CGI, Apache Tutorial](https://httpd.apache.org/docs/trunk/en/howto/cgi.html) \\n[History of Spring and the Spring Framework, Spring](https://docs.spring.io/spring-framework/reference/overview.html#overview-history) \\n[Understanding JavaServer Pages Model 2 architecture, Govind Seshadri](https://www.infoworld.com/article/2076557/understanding-javaserver-pages-model-2-architecture.html) \\n[MVC, XEROX PARC](https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html) \\n[Expert One-to-One J2EE Development, Rod Johnson](https://www.amazon.com/Expert-One-One-Development-without/dp/0764558315) \\n[\ubc30\ub2ec\uc758\ubbfc\uc871 \ucd5c\uc804\ubc29 \uc2dc\uc2a4\ud15c! \u2018\uac00\uac8c\ub178\ucd9c \uc2dc\uc2a4\ud15c\u2019\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4, \ubc30\ub2ec\uc758\ubbfc\uc871](https://techblog.woowahan.com/2667/) \\n[Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu](https://www.infoworld.com/article/2077995/java-concurrency-asynchronous-processing-support-in-servlet-3-0.html)\\n[WebFlux Overview, Spring](https://docs.spring.io/spring-framework/reference/web/webflux/new-framework.html)\\n[Spring WebFlux\uc640 Armeria\ub97c \uc774\uc6a9\ud558\uc5ec Microservice\uc5d0 \ud544\uc694\ud55c Reactive + RPC \ub3d9\uc2dc\uc5d0 \uc7a1\uae30, Naver D2](https://d2.naver.com/helloworld/6080222) \\n[Spring WebFlux\ub780 \ubb34\uc5c7\uc77c\uae4c](https://tweety1121.tistory.com/entry/Spring-WebFlux-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C)"},{"id":"spring-test-isolation","metadata":{"permalink":"/spring-test-isolation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md","source":"@site/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md","title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","description":"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac","date":"2023-10-03T00:00:00.000Z","formattedDate":"2023\ub144 10\uc6d4 3\uc77c","tags":[{"label":"test","permalink":"/tags/test"}],"readingTime":4.315,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","slug":"spring-test-isolation","tags":["test"]},"unlisted":false,"prevItem":{"title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","permalink":"/web-application-evolution"},"nextItem":{"title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/mvc-retrospective"}},"content":"### \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\\n\\n\ud14c\uc2a4\ud2b8\uc758 \uc21c\uc11c\uc5d0 \ub530\ub77c \uc131\uacf5 \uc2e4\ud328 \uc5ec\ubd80\uac00 \uacb0\uc815\ub418\ub294 \ube44\uacb0\uc815\uc801\uc778(non-determinism) \ud14c\uc2a4\ud2b8\uac00 \ub418\uc5b4\uc11c\ub294 \uc548\ub418\uace0, \ud14c\uc2a4\ud2b8\ub294 \ud56d\uc0c1 \uc21c\uc11c\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc218\ud589\ub418\ub3c4\ub85d \ubcf4\uc7a5\ub418\uc5b4\uc57c \ud55c\ub2e4. \uc77c\ubc18\uc801\uc73c\ub85c \uc790\uc6d0\uc758 \uacf5\uc720, \uc678\ubd80 API, \uc2dc\uac04 \ub4f1\uc73c\ub85c \ube44\uacb0\uc815\uc801\uc778 \ud14c\uc2a4\ud2b8\uac00 \ub41c\ub2e4. \uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \uc0ac\uc6a9\ud558\uac70\ub098, \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc7ac\uc2e4\ud589\ud558\ub294 `@DirtiesContext`, \uc790\uc6d0\uc744 \ucd08\uae30\ud654\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uc774\ud6c4\uc5d0 \ud14c\uc774\ube14\uc744 \ub864\ubc31 \ud558\ub294 `@Transactional`\ub4f1 \ub2e4\uc591\ud55c \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\ud574\ub2f9 \uae00\uc5d0\uc11c\ub294 \uc2a4\ud504\ub9c1\uc5d0\uc11c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc790\uc6d0\uc758 \uacf5\uc720\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc218\ud589\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc124\uba85\ud55c\ub2e4. \\n\\n:::note Independent - FIRST\\n\\n\ud14c\uc2a4\ud2b8\ub07c\ub9ac \uc11c\ub85c \uc758\uc874\ud558\uba74 \uc548 \ub41c\ub2e4. \\n\uc11c\ub85c \uc758\uc874\ud558\uac8c \ub41c\ub2e4\uba74 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \ub54c, \ub610 \ub2e4\ub978 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud14c\uc2a4\ud2b8\uac00 \uc88b\uc740 \ud14c\uc2a4\ud2b8\ub2e4. \\n\\n:::\\n\\n### TestExecutionListener\\n\\n\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 TextExecutionListner\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 \ud14c\uc2a4\ud2b8 \uc2e4\ud589 \ub2e8\uacc4\uc5d0\uc11c \uc774\ubca4\ud2b8\ub97c \uc218\uc2e0\ud560 \uc218 \uc788\ub2e4. \\n\uc774\ub97c \uc774\uc6a9\ud558\uba74 JUnit\uc758 @BeforeEach\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uacfc \uc720\uc0ac\ud558\uac8c, \ud14c\uc2a4\ud2b8\uc758 \uc0dd\uba85\uc8fc\uae30 \uc774\uc804 \ub610\ub294 \uc774\ud6c4\uc5d0 \ud544\uc694\ud55c \uc791\uc5c5\uc744 \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\\n```java title=TextExecutionListner\\npublic interface TestExecutionListener {\\n default void beforeTestClass(TestContext testContext) throws Exception {}\\n default void prepareTestInstance(TestContext testContext) throws Exception {}\\n default void beforeTestMethod(TestContext testContext) throws Exception {}\\n default void beforeTestExecution(TestContext testContext) throws Exception {}\\n default void afterTestExecution(TestContext testContext) throws Exception {}\\n default void afterTestMethod(TestContext testContext) throws Exception {}\\n default void afterTestClass(TestContext testContext) throws Exception {}\\n}\\n```\\n\\n### AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604\\n\\nAbstractTestExecutionListener\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac \ud658\uacbd\uc744 \ub9cc\ub4e4\uc5b4\uc8fc\ub294 \ud074\ub798\uc2a4\ub85c, \uc778\ud130\ud398\uc774\uc2a4\uc778 TextExecutionListner\uc640 \ub2ec\ub9ac Ordered\uac00 \uad6c\ud604\ub418\uc5b4 \uc788\uc5b4 \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ubc1b\uc544 \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub294 \ud504\ub808\uc784\uc6cc\ud06c\uac00 \uc81c\uacf5\ud558\ub294 \ub9ac\uc2a4\ub108 \ub2e4\uc74c\uc5d0 \uc2e4\ud589\uc2dc\ud0a4\ub3c4\ub85d \ud574\uc900\ub2e4. \\n\ub2e4\uc74c\uacfc \uac19\uc774 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac01\uac01\uc758 \ud14c\uc774\ube14\uc5d0 \ud574\ub2f9\ud558\ub294 Truncate \ucffc\ub9ac\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc870\ud68c\ud558\uace0, Test \uba54\uc11c\ub4dc\uac00 \ub05d\ub0a0\ub54c \ub9c8\ub2e4 \ud574\ub2f9 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uc5ec \ud14c\uc774\ube14\uc744 \ucd08\uae30\ud654\uc2dc\ud0a4\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n```java title=DatabaseCleaner\\n\\npublic class DatabaseCleaner extends AbstractTestExecutionListener {\\n\\n private static final String TRUNCATE_TABLE_QUERY = \\"\\"\\"\\n SELECT Concat(\'TRUNCATE TABLE \', TABLE_NAME, \';\') \\n FROM INFORMATION_SCHEMA.TABLES\\n WHERE TABLE_SCHEMA = \'PUBLIC\'\\n \\"\\"\\";\\n\\n @Override\\n public void afterTestMethod(TestContext testContext) {\\n JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);\\n List truncateTableQueries = getTruncateTableQueries(jdbcTemplate);\\n truncateTables(jdbcTemplate, truncateTableQueries);\\n }\\n\\n private JdbcTemplate getJdbcTemplate(TestContext testContext) {\\n return testContext.getApplicationContext().getBean(JdbcTemplate.class);\\n }\\n\\n private List getTruncateTableQueries(JdbcTemplate jdbcTemplate) {\\n return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);\\n }\\n\\n private void truncateTables(JdbcTemplate jdbcTemplate, List truncateTableQueries) {\\n jdbcTemplate.execute(\\"SET REFERENTIAL_INTEGRITY FALSE\\");\\n truncateTableQueries.forEach(jdbcTemplate::execute);\\n jdbcTemplate.execute(\\"SET REFERENTIAL_INTEGRITY TRUE\\");\\n }\\n}\\n\\n```\\n\\n### Listener \ub4f1\ub85d\\n\\n@TestExecutionListeners\ub97c \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790 \uc815\uc758 \ub9ac\uc2a4\ub108\ub97c \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4. \\nmergeMode\uc758 \uae30\ubcf8\uac12\uc740 REPLACE_DEFAULTS\ub85c \ub9ac\uc2a4\ub108\uac00 \uc774\ubbf8 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \ub4f1\ub85d\ub41c \ub9ac\uc2a4\ub108\ub85c \ubcc0\uacbd\ub41c\ub2e4. \\nMERGE_WITH_DEFAULTS\ub85c \uc124\uc815\ud55c\ub2e4\uba74 Ordered \uae30\uc900\uc73c\ub85c \uc21c\uc11c\uac00 \uacb0\uc815\ub41c\ub2e4. \\n\uc774\ud6c4 \uaca9\ub9ac\uac00 \ud544\uc694\ud55c \ud14c\uc2a4\ud2b8\ub4e4\uc740 \ub2e4\uc74c\uc758 \ucd94\uc0c1 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ud558\uc5ec \uc0ac\uc6a9\ud558\uba74 \ub41c\ub2e4. \\n\\n```java title=AcceptanceTest\\n\\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\\n@TestExecutionListeners(\\n value = DatabaseCleaner.class,\\n mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS\\n)\\npublic abstract class AcceptanceTest {\\n\\n @LocalServerPort\\n private int port;\\n\\n @BeforeEach\\n public void setUp() {\\n RestAssured.port = port;\\n }\\n}\\n\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[The Spring TestExecutionListener, Baeldung](https://www.baeldung.com/spring-testexecutionlistener) \\n[\uc778\uc218\ud14c\uc2a4\ud2b8\uc5d0\uc11c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ud558\uae30, \ud14c\ucf54\ube14](https://tecoble.techcourse.co.kr/post/2020-09-15-test-isolation/) \\n[Eradicating Non-Determinism in Tests, martin fowler](https://martinfowler.com/articles/nonDeterminism.html) \\n[@SpringBootTest\uc758 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\uc2dc\ud0a4\uae30, MangKyu](https://mangkyu.tistory.com/264)"},{"id":"mvc-retrospective","metadata":{"permalink":"/mvc-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-mvc/pull/404","date":"2023-10-07T00:00:00.000Z","formattedDate":"2023\ub144 10\uc6d4 7\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.175,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","slug":"mvc-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","permalink":"/spring-test-isolation"},"nextItem":{"title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/jdbc-retrospective"}},"content":":::note PR \ub9c1\ud06c\\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465 \\n3\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580 \\n:::\\n\\n### MVC \uad6c\ud604\\n\\nReflection\uc744 \uc774\uc6a9\ud558\uc5ec Spring MVC\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ubbf8\uc158\uc758 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\uc558\ub2e4.\\n\\n- MVC \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uad6c\ud604\ud558\uba74\uc11c \ub0b4\ubd80 \ub3d9\uc791 \uc6d0\ub9ac\ub97c \ud559\uc2b5\ud55c\ub2e4.\\n- \uc810\uc9c4\uc801\uc778 \ub9ac\ud329\ud1a0\ub9c1\uc744 \uacbd\ud5d8\ud55c\ub2e4.\\n\\n\ubbf8\uc158\uc758 \ubaa9\ud45c\uc640 \ub354\ubd88\uc5b4 \uac01 \ud074\ub798\uc2a4\ub4e4\uc774 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \uc801\uc808\ud788 \uac00\uc9c0\ub3c4\ub85d \ud558\uace0, \ud328\ud0a4\uc9c0\uc758 \uc758\uc874 \ubc29\ud5a5\uc744 \uace0\ubbfc\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc5d0 \uc911\uc810\uc744 \ub450\uc5c8\ub2e4. \\n\\n### \uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30\\n\\n\uae30\uc874 \ucf54\ub4dc\uc5d0 ManualHandlerMapping\uc774\ub77c\ub294 \uc11c\ube14\ub9bf\uc744 \uc9c1\uc811 \ub4f1\ub85d\ud574\uc11c \uc0ac\uc6a9\ud558\ub294 HandlerMapping \ud074\ub798\uc2a4\uac00 \uc788\uc5c8\uace0, 1\ub2e8\uacc4\uc5d0\uc11c\ub294 \uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18\uc758 AnnotationHandlerMapping\uc744 \uad6c\ud604\ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 @Controller, @RequestMapping\uc744 Reflection\uc744 \uc774\uc6a9\ud558\uc5ec \uc2a4\uce94\ud558\uace0, \ud578\ub4e4\ub7ec \ub9e4\ud551\uc744 \ub4f1\ub85d\ud558\ub294 \ubd80\ubd84\uae4c\uc9c0 \uc9c4\ud589\ud574\uc57c \ud588\ub2e4. \\n\ud14c\uc624\uac00 @GetMapping\uc774\ub098 @PostMapping \ubd80\ubd84\ub3c4 \uc9c4\ud589\ud558\uba74 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4\uace0 \ud574\uc11c \uac19\uc774 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4. \\n\ucd94\uac00\ub85c \ubbf8\uc158 \uc694\uad6c\uc0ac\ud56d\uc740 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ud074\ub798\uc2a4 \ub808\ubca8\uc5d0 \uc801\uc6a9\ub41c @RequestMapping\ub3c4 \ub3d9\uc791\ud558\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\uc558\ub2e4. \\n\\n```mermaid\\ngraph LR\\n AHM[AnnotationHandlerMapping] --\x3e AS[AnnotationScanner]\\n\\tAHM --\x3e HKG[HandlerKeyGenerator] --\x3e HMAP[HttpMappingAnnotationParser]\\n```\\n\\n\ub2e4\uc74c\uacfc \uac19\uc740 Flow\ub85c Handler(\uc2e4\uc81c \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uba54\uc11c\ub4dc) \ub4f1\ub85d\uc744 \uc9c4\ud589\ud55c\ub2e4. \\n\\n1. @Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 \uc815\ubcf4\ub97c \uc2a4\uce94\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4. \\n2. @Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 @RequestMapping\uc774 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\ub4e4\uc758 \uc815\ubcf4\ub97c \ubc18\ud658\ud55c\ub2e4. \\n3. \uac01 \uba54\uc11c\ub4dc\ub4e4\uc744 \uc21c\ud68c\ud558\uba70 HandlerKey(uri + httpMethod \uc815\ubcf4)\uc640 HandlerExecution(\uc778\uc2a4\ud134\uc2a4 + \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc)\uc744 \uc0dd\uc131\ud558\uc5ec `Map`\uc5d0 \ucd94\uac00\ud55c\ub2e4. \\n\\nAnnotationHandlerMapping\uc758 initialize \uba54\uc11c\ub4dc\uc5d0\uc11c Handler\ub97c \ub4f1\ub85d\ud55c\ub2e4. \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```java title=AnnotationHandlerMapping\\npublic void initialize() {\\n if (!initialized.compareAndSet(false, true)) {\\n return;\\n }\\n\\n final Map, ControllerInstance> controllers = annotationScanner.scanControllers();\\n final Set methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());\\n for (final Method method : methods) {\\n final ControllerInstance controller = controllers.get(method.getDeclaringClass());\\n final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);\\n final List handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);\\n handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));\\n }\\n\\n log.info(\\"Initialized AnnotationHandlerMapping!\\");\\n handlerExecutions.keySet().forEach(key -> log.info(\\"key: {}, Handler: {}\\", key, handlerExecutions.get(key)));\\n}\\n```\\n\\n### Legacy MVC\uc640 @MVC \ud1b5\ud569\\n\\n2\ub2e8\uacc4\ub294 Legacy MVC\uc640 AnnotationHandlerMapping\uc744 \ud1b5\ud569\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4. \\n\uae30\uc874\uc758 MVC\uc640 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc801\uc6a9\ub41c MVC \ub450 \uac1c\ub97c \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5b4\uc57c \ud5c0\ub2e4. \\n\ub300\ub7b5\uc801\uc778 \ud750\ub984\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n1. DispatcherServlet.service(request, response) \ud638\ucd9c\\n2. HandlerMappings\ub97c \ud1b5\ud574 \uc785\ub825\ubc1b\uc740 request\uc5d0 \ud574\ub2f9\ud558\ub294 Handler \uc870\ud68c\\n3. HandlerAdapters\ub97c \ud1b5\ud574 Handler\ub97c \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub294 HandlerAdapter \uc870\ud68c\\n4. HandlerAdapter\uc758.handle \uba54\uc11c\ub4dc \uc2e4\ud589\\n5. View\uc758 render \ud638\ucd9c\\n\\n```mermaid\\ngraph LR\\n D[DispatcherServlet]\\n D --\x3e HMS[HandlerMappings]\\n D --\x3e HAS[HandlerAdapters]\\n\\n\\tHMS --\x3e HandlerMapping\\n\\tsubgraph HandlerMapping\\n\\t\\tdirection BT\\n\\t\\tAHM[AnnotationHandlerMapping] --\x3e HM[HandlerMapping]\\n\\t\\tMHM[ManualHandlerMapping] --\x3e HM\\n\\tend\\n\\n\\tHAS --\x3e HandlerAdapter\\n\\tsubgraph HandlerAdapter\\n\\t\\tdirection BT\\n\\t\\tHEHA[HandlerExecutionHandlerAdapter] --\x3e HA[HandlerAdapter]\\n\\t\\tCHA[ControllerHandlerAdapter] --\x3e HA\\n\\tend\\n```\\n\\n### \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815\\n\\n\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4. \\n\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4.\\n\\n```mermaid\\ngraph LR\\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking\\n```\\n\\n\ub0b4\uc6a9\uc774 \uae38\uc5b4\uc838\uc11c [\ub2e4\uc74c \ubb38\uc11c](./web-application-evolution)\uc5d0 \uc815\ub9ac\ud588\ub2e4.\\n\\n### \ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95\\n\\n\uc9c1\uad00\uc801\uc774\uc9c0 \uc54a\uc740 \ucd94\uc0c1\uc801\uc778 \uac1c\ub150\uc744 \ud559\uc2b5\ud560 \ub54c\ub294 \uac1c\ub150\uc758 \uad6c\ud604\uc744 \ucc38\uace0\ud558\uba74 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \ud55c\ub2e4.\\n\\n| \uac1c\ub150 | \uad6c\ud604 |\\n| ---- | ------------------------------------------------ |\\n| OOP | Java |\\n| WAS | Tomcat, Jetty |\\n| IoC | Spring BeanFactory, Servlet Container, Framework |\\n| DI | Spring BeanFactory |\\n\\n### \uc815\ub9ac\\n\\n\uc9c0\uae08\uae4c\uc9c0 \uc2a4\ud504\ub9c1\uc758 DispatcherServlet\uc758 \ub3d9\uc791\uc744 \uc774\ub860\uc801\uc73c\ub85c\ub9cc \uc54c\uace0 \uc788\uc5c8\ub294\ub370, \uc2e4\uc81c\ub85c \uad6c\ud604\ud574 \ubcf4\ub2c8 \uc870\uae08 \ub354 \uc774\ud574\uac00 \uc798 \uac00\ub294 \uac83 \uac19\ub2e4. \\n\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c \ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub8e8\uce74, \ub9ac\ubdf0\uc774\ub294 \ud5e4\ub098\uc600\ub2e4. \\n\ub9e4 \ub2e8\uacc4\ub9c8\ub2e4 \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0\ud574 \uc900 \ub8e8\uce74\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\uace0, \ud5e4\ub098\uc5d0\uac8c \uc774\uc0c1\ud55c \ub9ac\ubdf0\ub97c \ub9ce\uc774 \ub0a8\uae34 \uac83 \uac19\uc740\ub370 \uaf3c\uaf3c\ud788 \ubc18\uc601\ud574\uc918\uc11c \uac10\uc0ac\ud558\ub2e4. \\n\uc624\ub7ab\ub3d9\uc548 \uae30\ub2e4\ub824\uc654\ub358 \ub808\ubca8 4 \ubbf8\uc158\uc774 \ud558\ub098\uc529 \ub9c8\ubb34\ub9ac \ub420 \ub54c \ub9c8\ub2e4 \uc544\uc26c\uc6c0\uc774 \ub0a8\ub294\ub2e4."},{"id":"jdbc-retrospective","metadata":{"permalink":"/jdbc-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-jdbc/pull/267","date":"2023-10-10T00:00:00.000Z","formattedDate":"2023\ub144 10\uc6d4 10\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.83,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","slug":"jdbc-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/mvc-retrospective"},"nextItem":{"title":"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0","permalink":"/refactoring-retrospective"}},"content":":::note PR \ub9c1\ud06c\\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358 \\n3\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448 \\n4\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515 \\n:::\\n\\n### Jdbc \uad6c\ud604\\n\\n\uc774\ubc88 \ubbf8\uc158\uc740 Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uace0, Transaction \uacbd\uacc4 \uc124\uc815\uacfc \ub3d9\uae30\ud654\ud558\ub294 \ubd80\ubd84\uc744 \uad6c\ud604\ud574 \ubcf4\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ubbf8\uc158 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n- JDBC \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uba74\uc11c \uc911\ubcf5\uc744 \uc81c\uac70\ud558\ub294 \uc5f0\uc2b5\uc744 \ud55c\ub2e4.\\n- \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\ub97c \ub192\uc778\ub2e4.\\n\\n\ucd5c\ub300\ud55c Java\uac00 \uc81c\uacf5\ud558\ub294 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud588\ub2e4. \\n\\n### JdbcTemplate\\n\\nJdbcTemplate\uc740 Connection\uc744 \uc774\uc6a9\ud558\uc5ec PreparedStatement\ub97c \uc0dd\uc131\ud558\ub294 \ubd80\ubd84, \uadf8\ub9ac\uace0 PreparedStatement\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ubd84\ub9ac\ud588\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc801\uc808\ud558\uac8c \uc801\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \ube44\uad50\uc801 \uac04\ub2e8\ud558\uac8c \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\uc608\uc804\uc5d0\ub3c4 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c [JdbcTemplate\uc744 \uad6c\ud604](./custom-jdbc-template)\ud55c \uc801\uc774 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \uc790\uc6d0 \ud560\ub2f9\uacfc \ud574\uc81c \ubd80\ubd84\uc5d0 \ub300\ud55c \uc911\ubcf5\ub3c4 \uc81c\uac70\ud588\ub2e4. \\n\\n```java\\npublic class JdbcTemplate {\\n\\n private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);\\n\\n private final DataSource dataSource;\\n private final StatementCreator statementCreator;\\n private final StatementExecutor statementExecutor;\\n\\n public JdbcTemplate(final DataSource dataSource) {\\n this(dataSource, new StatementCreator(), new StatementExecutor());\\n }\\n\\n JdbcTemplate(\\n final DataSource dataSource,\\n final StatementCreator statementCreator,\\n final StatementExecutor statementExecutor\\n ) {\\n this.dataSource = dataSource;\\n this.statementCreator = statementCreator;\\n this.statementExecutor = statementExecutor;\\n }\\n\\n private T query(\\n final String sql,\\n final PreparedStatementCallback preparedStatementCallback,\\n final Object... parameters\\n ) {\\n final Connection connection = DataSourceUtils.getConnection(dataSource);\\n try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {\\n return preparedStatementCallback.execute(preparedStatement);\\n } catch (final SQLException e) {\\n log.error(e.getMessage(), e);\\n throw new DataAccessException(e);\\n } finally {\\n DataSourceUtils.releaseConnection(connection, dataSource);\\n }\\n }\\n\\n public void update(final String sql, final Object... parameters) {\\n query(sql, PreparedStatement::executeUpdate, parameters);\\n }\\n\\n public Optional queryForObject(final String sql, final RowMapper rowMapper, final Object... parameters) {\\n final List results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\\n if (results.size() > 1) {\\n throw new DataAccessException(\\"2\uac1c \uc774\uc0c1\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\");\\n }\\n return results.stream().findAny();\\n }\\n\\n public List queryForList(final String sql, final RowMapper rowMapper, final Object... parameters) {\\n return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\\n }\\n}\\n```\\n\\n### \ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9\\n\\n3, 4\ub2e8\uacc4\ub294 \uae30\uc874\uc758 \ucf54\ub4dc\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uace0 \ub05d\ub098\ub294 \ubd80\ubd84\uc778 \ud2b8\ub79c\uc7ad\uc158 \uacbd\uacc4\ub97c \uc124\uc815\ud558\uace0 ThreadLocal\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654(Transaction synchronization)\ub97c \uc801\uc6a9\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654\ub780 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uae30 \uc704\ud55c Connection \uac1d\uccb4\ub97c ThreadLocal\uacfc \uac19\uc740 \uacf5\uac04\uc5d0 \ub530\ub85c \uc800\uc7a5 \ud6c4, \ud544\uc694\ud560 \ub54c \uc800\uc7a5\ub41c Connection\uc744 \uac00\uc838\ub2e4 \uc0ac\uc6a9\ud558\ub294 \ubc29\uc2dd\uc774\ub2e4. \\n\uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub294\ub370, ThreadLocal\uc5d0 Connection \uac1d\uccb4\uac00 \uc544\ub2cc, Connection \uac1d\uccb4\uc640 Transaction\uc774 \uc9c4\ud589 \uc911\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 flag\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \uc800\uc7a5\ud574\uc11c \uc0ac\uc6a9\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tTransactionTemplate --\x3e TransactionManager\\n\\tTransactionManager --\x3e TransactionSynchronizationManager\\n\\tDataSourceUtils --\x3e TransactionSynchronizationManager\\n\\tJdbcTemplate --\x3e DataSourceUtils\\n```\\n\\n### \ub9c8\ubb34\ub9ac\\n\\nJdbc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c AOP\ub098 Transactional\uc5d0 \ub300\ud55c \ud559\uc2b5 \ud14c\uc2a4\ud2b8\ub3c4 \uc9c4\ud589\ud558\uace0, \uc57d\uac04 \uc54c\ucc2c \ubbf8\uc158\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\uaf3c\uaf3c\ud788 \ucf54\ub4dc\ub97c \ubd10\uc900 \ub9ac\ubdf0\uc5b4 \ud638\uc774 \uadf8\ub9ac\uace0 \uc5f0\ud734 \ub3d9\uc548 \uacc4\uc18d \ud2f0\ud0a4\ud0c0\uce74 \ud558\uba74\uc11c \uc7ac\ubc0c\uac8c \ub9ac\ubdf0\ud55c \ubbfc\ud2b8\uc5d0\uac8c \uac10\uc0ac\ud558\ub2e4. \\n\ud68c\uace0 \uc774\ub9cc \ub05d\ub0b4\uace0 \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud558\ub7ec\uac00\uc57c\uaca0\ub2e4. \ud83d\ude0a"},{"id":"refactoring-retrospective","metadata":{"permalink":"/refactoring-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-refactoring/pull/465","date":"2023-10-31T00:00:00.000Z","formattedDate":"2023\ub144 10\uc6d4 31\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":8.095,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0","slug":"refactoring-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/jdbc-retrospective"}},"content":":::note PR \ub9c1\ud06c\\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-refactoring/pull/465 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-refactoring/pull/547 \\n3\ub2e8\uacc4: https://github.com/woowacourse/jwp-refactoring/pull/610 \\n4\ub2e8\uacc4: https://github.com/woowacourse/jwp-refactoring/pull/721 \\n:::\\n\\n### \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158\\n\\n\uc694\uad6c\uc0ac\ud56d \uc791\uc131 \u2192 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud55c \ucf54\ub4dc \ubcf4\ud638 \u2192 \ub9ac\ud329\ud130\ub9c1 \u2192 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1 \u2192 \uba40\ud2f0\ubaa8\ub4c8 \uc21c\uc11c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\ubbf8\uc158\uc5d0 \uc628\uc804\ud788 \uc9d1\uc911\ud558\uace0 \uc2f6\uc5c8\uc9c0\ub9cc, \ud504\ub85c\uc81d\ud2b8\uc640 \ubcd1\ud589\ud558\uba74\uc11c \uc9c4\ud589\ud588\uae30\uc5d0 \uc5b4\ub290\uc815\ub3c4 \ud0c0\ud611\ubcf4\uace0 \uc9c4\ud589\ud55c \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c \uc544\uc26c\uc6e0\ub2e4. \\n\\n### 1, 2\ub2e8\uacc4\\n\\n1\ub2e8\uacc4\ub294 \uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud558\uace0, \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ucd94\ud6c4\uc5d0 \ub9ac\ud329\ud130\ub9c1 \ud560 \ub54c \uc548\uc815\uac10 \uc788\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\ub3c4\ub85d \uc900\ube44\ud558\ub294 \uacfc\uc815\uc774\uc5c8\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud560 \ub54c \uc81c\uacf5\ub41c \uc6a9\uc5b4 \uc0ac\uc804\uc744 \ucd5c\ub300\ud55c \ud65c\uc6a9\ud558\uba74\uc11c \uae30\uc874\uc758 \ucf54\ub4dc\ub97c \ubcf4\uba74\uc11c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud588\ub2e4. \\n\ud14c\uc2a4\ud2b8\ub294 \uc2dc\uac04 \uad00\uacc4\uc0c1 API, \uc11c\ube44\uc2a4 \ub458 \uc911 \ud558\ub098\ub9cc \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4. \\n\\n\ucd5c\uc885\uc801\uc73c\ub85c \uc11c\ube44\uc2a4 \uae30\uc900\uc73c\ub85c \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud588\ub294\ub370 \uc57d\uac04 \ud6c4\ud68c\ub418\ub294 \uacb0\uc815\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ub9ac\ud329\ud130\ub9c1 \uacfc\uc815\uc5d0\uc11c API \uba85\uc138\uac00 \ubc14\ub00c\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4\ub294 \uac83\uc744 \uae30\uc900\uc744 \uc7a1\uace0 \uc774\ubc88 \ubbf8\uc158\uc744 \ud55c\ub2e4\uace0 \uac00\uc815\ud588\uc744 \ub54c API \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\uace0, \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ub354 \uc548\uc815\uac10 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n2\ub2e8\uacc4\ub294 \uc791\uc131\ub41c \ud14c\uc2a4\ud2b8 \uae30\ubc18\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\uc11c\ube44\uc2a4\uc5d0\uc11c \ub3c4\uba54\uc778\uc744 \uc9c1\uc811 \ubc18\ud658\ud558\ub294 \uad6c\uc870\uc600\ub294\ub370, \ub3c4\uba54\uc778\uc5d0 JPA\ub97c \uc801\uc6a9\ud558\uba74 \uae30\uc874 \uba85\uc138\uc640 \ub2ec\ub77c\uc9c8 \uac83\uc744 \uc6b0\ub824\ud574\uc11c DTO\ub85c \uc218\uc815\ud558\ub294 \uc791\uc5c5\uc744 \uba3c\uc800 \uc9c4\ud589\ud588\ub2e4. \\nDTO \uc774\ud6c4\uc5d0 \uc11c\ube44\uc2a4\uc5d0 \uc788\ub294 \ub85c\uc9c1\uc744 \ub3c4\uba54\uc778\uc73c\ub85c \uc774\ub3d9\uc2dc\ud0a4\uace0, \ucd5c\uc885\uc801\uc73c\ub85c JPA\ub97c \uc801\uc6a9\ud558\ub294 \uc21c\uc11c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\uc774 \uacfc\uc815\uc5d0\uc11c \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \uc591\ubc29\ud5a5\uc778 \ubd80\ubd84\ub3c4 \uc0dd\uaca8\ub0ac\ub2e4. \\n\\n### \uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\\n\\n\uc911\uac04\uc5d0 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\uc5d0 \uad00\ud55c \uc81c\uc774\uc2a8\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4. \\n\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\ub294 \uc5d0\ub9ad \uc5d0\ubc18\uc2a4\uc758 \uc800\uc11c `\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4`\uc758 \ubd80\uc81c\uc774\ub2e4. \\n\\n\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\ub294 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4, \uc804\uc220\uc801 \uc124\uacc4\uac00 \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4. \\n\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4\uac00 \uc804\uccb4\uc758 90%\uc5d0 \ud574\ub2f9\ud560 \uc815\ub3c4\ub85c \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4. \ub610\ud55c \uc804\uc220\uc801 \uc124\uacc4\ub9cc \ud558\ub294 \uacbd\uc6b0\ub97c DDD Lite \ub77c\uace0 \ud55c\ub2e4. \\n\\n\uac04\ub2e8\ud788 \ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\uc5d0\uc11c \ub098\uc624\ub294 \ub2e8\uc5b4\ub97c \uc815\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n| \ub2e8\uc5b4 | \uc124\uba85 |\\n| --- | --- |\\n| \ub3c4\uba54\uc778 | \uc18c\ud504\ud2b8\uc6e8\uc5b4\ub85c \ud574\uacb0\ud558\uace0\uc790 \ud558\ub294 \ubb38\uc81c \uc601\uc5ed |\\n| \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8 | \ud574\uacb0 \uc601\uc5ed, \uad00\uc2ec\uc0ac\ub97c \ubd84\ub9ac\ud558\uace0 \uaca9\ub9ac\ud558\uc5ec \ubb38\uc81c \ud574\uacb0\uc5d0 \uc9d1\uc911\ud560 \ubc94\uc704 |\\n| \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4 | \ud504\ub85c\uc81d\ud2b8\uc5d0 \uc774\ud574\uad00\uacc4\uc790\ub4e4\uc758 \uacf5\ud1b5\ub41c \uc5b8\uc5b4\ub85c, \uc11c\ub85c\uc758 \uc758\uc0ac\uc18c\ud1b5 \ube44\uc6a9\uc744 \uc904\uc774\uae30 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 \uc5b8\uc5b4 |\\n| \uc804\ub7b5\uc801 \uc124\uacc4 | \ub3c4\uba54\uc778 \uc804\ubb38\uac00\uc640 \uac1c\ubc1c\uc790\uac00 \ud568\uaed8 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec \ub3c4\uba54\uc778\uacfc \uad00\ub828\ub41c \uc9c0\uc2dd\uc744 \uc774\ud574\ud558\uace0 \uc774\ub97c \ubc14\ud0d5\uc73c\ub85c \uacbd\uacc4\ub97c \ub098\ub220 \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc815\uc758\ud558\uace0, \ucee8\ud14d\uc2a4\ud2b8 \ub9f5\uc744 \uc0dd\uc131\ud558\ub294 \uac83\uc744 \ud3ec\ud568\ud558\ub294 \uacfc\uc815 |\\n| \uc804\uc220\uc801 \uc124\uacc4 | \uc804\ub7b5\uc801 \uc124\uacc4\uc5d0\uc11c \uc815\uc758\ud55c \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\uc640 \ub3c4\uba54\uc778\uc744 \uc774\uc6a9\ud558\uc5ec \uc560\uadf8\ub9ac\uac70\ud2b8, Entity\uc640 VO, Repository \ub4f1\uc744 \uad6c\ud604\ud558\ub294 \uacfc\uc815 |\\n\\n\uc774 \uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ub0b4\uc6a9\ub4e4\uc774 \ub098\uc654\uc9c0\ub9cc, \uc9c0\uc2dd\uc744 \uc81c\ub300\ub85c \ud761\uc218\ud558\uc9c0\ub294 \ubabb\ud588\ub2e4. \\n\\n### 3, 4\ub2e8\uacc4\\n\\n\uc81c\uc774\uc2a8\uc758 \uac15\uc758\ub97c \ub4e3\uace0, \uc870\uc601\ud638\ub2d8\uc758 \uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5 \uc720\ud29c\ube0c \uc601\uc0c1\uc744 \ubcf8 \ub2e4\uc74c 3, 4\ub2e8\uacc4\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\\n3\ub2e8\uacc4\ub294 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1\uc5d0 \uad00\ud55c \ub0b4\uc6a9\uc774\uc5c8\ub2e4. \ud074\ub798\uc2a4 \uac04 \ubc29\ud5a5, \ud328\ud0a4\uc9c0 \uac04 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc774 \ub418\ub3c4\ub85d \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud574\uc57c \ud588\uc5c8\ub2e4. \\n\ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4\ub4e4\uc744 \ubb36\uace0, \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uae30 \uc704\ud574 \uc0dd\uba85\uc8fc\uae30\uac00 \ub2e4\ub974\ub2e4\uba74 id\ub97c \uc774\uc6a9\ud558\uc5ec \ucc38\uc870\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4. \\n\\n\uc758\uc874\uc131\uc744 \ubd84\ub9ac\ud558\uae30 \uc704\ud574 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4. \uc774\ubca4\ud2b8\ub294 \ud604\uc7ac \uae30\uc900\uc73c\ub85c \uacfc\uac70\uc5d0 \ubc8c\uc5b4\uc9c4 \uac83\uc744 \ud45c\ud604\ud558\uae30 \ub54c\ubb38\uc5d0 \uc774\ubca4\ud2b8\uba85\uc740 \uacfc\uac70 \uc2dc\uc81c\uac00 \ub418\uc5b4\uc57c\ud558\ub294 \uac83\uc744 \uc54c\uc558\ub2e4. \\n\ucc98\uc74c\uc5d0\ub294 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud588\uc9c0\ub9cc, \uc11c\ube44\uc2a4 \ub85c\uc9c1\uc744 \ucd5c\ub300\ud55c \uac04\ub2e8\ud558\uac8c \ud558\uae30 \uc704\ud574 \ub3c4\uba54\uc778 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4. \\n\\n4\ub2e8\uacc4\ub294 \uba40\ud2f0\ubaa8\ub4c8\ub85c \ubd84\ub9ac\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub294\ub370 3\ub2e8\uacc4\uc5d0\uc11c \ubd84\ub9ac\ud574\ub454 \ud328\ud0a4\uc9c0 \uadf8\ub300\ub85c \ubd84\ub9ac\ud558\uc9c0\ub294 \uc54a\uc558\ub2e4. \\n3\ub2e8\uacc4\uc5d0\uc11c\ub294 \ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4 \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ud588\ub2e4. 4\ub2e8\uacc4\uc5d0\uc11c\ub294 \ub0b4\uac00 \uc778\uc2dd\ud558\uae30 \ud3b8\ud55c \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ub97c \ud588\ub2e4. \\n\uc544\uc9c1 \ubd84\ub9ac\ud55c \uae30\uc900\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \ubaa8\ud638\ud588\uace0, \uc774\uc5d0 \ub300\ud55c \uacf5\ubd80\ub97c \uc870\uae08 \ub354 \ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph Table\\n\\t\\tOrderTable --\x3e TableGroup\\n\\tend\\n\\tsubgraph Order\\n\\t\\tO\\n\\tend\\n O[Order] --\x3e OrderTable\\n\\tsubgraph Menu\\n\\t\\tM[Menu] --\x3e MenuGroup\\n\\t\\tM --\x3e Product\\n\\tend\\n\\tO --\x3e M\\n```\\n\\n\ucd94\uac00\ub85c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc704\ud55c \uc9c1\uc811 \uc791\uc131\ud55c `@ServiceTest` \ucee4\uc2a4\ud140 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc788\uc5c8\ub294\ub370, \uc0c1\uc704 \ubaa8\ub4c8\uc758 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \ub9cc\ub4e0 \ud074\ub798\uc2a4\ub97c \ud558\uc704 \ubaa8\ub4c8\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c TestFixtures\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\uacb0\ud588\ub2e4. \\n\\n### \ub9c8\ubb34\ub9ac\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc758 \ub9c8\uc9c0\ub9c9 \ubbf8\uc158\uc774\ub2c8 \ub9cc\ud07c, \uac00\uc7a5 \ud765\ubbf8\ub85c\uc6b4 \ubbf8\uc158\uc774\uc5c8\uace0 \ubc30\uc6b8\uc810\ub3c4 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4. \\n\ubc14\uc05c \uae30\uac04\uc774\ub77c \ub9ce\uc740 \ub9ac\ubdf0\ub97c \ub0a8\uae30\uc9c0 \ubabb\ud588\ub358 \ub9ac\ubdf0\uc774 \ud638\uc774\uc5d0\uac8c \ubbf8\uc548\ud558\uace0, \ucf54\uba58\ud2b8 \uaf3c\uaf3c\ud558\uac8c \ub2ec\uc544\uc8fc\uace0 \ubbf8\uc158\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub3c4 \uc624\ud504\ub77c\uc778\uc73c\ub85c \ub9ce\uc774 \ub098\ub208 \ub9ac\ubdf0\uc5b4 \ud14c\uc624\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4. \\n\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[\ub3c4\uba54\uc778 \uc6d0\uc815\ub300, \uc6b0\uc544\ucf58 2021](https://www.youtube.com/watch?v=kmUneexSxk0) \\n[\uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5, \uc6b0\uc544\ud55c\ud14c\ud06c\uc138\ubbf8\ub098](https://www.youtube.com/watch?v=dJ5C4qRqAgA) \\n[TestFixtures, \uad8c\ub0a8\ub2d8](https://kwonnam.pe.kr/wiki/gradle/testfixtures)"}]}')}}]); \ No newline at end of file diff --git a/assets/js/b2b675dd.adafc1ef.js b/assets/js/b2b675dd.adafc1ef.js deleted file mode 100644 index 13ac40959..000000000 --- a/assets/js/b2b675dd.adafc1ef.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[533],{28017:n=>{n.exports=JSON.parse('{"blogPosts":[{"id":"refactoring-retrospective","metadata":{"permalink":"/refactoring-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-refactoring/pull/465","date":"2023-10-31T00:00:00.000Z","formattedDate":"2023\ub144 10\uc6d4 31\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":8.095,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0","slug":"refactoring-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"nextItem":{"title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/jdbc-retrospective"}},"content":":::note PR \ub9c1\ud06c\\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-refactoring/pull/465 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-refactoring/pull/547 \\n3\ub2e8\uacc4: https://github.com/woowacourse/jwp-refactoring/pull/610 \\n4\ub2e8\uacc4: https://github.com/woowacourse/jwp-refactoring/pull/721 \\n:::\\n\\n### \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158\\n\\n\uc694\uad6c\uc0ac\ud56d \uc791\uc131 \u2192 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud55c \ucf54\ub4dc \ubcf4\ud638 \u2192 \ub9ac\ud329\ud130\ub9c1 \u2192 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1 \u2192 \uba40\ud2f0\ubaa8\ub4c8 \uc21c\uc11c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\ubbf8\uc158\uc5d0 \uc628\uc804\ud788 \uc9d1\uc911\ud558\uace0 \uc2f6\uc5c8\uc9c0\ub9cc, \ud504\ub85c\uc81d\ud2b8\uc640 \ubcd1\ud589\ud558\uba74\uc11c \uc9c4\ud589\ud588\uae30\uc5d0 \uc5b4\ub290\uc815\ub3c4 \ud0c0\ud611\ubcf4\uace0 \uc9c4\ud589\ud55c \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c \uc544\uc26c\uc6e0\ub2e4. \\n\\n### 1, 2\ub2e8\uacc4\\n\\n1\ub2e8\uacc4\ub294 \uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud558\uace0, \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ucd94\ud6c4\uc5d0 \ub9ac\ud329\ud130\ub9c1 \ud560 \ub54c \uc548\uc815\uac10 \uc788\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\ub3c4\ub85d \uc900\ube44\ud558\ub294 \uacfc\uc815\uc774\uc5c8\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d\uc744 \uc791\uc131\ud560 \ub54c \uc81c\uacf5\ub41c \uc6a9\uc5b4 \uc0ac\uc804\uc744 \ucd5c\ub300\ud55c \ud65c\uc6a9\ud558\uba74\uc11c \uae30\uc874\uc758 \ucf54\ub4dc\ub97c \ubcf4\uba74\uc11c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud588\ub2e4. \\n\ud14c\uc2a4\ud2b8\ub294 \uc2dc\uac04 \uad00\uacc4\uc0c1 API, \uc11c\ube44\uc2a4 \ub458 \uc911 \ud558\ub098\ub9cc \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4. \\n\\n\ucd5c\uc885\uc801\uc73c\ub85c \uc11c\ube44\uc2a4 \uae30\uc900\uc73c\ub85c \ud1b5\ud569 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud588\ub294\ub370 \uc57d\uac04 \ud6c4\ud68c\ub418\ub294 \uacb0\uc815\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ub9ac\ud329\ud130\ub9c1 \uacfc\uc815\uc5d0\uc11c API \uba85\uc138\uac00 \ubc14\ub00c\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4\ub294 \uac83\uc744 \uae30\uc900\uc744 \uc7a1\uace0 \uc774\ubc88 \ubbf8\uc158\uc744 \ud55c\ub2e4\uace0 \uac00\uc815\ud588\uc744 \ub54c API \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\uace0, \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ub354 \uc548\uc815\uac10 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n2\ub2e8\uacc4\ub294 \uc791\uc131\ub41c \ud14c\uc2a4\ud2b8 \uae30\ubc18\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\uc11c\ube44\uc2a4\uc5d0\uc11c \ub3c4\uba54\uc778\uc744 \uc9c1\uc811 \ubc18\ud658\ud558\ub294 \uad6c\uc870\uc600\ub294\ub370, \ub3c4\uba54\uc778\uc5d0 JPA\ub97c \uc801\uc6a9\ud558\uba74 \uae30\uc874 \uba85\uc138\uc640 \ub2ec\ub77c\uc9c8 \uac83\uc744 \uc6b0\ub824\ud574\uc11c DTO\ub85c \uc218\uc815\ud558\ub294 \uc791\uc5c5\uc744 \uba3c\uc800 \uc9c4\ud589\ud588\ub2e4. \\nDTO \uc774\ud6c4\uc5d0 \uc11c\ube44\uc2a4\uc5d0 \uc788\ub294 \ub85c\uc9c1\uc744 \ub3c4\uba54\uc778\uc73c\ub85c \uc774\ub3d9\uc2dc\ud0a4\uace0, \ucd5c\uc885\uc801\uc73c\ub85c JPA\ub97c \uc801\uc6a9\ud558\ub294 \uc21c\uc11c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\uc774 \uacfc\uc815\uc5d0\uc11c \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \uc591\ubc29\ud5a5\uc778 \ubd80\ubd84\ub3c4 \uc0dd\uaca8\ub0ac\ub2e4. \\n\\n### \uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\\n\\n\uc911\uac04\uc5d0 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\uc5d0 \uad00\ud55c \uc81c\uc774\uc2a8\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4. \\n\uc18c\ud504\ud2b8\uc6e8\uc5b4\uc758 \ubcf5\uc7a1\uc131\uc744 \ub2e4\ub8e8\ub294 \uc9c0\ud61c\ub294 \uc5d0\ub9ad \uc5d0\ubc18\uc2a4\uc758 \uc800\uc11c `\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4`\uc758 \ubd80\uc81c\uc774\ub2e4. \\n\\n\ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\ub294 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4, \uc804\uc220\uc801 \uc124\uacc4\uac00 \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4. \\n\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4, \uc804\ub7b5\uc801 \uc124\uacc4\uac00 \uc804\uccb4\uc758 90%\uc5d0 \ud574\ub2f9\ud560 \uc815\ub3c4\ub85c \uc911\uc694\ud558\ub2e4\uace0 \ud55c\ub2e4. \ub610\ud55c \uc804\uc220\uc801 \uc124\uacc4\ub9cc \ud558\ub294 \uacbd\uc6b0\ub97c DDD Lite \ub77c\uace0 \ud55c\ub2e4. \\n\\n\uac04\ub2e8\ud788 \ub3c4\uba54\uc778 \uc8fc\ub3c4 \uc124\uacc4\uc5d0\uc11c \ub098\uc624\ub294 \ub2e8\uc5b4\ub97c \uc815\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n| \ub2e8\uc5b4 | \uc124\uba85 |\\n| --- | --- |\\n| \ub3c4\uba54\uc778 | \uc18c\ud504\ud2b8\uc6e8\uc5b4\ub85c \ud574\uacb0\ud558\uace0\uc790 \ud558\ub294 \ubb38\uc81c \uc601\uc5ed |\\n| \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8 | \ud574\uacb0 \uc601\uc5ed, \uad00\uc2ec\uc0ac\ub97c \ubd84\ub9ac\ud558\uace0 \uaca9\ub9ac\ud558\uc5ec \ubb38\uc81c \ud574\uacb0\uc5d0 \uc9d1\uc911\ud560 \ubc94\uc704 |\\n| \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4 | \ud504\ub85c\uc81d\ud2b8\uc5d0 \uc774\ud574\uad00\uacc4\uc790\ub4e4\uc758 \uacf5\ud1b5\ub41c \uc5b8\uc5b4\ub85c, \uc11c\ub85c\uc758 \uc758\uc0ac\uc18c\ud1b5 \ube44\uc6a9\uc744 \uc904\uc774\uae30 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 \uc5b8\uc5b4 |\\n| \uc804\ub7b5\uc801 \uc124\uacc4 | \ub3c4\uba54\uc778 \uc804\ubb38\uac00\uc640 \uac1c\ubc1c\uc790\uac00 \ud568\uaed8 \uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec \ub3c4\uba54\uc778\uacfc \uad00\ub828\ub41c \uc9c0\uc2dd\uc744 \uc774\ud574\ud558\uace0 \uc774\ub97c \ubc14\ud0d5\uc73c\ub85c \uacbd\uacc4\ub97c \ub098\ub220 \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc815\uc758\ud558\uace0, \ucee8\ud14d\uc2a4\ud2b8 \ub9f5\uc744 \uc0dd\uc131\ud558\ub294 \uac83\uc744 \ud3ec\ud568\ud558\ub294 \uacfc\uc815 |\\n| \uc804\uc220\uc801 \uc124\uacc4 | \uc804\ub7b5\uc801 \uc124\uacc4\uc5d0\uc11c \uc815\uc758\ud55c \ubc14\uc6b4\ub514\ub4dc \ucee8\ud14d\uc2a4\ud2b8\uc640 \ub3c4\uba54\uc778\uc744 \uc774\uc6a9\ud558\uc5ec \uc560\uadf8\ub9ac\uac70\ud2b8, Entity\uc640 VO, Repository \ub4f1\uc744 \uad6c\ud604\ud558\ub294 \uacfc\uc815 |\\n\\n\uc774 \uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ub0b4\uc6a9\ub4e4\uc774 \ub098\uc654\uc9c0\ub9cc, \uc9c0\uc2dd\uc744 \uc81c\ub300\ub85c \ud761\uc218\ud558\uc9c0\ub294 \ubabb\ud588\ub2e4. \\n\\n### 3, 4\ub2e8\uacc4\\n\\n\uc81c\uc774\uc2a8\uc758 \uac15\uc758\ub97c \ub4e3\uace0, \uc870\uc601\ud638\ub2d8\uc758 \uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5 \uc720\ud29c\ube0c \uc601\uc0c1\uc744 \ubcf8 \ub2e4\uc74c 3, 4\ub2e8\uacc4\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\\n3\ub2e8\uacc4\ub294 \uc758\uc874\uc131 \ub9ac\ud329\ud130\ub9c1\uc5d0 \uad00\ud55c \ub0b4\uc6a9\uc774\uc5c8\ub2e4. \ud074\ub798\uc2a4 \uac04 \ubc29\ud5a5, \ud328\ud0a4\uc9c0 \uac04 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc774 \ub418\ub3c4\ub85d \ub9ac\ud329\ud130\ub9c1\uc744 \uc9c4\ud589\ud574\uc57c \ud588\uc5c8\ub2e4. \\n\ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4\ub4e4\uc744 \ubb36\uace0, \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uae30 \uc704\ud574 \uc0dd\uba85\uc8fc\uae30\uac00 \ub2e4\ub974\ub2e4\uba74 id\ub97c \uc774\uc6a9\ud558\uc5ec \ucc38\uc870\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4. \\n\\n\uc758\uc874\uc131\uc744 \ubd84\ub9ac\ud558\uae30 \uc704\ud574 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4. \uc774\ubca4\ud2b8\ub294 \ud604\uc7ac \uae30\uc900\uc73c\ub85c \uacfc\uac70\uc5d0 \ubc8c\uc5b4\uc9c4 \uac83\uc744 \ud45c\ud604\ud558\uae30 \ub54c\ubb38\uc5d0 \uc774\ubca4\ud2b8\uba85\uc740 \uacfc\uac70 \uc2dc\uc81c\uac00 \ub418\uc5b4\uc57c\ud558\ub294 \uac83\uc744 \uc54c\uc558\ub2e4. \\n\ucc98\uc74c\uc5d0\ub294 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud588\uc9c0\ub9cc, \uc11c\ube44\uc2a4 \ub85c\uc9c1\uc744 \ucd5c\ub300\ud55c \uac04\ub2e8\ud558\uac8c \ud558\uae30 \uc704\ud574 \ub3c4\uba54\uc778 \uc774\ubca4\ud2b8\ub3c4 \uc0ac\uc6a9\ud574\ubcf4\uc558\ub2e4. \\n\\n4\ub2e8\uacc4\ub294 \uba40\ud2f0\ubaa8\ub4c8\ub85c \ubd84\ub9ac\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub294\ub370 3\ub2e8\uacc4\uc5d0\uc11c \ubd84\ub9ac\ud574\ub454 \ud328\ud0a4\uc9c0 \uadf8\ub300\ub85c \ubd84\ub9ac\ud558\uc9c0\ub294 \uc54a\uc558\ub2e4. \\n3\ub2e8\uacc4\uc5d0\uc11c\ub294 \ud568\uaed8 \uc0dd\uc131\ub418\uace0 \uc0ad\uc81c\ub418\ub294 \uac1d\uccb4 \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ud588\ub2e4. 4\ub2e8\uacc4\uc5d0\uc11c\ub294 \ub0b4\uac00 \uc778\uc2dd\ud558\uae30 \ud3b8\ud55c \uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ub97c \ud588\ub2e4. \\n\uc544\uc9c1 \ubd84\ub9ac\ud55c \uae30\uc900\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \ubaa8\ud638\ud588\uace0, \uc774\uc5d0 \ub300\ud55c \uacf5\ubd80\ub97c \uc870\uae08 \ub354 \ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph Table\\n\\t\\tOrderTable --\x3e TableGroup\\n\\tend\\n\\tsubgraph Order\\n\\t\\tO\\n\\tend\\n O[Order] --\x3e OrderTable\\n\\tsubgraph Menu\\n\\t\\tM[Menu] --\x3e MenuGroup\\n\\t\\tM --\x3e Product\\n\\tend\\n\\tO --\x3e M\\n```\\n\\n\ucd94\uac00\ub85c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc704\ud55c \uc9c1\uc811 \uc791\uc131\ud55c `@ServiceTest` \ucee4\uc2a4\ud140 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc788\uc5c8\ub294\ub370, \uc0c1\uc704 \ubaa8\ub4c8\uc758 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \ub9cc\ub4e0 \ud074\ub798\uc2a4\ub97c \ud558\uc704 \ubaa8\ub4c8\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c TestFixtures\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\uacb0\ud588\ub2e4. \\n\\n### \ub9c8\ubb34\ub9ac\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc758 \ub9c8\uc9c0\ub9c9 \ubbf8\uc158\uc774\ub2c8 \ub9cc\ud07c, \uac00\uc7a5 \ud765\ubbf8\ub85c\uc6b4 \ubbf8\uc158\uc774\uc5c8\uace0 \ubc30\uc6b8\uc810\ub3c4 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4. \\n\ubc14\uc05c \uae30\uac04\uc774\ub77c \ub9ce\uc740 \ub9ac\ubdf0\ub97c \ub0a8\uae30\uc9c0 \ubabb\ud588\ub358 \ub9ac\ubdf0\uc774 \ud638\uc774\uc5d0\uac8c \ubbf8\uc548\ud558\uace0, \ucf54\uba58\ud2b8 \uaf3c\uaf3c\ud558\uac8c \ub2ec\uc544\uc8fc\uace0 \ubbf8\uc158\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub3c4 \uc624\ud504\ub77c\uc778\uc73c\ub85c \ub9ce\uc774 \ub098\ub208 \ub9ac\ubdf0\uc5b4 \ud14c\uc624\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4. \\n\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[\ub3c4\uba54\uc778 \uc6d0\uc815\ub300, \uc6b0\uc544\ucf58 2021](https://www.youtube.com/watch?v=kmUneexSxk0) \\n[\uc6b0\uc544\ud55c\uac1d\uccb4\uc9c0\ud5a5, \uc6b0\uc544\ud55c\ud14c\ud06c\uc138\ubbf8\ub098](https://www.youtube.com/watch?v=dJ5C4qRqAgA) \\n[TestFixtures, \uad8c\ub0a8\ub2d8](https://kwonnam.pe.kr/wiki/gradle/testfixtures)"},{"id":"jdbc-retrospective","metadata":{"permalink":"/jdbc-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-jdbc/pull/267","date":"2023-10-10T00:00:00.000Z","formattedDate":"2023\ub144 10\uc6d4 10\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.83,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","slug":"jdbc-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0","permalink":"/refactoring-retrospective"},"nextItem":{"title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/mvc-retrospective"}},"content":":::note PR \ub9c1\ud06c\\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358 \\n3\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448 \\n4\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515 \\n:::\\n\\n### Jdbc \uad6c\ud604\\n\\n\uc774\ubc88 \ubbf8\uc158\uc740 Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uace0, Transaction \uacbd\uacc4 \uc124\uc815\uacfc \ub3d9\uae30\ud654\ud558\ub294 \ubd80\ubd84\uc744 \uad6c\ud604\ud574 \ubcf4\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ubbf8\uc158 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n- JDBC \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uba74\uc11c \uc911\ubcf5\uc744 \uc81c\uac70\ud558\ub294 \uc5f0\uc2b5\uc744 \ud55c\ub2e4.\\n- \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\ub97c \ub192\uc778\ub2e4.\\n\\n\ucd5c\ub300\ud55c Java\uac00 \uc81c\uacf5\ud558\ub294 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud588\ub2e4. \\n\\n### JdbcTemplate\\n\\nJdbcTemplate\uc740 Connection\uc744 \uc774\uc6a9\ud558\uc5ec PreparedStatement\ub97c \uc0dd\uc131\ud558\ub294 \ubd80\ubd84, \uadf8\ub9ac\uace0 PreparedStatement\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ubd84\ub9ac\ud588\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc801\uc808\ud558\uac8c \uc801\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \ube44\uad50\uc801 \uac04\ub2e8\ud558\uac8c \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\uc608\uc804\uc5d0\ub3c4 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c [JdbcTemplate\uc744 \uad6c\ud604](./custom-jdbc-template)\ud55c \uc801\uc774 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \uc790\uc6d0 \ud560\ub2f9\uacfc \ud574\uc81c \ubd80\ubd84\uc5d0 \ub300\ud55c \uc911\ubcf5\ub3c4 \uc81c\uac70\ud588\ub2e4. \\n\\n```java\\npublic class JdbcTemplate {\\n\\n private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);\\n\\n private final DataSource dataSource;\\n private final StatementCreator statementCreator;\\n private final StatementExecutor statementExecutor;\\n\\n public JdbcTemplate(final DataSource dataSource) {\\n this(dataSource, new StatementCreator(), new StatementExecutor());\\n }\\n\\n JdbcTemplate(\\n final DataSource dataSource,\\n final StatementCreator statementCreator,\\n final StatementExecutor statementExecutor\\n ) {\\n this.dataSource = dataSource;\\n this.statementCreator = statementCreator;\\n this.statementExecutor = statementExecutor;\\n }\\n\\n private T query(\\n final String sql,\\n final PreparedStatementCallback preparedStatementCallback,\\n final Object... parameters\\n ) {\\n final Connection connection = DataSourceUtils.getConnection(dataSource);\\n try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {\\n return preparedStatementCallback.execute(preparedStatement);\\n } catch (final SQLException e) {\\n log.error(e.getMessage(), e);\\n throw new DataAccessException(e);\\n } finally {\\n DataSourceUtils.releaseConnection(connection, dataSource);\\n }\\n }\\n\\n public void update(final String sql, final Object... parameters) {\\n query(sql, PreparedStatement::executeUpdate, parameters);\\n }\\n\\n public Optional queryForObject(final String sql, final RowMapper rowMapper, final Object... parameters) {\\n final List results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\\n if (results.size() > 1) {\\n throw new DataAccessException(\\"2\uac1c \uc774\uc0c1\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\");\\n }\\n return results.stream().findAny();\\n }\\n\\n public List queryForList(final String sql, final RowMapper rowMapper, final Object... parameters) {\\n return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\\n }\\n}\\n```\\n\\n### \ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9\\n\\n3, 4\ub2e8\uacc4\ub294 \uae30\uc874\uc758 \ucf54\ub4dc\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uace0 \ub05d\ub098\ub294 \ubd80\ubd84\uc778 \ud2b8\ub79c\uc7ad\uc158 \uacbd\uacc4\ub97c \uc124\uc815\ud558\uace0 ThreadLocal\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654(Transaction synchronization)\ub97c \uc801\uc6a9\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654\ub780 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uae30 \uc704\ud55c Connection \uac1d\uccb4\ub97c ThreadLocal\uacfc \uac19\uc740 \uacf5\uac04\uc5d0 \ub530\ub85c \uc800\uc7a5 \ud6c4, \ud544\uc694\ud560 \ub54c \uc800\uc7a5\ub41c Connection\uc744 \uac00\uc838\ub2e4 \uc0ac\uc6a9\ud558\ub294 \ubc29\uc2dd\uc774\ub2e4. \\n\uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub294\ub370, ThreadLocal\uc5d0 Connection \uac1d\uccb4\uac00 \uc544\ub2cc, Connection \uac1d\uccb4\uc640 Transaction\uc774 \uc9c4\ud589 \uc911\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 flag\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \uc800\uc7a5\ud574\uc11c \uc0ac\uc6a9\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tTransactionTemplate --\x3e TransactionManager\\n\\tTransactionManager --\x3e TransactionSynchronizationManager\\n\\tDataSourceUtils --\x3e TransactionSynchronizationManager\\n\\tJdbcTemplate --\x3e DataSourceUtils\\n```\\n\\n### \ub9c8\ubb34\ub9ac\\n\\nJdbc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c AOP\ub098 Transactional\uc5d0 \ub300\ud55c \ud559\uc2b5 \ud14c\uc2a4\ud2b8\ub3c4 \uc9c4\ud589\ud558\uace0, \uc57d\uac04 \uc54c\ucc2c \ubbf8\uc158\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\uaf3c\uaf3c\ud788 \ucf54\ub4dc\ub97c \ubd10\uc900 \ub9ac\ubdf0\uc5b4 \ud638\uc774 \uadf8\ub9ac\uace0 \uc5f0\ud734 \ub3d9\uc548 \uacc4\uc18d \ud2f0\ud0a4\ud0c0\uce74 \ud558\uba74\uc11c \uc7ac\ubc0c\uac8c \ub9ac\ubdf0\ud55c \ubbfc\ud2b8\uc5d0\uac8c \uac10\uc0ac\ud558\ub2e4. \\n\ud68c\uace0 \uc774\ub9cc \ub05d\ub0b4\uace0 \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud558\ub7ec\uac00\uc57c\uaca0\ub2e4. \ud83d\ude0a"},{"id":"mvc-retrospective","metadata":{"permalink":"/mvc-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-mvc/pull/404","date":"2023-10-07T00:00:00.000Z","formattedDate":"2023\ub144 10\uc6d4 7\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.175,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","slug":"mvc-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/jdbc-retrospective"},"nextItem":{"title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","permalink":"/spring-test-isolation"}},"content":":::note PR \ub9c1\ud06c\\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465 \\n3\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580 \\n:::\\n\\n### MVC \uad6c\ud604\\n\\nReflection\uc744 \uc774\uc6a9\ud558\uc5ec Spring MVC\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ubbf8\uc158\uc758 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\uc558\ub2e4.\\n\\n- MVC \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uad6c\ud604\ud558\uba74\uc11c \ub0b4\ubd80 \ub3d9\uc791 \uc6d0\ub9ac\ub97c \ud559\uc2b5\ud55c\ub2e4.\\n- \uc810\uc9c4\uc801\uc778 \ub9ac\ud329\ud1a0\ub9c1\uc744 \uacbd\ud5d8\ud55c\ub2e4.\\n\\n\ubbf8\uc158\uc758 \ubaa9\ud45c\uc640 \ub354\ubd88\uc5b4 \uac01 \ud074\ub798\uc2a4\ub4e4\uc774 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \uc801\uc808\ud788 \uac00\uc9c0\ub3c4\ub85d \ud558\uace0, \ud328\ud0a4\uc9c0\uc758 \uc758\uc874 \ubc29\ud5a5\uc744 \uace0\ubbfc\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac83\uc5d0 \uc911\uc810\uc744 \ub450\uc5c8\ub2e4. \\n\\n### \uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c \ub9cc\ub4e4\uae30\\n\\n\uae30\uc874 \ucf54\ub4dc\uc5d0 ManualHandlerMapping\uc774\ub77c\ub294 \uc11c\ube14\ub9bf\uc744 \uc9c1\uc811 \ub4f1\ub85d\ud574\uc11c \uc0ac\uc6a9\ud558\ub294 HandlerMapping \ud074\ub798\uc2a4\uac00 \uc788\uc5c8\uace0, 1\ub2e8\uacc4\uc5d0\uc11c\ub294 \uc560\ub108\ud14c\uc774\uc158 \uae30\ubc18\uc758 AnnotationHandlerMapping\uc744 \uad6c\ud604\ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 @Controller, @RequestMapping\uc744 Reflection\uc744 \uc774\uc6a9\ud558\uc5ec \uc2a4\uce94\ud558\uace0, \ud578\ub4e4\ub7ec \ub9e4\ud551\uc744 \ub4f1\ub85d\ud558\ub294 \ubd80\ubd84\uae4c\uc9c0 \uc9c4\ud589\ud574\uc57c \ud588\ub2e4. \\n\ud14c\uc624\uac00 @GetMapping\uc774\ub098 @PostMapping \ubd80\ubd84\ub3c4 \uc9c4\ud589\ud558\uba74 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4\uace0 \ud574\uc11c \uac19\uc774 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4. \\n\ucd94\uac00\ub85c \ubbf8\uc158 \uc694\uad6c\uc0ac\ud56d\uc740 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ud074\ub798\uc2a4 \ub808\ubca8\uc5d0 \uc801\uc6a9\ub41c @RequestMapping\ub3c4 \ub3d9\uc791\ud558\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\uc558\ub2e4. \\n\\n```mermaid\\ngraph LR\\n AHM[AnnotationHandlerMapping] --\x3e AS[AnnotationScanner]\\n\\tAHM --\x3e HKG[HandlerKeyGenerator] --\x3e HMAP[HttpMappingAnnotationParser]\\n```\\n\\n\ub2e4\uc74c\uacfc \uac19\uc740 Flow\ub85c Handler(\uc2e4\uc81c \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uba54\uc11c\ub4dc) \ub4f1\ub85d\uc744 \uc9c4\ud589\ud55c\ub2e4. \\n\\n1. @Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 \uc815\ubcf4\ub97c \uc2a4\uce94\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4. \\n2. @Controller\uac00 \uc801\uc6a9\ub41c \ud074\ub798\uc2a4\uc758 @RequestMapping\uc774 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\ub4e4\uc758 \uc815\ubcf4\ub97c \ubc18\ud658\ud55c\ub2e4. \\n3. \uac01 \uba54\uc11c\ub4dc\ub4e4\uc744 \uc21c\ud68c\ud558\uba70 HandlerKey(uri + httpMethod \uc815\ubcf4)\uc640 HandlerExecution(\uc778\uc2a4\ud134\uc2a4 + \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc)\uc744 \uc0dd\uc131\ud558\uc5ec `Map`\uc5d0 \ucd94\uac00\ud55c\ub2e4. \\n\\nAnnotationHandlerMapping\uc758 initialize \uba54\uc11c\ub4dc\uc5d0\uc11c Handler\ub97c \ub4f1\ub85d\ud55c\ub2e4. \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```java title=AnnotationHandlerMapping\\npublic void initialize() {\\n if (!initialized.compareAndSet(false, true)) {\\n return;\\n }\\n\\n final Map, ControllerInstance> controllers = annotationScanner.scanControllers();\\n final Set methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());\\n for (final Method method : methods) {\\n final ControllerInstance controller = controllers.get(method.getDeclaringClass());\\n final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);\\n final List handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);\\n handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));\\n }\\n\\n log.info(\\"Initialized AnnotationHandlerMapping!\\");\\n handlerExecutions.keySet().forEach(key -> log.info(\\"key: {}, Handler: {}\\", key, handlerExecutions.get(key)));\\n}\\n```\\n\\n### Legacy MVC\uc640 @MVC \ud1b5\ud569\\n\\n2\ub2e8\uacc4\ub294 Legacy MVC\uc640 AnnotationHandlerMapping\uc744 \ud1b5\ud569\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4. \\n\uae30\uc874\uc758 MVC\uc640 \uc560\ub108\ud14c\uc774\uc158\uc774 \uc801\uc6a9\ub41c MVC \ub450 \uac1c\ub97c \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5b4\uc57c \ud5c0\ub2e4. \\n\ub300\ub7b5\uc801\uc778 \ud750\ub984\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n1. DispatcherServlet.service(request, response) \ud638\ucd9c\\n2. HandlerMappings\ub97c \ud1b5\ud574 \uc785\ub825\ubc1b\uc740 request\uc5d0 \ud574\ub2f9\ud558\ub294 Handler \uc870\ud68c\\n3. HandlerAdapters\ub97c \ud1b5\ud574 Handler\ub97c \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub294 HandlerAdapter \uc870\ud68c\\n4. HandlerAdapter\uc758.handle \uba54\uc11c\ub4dc \uc2e4\ud589\\n5. View\uc758 render \ud638\ucd9c\\n\\n```mermaid\\ngraph LR\\n D[DispatcherServlet]\\n D --\x3e HMS[HandlerMappings]\\n D --\x3e HAS[HandlerAdapters]\\n\\n\\tHMS --\x3e HandlerMapping\\n\\tsubgraph HandlerMapping\\n\\t\\tdirection BT\\n\\t\\tAHM[AnnotationHandlerMapping] --\x3e HM[HandlerMapping]\\n\\t\\tMHM[ManualHandlerMapping] --\x3e HM\\n\\tend\\n\\n\\tHAS --\x3e HandlerAdapter\\n\\tsubgraph HandlerAdapter\\n\\t\\tdirection BT\\n\\t\\tHEHA[HandlerExecutionHandlerAdapter] --\x3e HA[HandlerAdapter]\\n\\t\\tCHA[ControllerHandlerAdapter] --\x3e HA\\n\\tend\\n```\\n\\n### \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815\\n\\n\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4. \\n\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4.\\n\\n```mermaid\\ngraph LR\\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking\\n```\\n\\n\ub0b4\uc6a9\uc774 \uae38\uc5b4\uc838\uc11c [\ub2e4\uc74c \ubb38\uc11c](./web-application-evolution)\uc5d0 \uc815\ub9ac\ud588\ub2e4.\\n\\n### \ucd94\uc0c1\uc801\uc778 \uac1c\ub150 \ud559\uc2b5 \ubc29\ubc95\\n\\n\uc9c1\uad00\uc801\uc774\uc9c0 \uc54a\uc740 \ucd94\uc0c1\uc801\uc778 \uac1c\ub150\uc744 \ud559\uc2b5\ud560 \ub54c\ub294 \uac1c\ub150\uc758 \uad6c\ud604\uc744 \ucc38\uace0\ud558\uba74 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \ud55c\ub2e4.\\n\\n| \uac1c\ub150 | \uad6c\ud604 |\\n| ---- | ------------------------------------------------ |\\n| OOP | Java |\\n| WAS | Tomcat, Jetty |\\n| IoC | Spring BeanFactory, Servlet Container, Framework |\\n| DI | Spring BeanFactory |\\n\\n### \uc815\ub9ac\\n\\n\uc9c0\uae08\uae4c\uc9c0 \uc2a4\ud504\ub9c1\uc758 DispatcherServlet\uc758 \ub3d9\uc791\uc744 \uc774\ub860\uc801\uc73c\ub85c\ub9cc \uc54c\uace0 \uc788\uc5c8\ub294\ub370, \uc2e4\uc81c\ub85c \uad6c\ud604\ud574 \ubcf4\ub2c8 \uc870\uae08 \ub354 \uc774\ud574\uac00 \uc798 \uac00\ub294 \uac83 \uac19\ub2e4. \\n\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c \ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub8e8\uce74, \ub9ac\ubdf0\uc774\ub294 \ud5e4\ub098\uc600\ub2e4. \\n\ub9e4 \ub2e8\uacc4\ub9c8\ub2e4 \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0\ud574 \uc900 \ub8e8\uce74\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\uace0, \ud5e4\ub098\uc5d0\uac8c \uc774\uc0c1\ud55c \ub9ac\ubdf0\ub97c \ub9ce\uc774 \ub0a8\uae34 \uac83 \uac19\uc740\ub370 \uaf3c\uaf3c\ud788 \ubc18\uc601\ud574\uc918\uc11c \uac10\uc0ac\ud558\ub2e4. \\n\uc624\ub7ab\ub3d9\uc548 \uae30\ub2e4\ub824\uc654\ub358 \ub808\ubca8 4 \ubbf8\uc158\uc774 \ud558\ub098\uc529 \ub9c8\ubb34\ub9ac \ub420 \ub54c \ub9c8\ub2e4 \uc544\uc26c\uc6c0\uc774 \ub0a8\ub294\ub2e4."},{"id":"spring-test-isolation","metadata":{"permalink":"/spring-test-isolation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md","source":"@site/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md","title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","description":"\ud14c\uc2a4\ud2b8 \uaca9\ub9ac","date":"2023-10-03T00:00:00.000Z","formattedDate":"2023\ub144 10\uc6d4 3\uc77c","tags":[{"label":"test","permalink":"/tags/test"}],"readingTime":4.315,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","slug":"spring-test-isolation","tags":["test"]},"unlisted":false,"prevItem":{"title":"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/mvc-retrospective"},"nextItem":{"title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","permalink":"/web-application-evolution"}},"content":"### \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\\n\\n\ud14c\uc2a4\ud2b8\uc758 \uc21c\uc11c\uc5d0 \ub530\ub77c \uc131\uacf5 \uc2e4\ud328 \uc5ec\ubd80\uac00 \uacb0\uc815\ub418\ub294 \ube44\uacb0\uc815\uc801\uc778(non-determinism) \ud14c\uc2a4\ud2b8\uac00 \ub418\uc5b4\uc11c\ub294 \uc548\ub418\uace0, \ud14c\uc2a4\ud2b8\ub294 \ud56d\uc0c1 \uc21c\uc11c\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc218\ud589\ub418\ub3c4\ub85d \ubcf4\uc7a5\ub418\uc5b4\uc57c \ud55c\ub2e4. \uc77c\ubc18\uc801\uc73c\ub85c \uc790\uc6d0\uc758 \uacf5\uc720, \uc678\ubd80 API, \uc2dc\uac04 \ub4f1\uc73c\ub85c \ube44\uacb0\uc815\uc801\uc778 \ud14c\uc2a4\ud2b8\uac00 \ub41c\ub2e4. \uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \uc0ac\uc6a9\ud558\uac70\ub098, \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc7ac\uc2e4\ud589\ud558\ub294 `@DirtiesContext`, \uc790\uc6d0\uc744 \ucd08\uae30\ud654\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uc774\ud6c4\uc5d0 \ud14c\uc774\ube14\uc744 \ub864\ubc31 \ud558\ub294 `@Transactional`\ub4f1 \ub2e4\uc591\ud55c \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\ud574\ub2f9 \uae00\uc5d0\uc11c\ub294 \uc2a4\ud504\ub9c1\uc5d0\uc11c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc790\uc6d0\uc758 \uacf5\uc720\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud574 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ub97c \uc218\ud589\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc124\uba85\ud55c\ub2e4. \\n\\n:::note Independent - FIRST\\n\\n\ud14c\uc2a4\ud2b8\ub07c\ub9ac \uc11c\ub85c \uc758\uc874\ud558\uba74 \uc548 \ub41c\ub2e4. \\n\uc11c\ub85c \uc758\uc874\ud558\uac8c \ub41c\ub2e4\uba74 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \ub54c, \ub610 \ub2e4\ub978 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud14c\uc2a4\ud2b8\uac00 \uc88b\uc740 \ud14c\uc2a4\ud2b8\ub2e4. \\n\\n:::\\n\\n### TestExecutionListener\\n\\n\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 TextExecutionListner\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 \ud14c\uc2a4\ud2b8 \uc2e4\ud589 \ub2e8\uacc4\uc5d0\uc11c \uc774\ubca4\ud2b8\ub97c \uc218\uc2e0\ud560 \uc218 \uc788\ub2e4. \\n\uc774\ub97c \uc774\uc6a9\ud558\uba74 JUnit\uc758 @BeforeEach\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uacfc \uc720\uc0ac\ud558\uac8c, \ud14c\uc2a4\ud2b8\uc758 \uc0dd\uba85\uc8fc\uae30 \uc774\uc804 \ub610\ub294 \uc774\ud6c4\uc5d0 \ud544\uc694\ud55c \uc791\uc5c5\uc744 \uc2e4\ud589\uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\\n```java title=TextExecutionListner\\npublic interface TestExecutionListener {\\n default void beforeTestClass(TestContext testContext) throws Exception {}\\n default void prepareTestInstance(TestContext testContext) throws Exception {}\\n default void beforeTestMethod(TestContext testContext) throws Exception {}\\n default void beforeTestExecution(TestContext testContext) throws Exception {}\\n default void afterTestExecution(TestContext testContext) throws Exception {}\\n default void afterTestMethod(TestContext testContext) throws Exception {}\\n default void afterTestClass(TestContext testContext) throws Exception {}\\n}\\n```\\n\\n### AbstractTestExecutionListener \uc0c1\uc18d\ud558\uc5ec \uad6c\ud604\\n\\nAbstractTestExecutionListener\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac \ud658\uacbd\uc744 \ub9cc\ub4e4\uc5b4\uc8fc\ub294 \ud074\ub798\uc2a4\ub85c, \uc778\ud130\ud398\uc774\uc2a4\uc778 TextExecutionListner\uc640 \ub2ec\ub9ac Ordered\uac00 \uad6c\ud604\ub418\uc5b4 \uc788\uc5b4 \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ubc1b\uc544 \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub294 \ud504\ub808\uc784\uc6cc\ud06c\uac00 \uc81c\uacf5\ud558\ub294 \ub9ac\uc2a4\ub108 \ub2e4\uc74c\uc5d0 \uc2e4\ud589\uc2dc\ud0a4\ub3c4\ub85d \ud574\uc900\ub2e4. \\n\ub2e4\uc74c\uacfc \uac19\uc774 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac01\uac01\uc758 \ud14c\uc774\ube14\uc5d0 \ud574\ub2f9\ud558\ub294 Truncate \ucffc\ub9ac\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc870\ud68c\ud558\uace0, Test \uba54\uc11c\ub4dc\uac00 \ub05d\ub0a0\ub54c \ub9c8\ub2e4 \ud574\ub2f9 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uc5ec \ud14c\uc774\ube14\uc744 \ucd08\uae30\ud654\uc2dc\ud0a4\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n```java title=DatabaseCleaner\\n\\npublic class DatabaseCleaner extends AbstractTestExecutionListener {\\n\\n private static final String TRUNCATE_TABLE_QUERY = \\"\\"\\"\\n SELECT Concat(\'TRUNCATE TABLE \', TABLE_NAME, \';\') \\n FROM INFORMATION_SCHEMA.TABLES\\n WHERE TABLE_SCHEMA = \'PUBLIC\'\\n \\"\\"\\";\\n\\n @Override\\n public void afterTestMethod(TestContext testContext) {\\n JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);\\n List truncateTableQueries = getTruncateTableQueries(jdbcTemplate);\\n truncateTables(jdbcTemplate, truncateTableQueries);\\n }\\n\\n private JdbcTemplate getJdbcTemplate(TestContext testContext) {\\n return testContext.getApplicationContext().getBean(JdbcTemplate.class);\\n }\\n\\n private List getTruncateTableQueries(JdbcTemplate jdbcTemplate) {\\n return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);\\n }\\n\\n private void truncateTables(JdbcTemplate jdbcTemplate, List truncateTableQueries) {\\n jdbcTemplate.execute(\\"SET REFERENTIAL_INTEGRITY FALSE\\");\\n truncateTableQueries.forEach(jdbcTemplate::execute);\\n jdbcTemplate.execute(\\"SET REFERENTIAL_INTEGRITY TRUE\\");\\n }\\n}\\n\\n```\\n\\n### Listener \ub4f1\ub85d\\n\\n@TestExecutionListeners\ub97c \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790 \uc815\uc758 \ub9ac\uc2a4\ub108\ub97c \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4. \\nmergeMode\uc758 \uae30\ubcf8\uac12\uc740 REPLACE_DEFAULTS\ub85c \ub9ac\uc2a4\ub108\uac00 \uc774\ubbf8 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \ub4f1\ub85d\ub41c \ub9ac\uc2a4\ub108\ub85c \ubcc0\uacbd\ub41c\ub2e4. \\nMERGE_WITH_DEFAULTS\ub85c \uc124\uc815\ud55c\ub2e4\uba74 Ordered \uae30\uc900\uc73c\ub85c \uc21c\uc11c\uac00 \uacb0\uc815\ub41c\ub2e4. \\n\uc774\ud6c4 \uaca9\ub9ac\uac00 \ud544\uc694\ud55c \ud14c\uc2a4\ud2b8\ub4e4\uc740 \ub2e4\uc74c\uc758 \ucd94\uc0c1 \ud074\ub798\uc2a4\ub97c \uc0c1\uc18d\ud558\uc5ec \uc0ac\uc6a9\ud558\uba74 \ub41c\ub2e4. \\n\\n```java title=AcceptanceTest\\n\\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\\n@TestExecutionListeners(\\n value = DatabaseCleaner.class,\\n mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS\\n)\\npublic abstract class AcceptanceTest {\\n\\n @LocalServerPort\\n private int port;\\n\\n @BeforeEach\\n public void setUp() {\\n RestAssured.port = port;\\n }\\n}\\n\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[The Spring TestExecutionListener, Baeldung](https://www.baeldung.com/spring-testexecutionlistener) \\n[\uc778\uc218\ud14c\uc2a4\ud2b8\uc5d0\uc11c \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\ud558\uae30, \ud14c\ucf54\ube14](https://tecoble.techcourse.co.kr/post/2020-09-15-test-isolation/) \\n[Eradicating Non-Determinism in Tests, martin fowler](https://martinfowler.com/articles/nonDeterminism.html) \\n[@SpringBootTest\uc758 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac\uc2dc\ud0a4\uae30, MangKyu](https://mangkyu.tistory.com/264)"},{"id":"web-application-evolution","metadata":{"permalink":"/web-application-evolution","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx","source":"@site/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx","title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","description":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","date":"2023-09-30T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 30\uc77c","tags":[{"label":"web application","permalink":"/tags/web-application"}],"readingTime":7.5,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","slug":"web-application-evolution","tags":["web application"]},"unlisted":false,"prevItem":{"title":"\uc2a4\ud504\ub9c1 \ud14c\uc2a4\ud2b8 \uaca9\ub9ac","permalink":"/spring-test-isolation"},"nextItem":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","permalink":"/log-async-exception"}},"content":"### \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815\\n\\n\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815 \ub300\ud55c \uad6c\uad6c\uc758 \uac15\uc758\uac00 \uc788\uc5c8\ub2e4. \\n\uac04\ub2e8\ud558\uac8c \uc815\ub9ac\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ud750\ub984\uc73c\ub85c \uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ubc1c\uc804\ud588\ub2e4. \\n\uc6d0\ub798 \ud68c\uace0\uc5d0 \uc791\uc131\ud558\ub824\uace0 \ud588\uc9c0\ub9cc, \uc815\ub9ac\ud558\ub2e4 \ubcf4\ub2c8 \uc870\uae08 \uae38\uc5b4\uc838\uc11c \ub530\ub85c \ubd84\ub9ac\ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n WWW --\x3e CGI(Common Gateway Interface) --\x3e Servlet --\x3e JSP --\x3e MVC --\x3e Framework --\x3e Non-Blocking\\n```\\n\\n### WWW(1989)\\n\\n\uc815\uc801 \ud398\uc774\uc9c0\ub97c \uc81c\uacf5\ud558\ub294 \uc6f9 \uc11c\ubc84\ub97c \uc2dc\uc791\uc73c\ub85c \ub3d9\uc801 \ud398\uc774\uc9c0\uac00 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 CGI\uac00 \ub4f1\uc7a5\ud588\ub2e4. \\n\\n### CGI(1993) \\n\\nCGI\ub294 \ub3d9\uc801 \ucf58\ud150\uce20\ub97c \uc81c\uacf5\ud558\uae30 \uc704\ud55c \uaddc\uc57d\uc73c\ub85c, \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc774\uc6a9\ud574\uc11c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ucf1c \uc815\ubcf4\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ub9ce\uc740 \ubd80\ud558\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc774\ub7ec\ud55c \ub2e8\uc810\uc744 \uadf9\ubcf5\ud558\uae30 \uc704\ud574 \ub098\uc628 \uac83\uc774 Servlet\uc774\ub2e4. \\n\\n### Servlet(1996)\\n\\nServlet\uc740 \uc6f9 \uc11c\ubc84\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uc790\ubc14 \ud504\ub85c\uadf8\ub7a8\uc73c\ub85c HTTP\ub97c \uc774\uc6a9\ud558\uc5ec \uc6f9 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc744 \uc218\uc2e0\ud558\uace0 \uc751\ub2f5\ud55c\ub2e4. CGI\uc640 \ub2e4\ub974\uac8c \ub9e4 \uc694\uccad\ub9c8\ub2e4 \ud504\ub85c\uc138\uc2a4\uac00 \uc544\ub2cc \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uc5ec \uc751\ub2f5\ud55c\ub2e4. \\n\ud558\uc9c0\ub9cc View \uc601\uc5ed\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uae30 \uc704\ud574 Servlet\uc758 \uc18c\uc2a4 \ucf54\ub4dc\ub97c \uc54c\uc544\uc57c \ud558\ub294 \ub4f1 \ubcf5\uc7a1\ub3c4\uac00 \ub108\ubb34 \ub192\uc558\ub2e4. \ub530\ub77c\uc11c \ud574\ub2f9 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 JSP\uac00 \ub4f1\uc7a5\ud588\ub2e4. \\n\\n### JSP(1999)\\n\\nJSP\ub294 HTML\uc5d0 \uc790\ubc14 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \ub3d9\uc801 \uc6f9 \ud398\uc774\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\uc220\ub85c, \uc720\uc0ac\ud55c \uae30\uc220\ub85c\ub294 ASP, PHP\uac00 \uc788\ub2e4. \\nJSP\ub9cc \uc0ac\uc6a9\ud558\uc5ec \ud504\ub85c\uadf8\ub798\ubc0d\ud55c\ub2e4\uba74 Model 1, \uc544\ub798 \uad6c\uc131\ub3c4\uc640 \uac19\uc774 JSP\uac00 View \uc601\uc5ed\ub9cc \ub2f4\ub2f9\ud55c\ub2e4\uba74 Model 2\ub77c\uace0 \ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: JSP Model 2\\n---\\ngraph LR\\n Client -- Request --\x3e Servlet <-- JDBC --\x3e Database\\n\\tServlet --\x3e Bean\\n\\tServlet --\x3e JSP\\n\\tBean <--\x3e JSP\\n\\tJSP -- Response --\x3e Client\\n```\\n\\n### MVC(2000)\\n\\n\uc704 JSP\uc758 \uad6c\uc131\ub3c4\ub97c \ubcf4\uba74 \ud604\uc7ac MVC\uc640 \ub9e4\uc6b0 \uc720\uc0ac\ud55c\ub370, Govind Seshadri\ub77c\ub294 \uc0ac\ub78c\uc774 JSP Model 2\ub97c MVC \ud328\ud134\uc73c\ub85c \uacf5\uc2dd\ud654\ub97c \uc81c\uc548\ud588\ub2e4. \\n\\n> I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern. \\n> Govind Seshadri\\n\\n\uc774\ub54c MVC \ud328\ud134\uc774 \ucc98\uc74c \ud0c4\uc0dd\ud55c \uac83\uc740 \uc544\ub2c8\uace0, \uc11c\ubc84 \uce21 \uad6c\ud604\uc774\ub77c\uace0 \ud558\ub294 \uac83\uc744 \ubcf4\ub2c8 MVC\uac00 \ucc98\uc74c \ub4f1\uc7a5\ud55c \uac74 \uc544\ub2cc \uac83 \uac19\ub2e4. \\n[\ud574\ub2f9 \ubb38\uc11c](https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html)\ub97c \ubcf4\uba74 MVC\ub77c\ub294 \uc6a9\uc5b4\uc758 \ub4f1\uc7a5\uc740 1978\ub144\uc5d0 \ub4f1\uc7a5\ud55c \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4. \\n\\n### Spring Framework(2003)\\n\\nSpring\uc740 \ubcf5\uc7a1\ud588\ub358 J2EE\uc744 \ub300\uccb4\ud558\uae30 \uc704\ud574 2003\ub144\uc5d0 \ub4f1\uc7a5\ud588\ub2e4. \\nJ2EE\ub294 \uc6f9 \uae30\ubc18\uc758 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\uae30 \uc704\ud55c \ud50c\ub7ab\ud3fc\uc73c\ub85c \uc704\uc5d0\uc11c \uc124\uba85\ud55c Servlet, JSP, EJB \ub4f1\uc758 \uae30\uc220\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \uc774\uc911 EJB\ub77c\ub294 \uae30\uc220\uc774 J2EE\uc758 \ud575\uc2ec \uae30\uc220\uc774\uc5c8\ub294\ub370, \ud574\ub2f9 \uae30\uc220\uc774 \ub9e4\uc6b0 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub9ce\uc558\ub2e4\uace0 \ud55c\ub2e4. \\n2002\ub144\uc5d0 Rod Johnson\uc774 EJB\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 J2EE \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc800\uc220\ud55c `Expert One-to-One J2EE Development`\ub77c\ub294 \ucc45\uc744 \ubc1c\ud589\ud588\uace0, \ucd9c\uac04 \ud6c4 Juergen Hoeller, Yann Caroff\uac00 Rod Johnson\uc5d0\uac8c \uc624\ud508\uc18c\uc2a4 \uc81c\uc548\uc744 \ud558\uc5ec \uc2a4\ud504\ub9c1\uc774 \ud0c4\uc0dd\ud588\ub2e4\uace0 \ud55c\ub2e4. \\n\\n\uc2a4\ud504\ub9c1\uc740 \uc5d4\ud130\ud504\ub77c\uc774\uc988 \uc11c\ube44\uc2a4 \uae30\ub2a5\uc744 POJO\uc5d0 \uc81c\uacf5\ud558\uba70, \uc774 \ub355\ubd84\uc5d0 \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\ub2e4. \\n\\n### WebFlux \uc774\uc804 Servlet 3.0(2009), 3.1(2013)\\n\\nTomcat\uc758 NIO \ub3d9\uc791 \ubc29\uc2dd\uc744 \ubcf4\uba74 Poller\uac00 \uc18c\ucf13 \ucee4\ub125\uc158\uc744 \ub4e4\uace0 \uc788\ub2e4\uac00 \ucc98\ub9ac\uac00 \uac00\ub2a5\ud560 \ub54c \uc2a4\ub808\ub4dc\ub97c \ud560\ub2f9\ud558\ub294 \uc2dd\uc73c\ub85c \ucc98\ub9ac\ub97c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ud560\ub2f9 \ud6c4 Servlet\uacfc \ud1b5\uc2e0\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \uc694\uccad\uc774 \ub05d\ub0a0 \ub54c\uae4c\uc9c0 \uc2a4\ub808\ub4dc\ub97c \uc810\uc720\ud558\uace0 \uc788\uc5c8\uace0, \uc2a4\ub808\ub4dc \uc810\uc720\ub85c \uc778\ud574 \uc694\uccad\uc774 max thread\uc5d0 \ub3c4\ub2ec\ud558\uba74 \uc694\uccad\uc744 \ucc98\ub9ac\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uadf8\ub798\uc11c \ube44\ub3d9\uae30 \ubc29\uc2dd\uc758 Servlet\uc774 Servlet 3.0\uc5d0 \ub4f1\uc7a5\ud588\ub2e4. \ud558\uc9c0\ub9cc \uc804\ud1b5\uc801\uc778 I/O \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc740 \ube14\ub85c\ud0b9 \ubc29\uc2dd\uc73c\ub85c \ub3d9\uc791\ud588\ub2e4. Servlet 3.1\uc5d0\uc11c \ub17c\ube14\ub85c\ud0b9 I/O\uac00 \ucd94\uac00\ub418\uc5c8\uc9c0\ub9cc, \ub9ce\uc774 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc558\ub2e4\uace0 \ud55c\ub2e4. \\n\\n### Spring WebFlux(2017)\\n\\n\uc801\uc740 \uc218\uc758 \uc2a4\ub808\ub4dc\ub85c \ub3d9\uc2dc\uc131\uc744 \ucc98\ub9ac\ud558\uace0, \uc801\uc740 \ub9ac\uc18c\uc2a4\ub85c \ud655\uc7a5\uc774 \uac00\ub2a5\ud55c \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd\uc758 \uc6f9 \uae30\uc220\uc774 \ud544\uc694\ud588\uace0, \uae30\uc874\uc758 Servlet\uc758 \uacbd\uc6b0 \ube44\ub3d9\uae30\ub97c \uc9c0\uc6d0\ud55c\ub2e4 \ud574\ub3c4 \ub3d9\uae30\uc2dd API\ub4e4\uc774 \ub9ce\uc774 \ub0a8\uc544\uc788\uc5c8\uae30 \ub54c\ubb38\uc5d0 \uc774\ub7ec\ud55c Servlet\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294 \uae30\uc220\uc774 \ud544\uc694\ud588\ub2e4. \ub610\ud55c \uae30\uc874\uc5d0 Netty\uc640 \uac19\uc774 \ube44\ub3d9\uae30, \ub17c\ube14\ub85c\ud0b9 \ubc29\uc2dd \uc11c\ubc84\ub85c \uc790\ub9ac\ub97c \uc798 \uc7a1\uc740 \uc11c\ubc84\ub97c \uc704\ud574 Spring WebFlux\uac00 \ub4f1\uc7a5\ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub370\uc774\ud130 \uc811\uadfc\uc744 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 JDBC\uc758 \uacbd\uc6b0 Blocking API\ub77c, Spring Webflux\uc5d0\uc11c\ub294 R2DBC\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uace0 \ud55c\ub2e4. \\n\\n### \ub9c8\uce58\uba70\\n\\n\ud574\ub2f9 \uc815\ub9ac \ub0b4\uc6a9\uc758 \uacbd\uc6b0 Async, Non Blocking \uad00\ub828\ub41c \ub0b4\uc6a9\uc744 \uae4a\uac8c \uacf5\ubd80\ud55c \uc801\uc774 \uc5c6\uc5b4\uc11c \uc815\ud655\ud558\uc9c0 \uc54a\uc744 \uc218 \uc788\ub2e4. \\n\uadf8\ub798\ub3c4 \uae30\uc220\uc758 \ub4f1\uc7a5 \ubc30\uacbd\uc774\ub098 \uacfc\uc815\uc744 \uc54c\uace0 \uc788\ub2e4\uba74 \uc870\uae08 \ub354 \uae4a\uc774 \uc788\ub294 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0\uc774 \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubc1c\uc804 \uacfc\uc815, \uad6c\uad6c \uac15\uc758 \\n[Dynamic Content with CGI, Apache Tutorial](https://httpd.apache.org/docs/trunk/en/howto/cgi.html) \\n[History of Spring and the Spring Framework, Spring](https://docs.spring.io/spring-framework/reference/overview.html#overview-history) \\n[Understanding JavaServer Pages Model 2 architecture, Govind Seshadri](https://www.infoworld.com/article/2076557/understanding-javaserver-pages-model-2-architecture.html) \\n[MVC, XEROX PARC](https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html) \\n[Expert One-to-One J2EE Development, Rod Johnson](https://www.amazon.com/Expert-One-One-Development-without/dp/0764558315) \\n[\ubc30\ub2ec\uc758\ubbfc\uc871 \ucd5c\uc804\ubc29 \uc2dc\uc2a4\ud15c! \u2018\uac00\uac8c\ub178\ucd9c \uc2dc\uc2a4\ud15c\u2019\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4, \ubc30\ub2ec\uc758\ubbfc\uc871](https://techblog.woowahan.com/2667/) \\n[Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu](https://www.infoworld.com/article/2077995/java-concurrency-asynchronous-processing-support-in-servlet-3-0.html)\\n[WebFlux Overview, Spring](https://docs.spring.io/spring-framework/reference/web/webflux/new-framework.html)\\n[Spring WebFlux\uc640 Armeria\ub97c \uc774\uc6a9\ud558\uc5ec Microservice\uc5d0 \ud544\uc694\ud55c Reactive + RPC \ub3d9\uc2dc\uc5d0 \uc7a1\uae30, Naver D2](https://d2.naver.com/helloworld/6080222) \\n[Spring WebFlux\ub780 \ubb34\uc5c7\uc77c\uae4c](https://tweety1121.tistory.com/entry/Spring-WebFlux-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C)"},{"id":"log-async-exception","metadata":{"permalink":"/log-async-exception","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx","source":"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx","title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","description":"\ubb38\uc81c \uc0c1\ud669","date":"2023-09-18T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 18\uc77c","tags":[{"label":"async","permalink":"/tags/async"},{"label":"exception","permalink":"/tags/exception"}],"readingTime":3.615,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","slug":"log-async-exception","tags":["async","exception"]},"unlisted":false,"prevItem":{"title":"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815","permalink":"/web-application-evolution"},"nextItem":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"}},"content":"### \ubb38\uc81c \uc0c1\ud669\\n\\n\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 `@Async`\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 `@ControllerAdvice` + `@ExceptionHandler`\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4. \\n\\n### \ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815\\n\\n\uc2a4\ud504\ub9c1 4.1 \ubd80\ud130 \uc81c\uacf5\ub418\ub294 [AsyncUncaughtExceptionHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html)\uc758 \uacbd\uc6b0 \ubc18\ud658 \ud0c0\uc785\uc774 void\uc778 \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\ub97c \uc608\uc678 \ucc98\ub9ac\ud558\uae30 \uc27d\ub3c4\ub85d \ub3c4\uc640\uc900\ub2e4. \\n\\n\ub530\ub77c\uc11c AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ud578\ub4e4\ub9c1\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4. \\n\uae30\uc874\uc758 \ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4. \\n\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\ub3c4 \ub9c8\ucc2c\uac00\uc9c0\ub85c MDC\uc758 \uc815\ubcf4\ub97c \uac00\uc838\uc640\uc11c \ub85c\uadf8\ub97c \ucd9c\ub825\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4. \\n\\n```java title=AsyncExceptionHandler\\n@Slf4j\\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\\n\\n private static final String LOG_FORMAT = \\"[%s] %s\\";\\n\\n @Override\\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\\n }\\n}\\n```\\n\\nAsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4. \\ngetAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4. \\n\\n```java title=AsyncConfig\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig implements AsyncConfigurer {\\n\\n @Override\\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\\n return new AsyncExceptionHandler();\\n }\\n}\\n```\\n\\n\uc774\uc81c \ube44\ub3d9\uae30 \uc0c1\ud669\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544 \ucc98\ub9ac\ud55c\ub2e4. \\n\\n### MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c\\n\\n\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\\n![./mdc-null.png](./mdc-null.png)\\n\\n\uc2a4\ud504\ub9c1 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 [TaskDecorator](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html)\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n```java title=MdcTaskDecorator\\npublic class MdcTaskDecorator implements TaskDecorator {\\n\\n @Override\\n public Runnable decorate(final Runnable runnable) {\\n Map threadContext = MDC.getCopyOfContextMap();\\n return () -> {\\n MDC.setContextMap(threadContext);\\n runnable.run();\\n };\\n }\\n}\\n```\\n\\n\uc0dd\uc131\ud55c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4.\\n\\n```java title=AsyncConfig\\n@RequiredArgsConstructor\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig implements AsyncConfigurer {\\n\\n private final AsyncConfigurationProperties properties;\\n\\n @Bean\\n public ThreadPoolTaskExecutor taskExecutor() {\\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\\n executor.setCorePoolSize(properties.coreSize());\\n executor.setMaxPoolSize(properties.maxSize());\\n executor.setQueueCapacity(properties.queueCapacity());\\n \\n // highlight-next-line\\n executor.setTaskDecorator(new MdcTaskDecorator());\\n executor.setWaitForTasksToCompleteOnShutdown(true);\\n executor.initialize();\\n return executor;\\n }\\n\\n @Override\\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\\n return new AsyncExceptionHandler();\\n }\\n}\\n```\\n\\n\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4.\\n\\n![./mdc-not-null.png](./mdc-not-null.png)\\n\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[spring async, baeldung](https://www.baeldung.com/spring-async) \\n[@Async will not call by @ControllerAdvice for global exception](https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception) \\n[Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8](https://blog.gangnamunni.com/post/mdc-context-task-decorator/) \\n[TaskDecorator, Spring docs](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html) \\n[AsyncUncaughtExceptionHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html)"},{"id":"tomcat-retrospective","metadata":{"permalink":"/tomcat-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","description":"1, 2\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-http/pull/302","date":"2023-09-11T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 11\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":12.345,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","slug":"tomcat-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","permalink":"/log-async-exception"},"nextItem":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"}},"content":":::note PR \ub9c1\ud06c \\n1, 2\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-http/pull/302 \\n3, 4\ub2e8\uacc4: https://github.com/woowacourse/jwp-dashboard-http/pull/431\\n:::\\n\\n### \ud1b0\ucea3 \uad6c\ud604\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4. \\n\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4. \\n\\n\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616/)\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4. \\n\\n### \ub2e4\uc774\uc5b4\uadf8\ub7a8\\n\\nCatalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4. \\n\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4. \\n\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph coyote\\n\\t\\tHP[Http11Processor] --\x3e A\\n\\t\\tHP --\x3e HttpRequestParser\\n\\t\\tHP --\x3e HttpResponseGenerator\\n\\t\\tA[Adapter]\\n end\\n\\n subgraph catalina\\n\\t\\tRA[RequestAdapter] -.-> A\\n\\t\\tAC[AbstractController] -.-> C[Controller]\\n\\t\\tStaticController -.-> AC\\n\\t\\tSM[SessionManger] -.-> Manager\\n\\t\\tTC[Tomcat] --\x3e RA\\n\\t\\tRA --\x3e C\\n\\t\\tRA --\x3e Manager\\n\\t\\tRA --\x3e RM\\n\\t\\tRM[RequestMapper] --\x3e C\\n end\\n\\n subgraph jwp\\n\\t\\tLC[LoginController] -.-> AC\\n\\t\\tApplication --\x3e TC\\n end\\n\\n```\\n\\n### \ucf54\ub4dc \ub9ac\ubdf0 \\n\\n\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4. \\n\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4. \\n\\n\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4. \\n\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### SessionConfig\\n\\n\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 [\ucee8\ud2b8\ub9ac\ubdf0\ud2b8](https://github.com/apache/tomcat/pull/660)\ub97c \uc2dc\ub3c4\ud588\ub2e4. \\n\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4. \\n\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4. \\n\\n\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4. \\n\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4. \\n\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n\\n String result = getConfiguredSessionCookieName(context);\\n\\n if (result == null) {\\n result = DEFAULT_SESSION_COOKIE_NAME;\\n }\\n\\n return result;\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n\\n String result = getConfiguredSessionCookieName(context);\\n\\n if (result == null) {\\n result = DEFAULT_SESSION_PARAMETER_NAME;\\n }\\n\\n return result;\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context) {\\n\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n if (context != null) {\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc =\\n context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n }\\n\\n return null;\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n if (context == null) {\\n return DEFAULT_SESSION_COOKIE_NAME;\\n }\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n if (context == null) {\\n return DEFAULT_SESSION_PARAMETER_NAME;\\n }\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n return defaultName;\\n}\\n```\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n if (context != null) {\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n }\\n return defaultName;\\n}\\n```\\n\\n\\n\\n\\n### HTTP \uc218\uc5c5\\n\\n\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. \\n\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4. \\nHTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. \\n\\n\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4. \\n\\n```yml\\nserver:\\n compression:\\n enabled: true\\n```\\n\\n\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4. \\n\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 [issue](https://github.com/spring-projects/spring-boot/issues/21369)\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4. \\n\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4. \\n\\n> If you\'re developing a public-facing application then it\'s probably likely gzip compression would be worthwhile. If, however, you\'re a microservice application and you\'re in a dataceter, you may well prefer to reduce CPU load because you know you\'ll only be talking to other microservices and you have a reliable gigabit network.\\n\\nPhil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4. \\n\\n\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4. \\n\\n:::note ETag\\nETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4. \\n\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4. \\nMDN\\n:::\\n\\n### Thread \uc218\uc5c5\\n\\n\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4. \\n\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4. \\n\\n\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4. \\n\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n`threads.max`: Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218 \\n`max-connections`: Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218 \\n`accept-count`: \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n C(\\"Client\\") -- request --\x3e ACQ(\\"\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \\n size = accept-count\\") --\x3e TCQ(\\"Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\\n size = max-connections\\") --\x3e TP(\\"Thread Pool\\n size = threads.max\\")\\n```\\n\\n### \ub9c8\uce58\uba70\\n\\n\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4. \\n\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4. \\n\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616/) \\n[ETag, mdn](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag) \\n[Apache Tomcat 8 Configuration Reference](https://tomcat.apache.org/tomcat-8.5-doc/config/http.html) \\n[Apache Tomcat Tuning, Terry Cho](https://bcho.tistory.com/788) \\n[maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30](https://dev-ws.tistory.com/96)"},{"id":"performance-test-type","metadata":{"permalink":"/performance-test-type","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx","source":"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx","title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","description":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8","date":"2023-09-10T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 10\uc77c","tags":[{"label":"performance test","permalink":"/tags/performance-test"}],"readingTime":5.8,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","slug":"performance-test-type","tags":["performance test"]},"unlisted":false,"prevItem":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"},"nextItem":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"}},"content":"## \uc131\ub2a5 \ud14c\uc2a4\ud2b8\\n\\nAPI\uc758 \uc694\uccad\uc774 \ub9ce\uc740 \uc0c1\ud669\uc5d0\uc11c \uc11c\ubc84\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\\n\\n\uc2dc\uc2a4\ud15c\uc5d0 \ubd80\ud558\uac00 \uac78\ub9ac\uba74 \ubb38\uc81c \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\uc591\ud55c \uc0c1\ud669\uc5d0 \ub300\ube44\ud574\uc11c \uc131\ub2a5 \ud14c\uc2a4\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4. \\n\\n![./test.png](./test.png)\\n\\n### \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)\\n\\n\ucd5c\uc18c\ud55c\uc758 \ubd80\ud558\ub97c \uc8fc\uc5b4 \uc2dc\uc2a4\ud15c\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\nVU\ub97c \ucd5c\uc18c\ud55c\uc73c\ub85c \ub450\uace0, \uc9e7\uc740 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \ud14c\uc2a4\ud2b8\ud55c\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud568\uc73c\ub85c\uc368 \ud14c\uc2a4\ud2b8 \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc624\ub958\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uace0, \uc131\ub2a5 \uc9c0\ud45c\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc9d1, \ubaa8\ub2c8\ud130\ub9c1 \ub418\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \uac00\uc0c1 \uc0ac\uc6a9\uc790(VU)\\n\uac00\uc0c1 \uc0ac\uc6a9\uc790\ub294 \uc11c\ubc84 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ub300\ud574 \ud2b9\uc815 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c\ub2e4. \\n\uc774\ub294 \ub2e4\ub978 \uac00\uc0c1 \uc0ac\uc6a9\uc790\uc640 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uba70, \uc5ec\ub7ec \uac00\uc0c1 \uc0ac\uc6a9\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc2dc \uc5f0\uacb0\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\uc2a4\ub808\ub4dc\ub77c\uace0 \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4. \\n:::\\n\\n### \uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)\\n\\n\uc0ac\uc6a9\ub7c9\uc774 \uae09\uc99d\ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uacac\ub514\uace0 \uc131\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\ud2f0\ucf13 \ubc1c\uae09, \ud560\uc778 \ucfe0\ud3f0 \ubc1c\uae09\uacfc \uac19\uc740 \uc774\ubca4\ud2b8\ub97c \ud558\ub294 \uacbd\uc6b0 \ub300\uaddc\ubaa8 \ud2b8\ub798\ud53d\uc774 \ub4e4\uc5b4\uc628\ub2e4. \\n\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uae09\uc99d\ud558\ub294 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\uace0, \ubd80\ud558\ub97c \uc798 \ubc84\ud2f0\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n### \ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)\\n\\n\ubaa9\ud46f\uac12\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \uacac\ub51c \uc218 \uc788\uc744\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\uc77c\ubc18\uc801\uc778 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\ub2e4. \\n\ub7a8\ud504\uc5c5 \ub610\ub294 \ubb19\ud46f\uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ubd80\ud558 \uae30\uac04\ub3d9\uc548 \uc131\ub2a5\uc774 \ubb38\uc81c\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uace0, \uc2dc\uc2a4\ud15c \ubcc0\uacbd \ud6c4\uc5d0\ub3c4 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ub3d9\uc77c\ud558\uac8c \ubaa9\ud46f\uac12\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \ub7a8\ud504 \uc5c5(Ramp-up)\\n\ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574 \uc124\uc815\ud55c \uac00\uc0c1 \uc0ac\uc6a9\uc790 \uc218\uc5d0 \ub3c4\ub2ec\ud558\ub294 \ub370 \uac78\ub9ac\ub294 \uc2dc\uac04\\n:::\\n\\n### \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test) \\n\\n\uc2dc\uc2a4\ud15c\uc758 \ucd5c\ub300\uce58\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \ubc1b\uc558\uc744 \ub54c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\uadf8\ub798\ud504\ub97c \ubd24\uc744 \ub54c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc640 \uc720\uc0ac\ud55c \ud615\ud0dc\ub85c \ubcf4\uc774\uc9c0\ub9cc, \ubd80\ud558\ub7c9\uc774 \ub2e4\ub974\ub2e4. \\n\uc77c\ubc18\uc801\uc73c\ub85c \ud3c9\uade0\uc801\uc778 \ubaa9\ud46f\uac12 \ub300\ube44 \uc791\uac8c\ub294 50% \uc774\uc0c1, \ud544\uc694\uc758 \uacbd\uc6b0 \uadf8 \uc774\uc0c1\uc73c\ub85c \ubd80\ud558\ub97c \uc900\ub2e4. \\n\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub294 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c \ud6c4\uc5d0\ub9cc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4. \ubd80\ud558 \ud14c\uc2a4\ud2b8\uac00 \uc774\ub8e8\uc5b4\uc9c0\uc9c0 \uc54a\uc740 \uc0c1\ud669\uc5d0\uc11c \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \ubcd1\ubaa9 \uc9c0\uc810\uc774\ub098 \ubb38\uc81c \uc0c1\ud669\uc744 \ucc3e\uae30 \uc5b4\ub824\uc6cc\uc9c4\ub2e4. \\n\ub610\ud55c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c VU\uac12(\uc2a4\ub808\ub4dc \uc218)\ub9cc \uc218\uc815\ud558\uc5ec \uc7ac\uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\\n### \ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test) \\n\\n\ud3c9\uade0 \uc0ac\uc6a9\ub960\ub85c \uc77c\uc815 \ubd80\ud558\ub97c \uc9c0\uc18d\uc801\uc73c\ub85c \uc8fc\uba70 \uc2dc\uc2a4\ud15c\uc774 \ubb38\uc81c\ub418\ub294 \uc9c0\uc810\uc744 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\ud761\uc218 \ud14c\uc2a4\ud2b8(Soak Test)\ub77c\uace0\ub3c4 \ud558\uba70, \uae30\ubcf8\uc801\uc778 \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc758 \ubcc0\ud615\uc774\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc640 \ub2ec\ub9ac \uae34 \uc2dc\uac04\ub3d9\uc548 \ud14c\uc2a4\ud2b8\ub97c \ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\uba70, \uba54\ubaa8\ub9ac \ub204\uc218 \ubb38\uc81c\uc640 \uac19\uc774 \uc7a5\uc2dc\uac04 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud560 \ub54c \uc2dc\uc2a4\ud15c\uc758 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \ubd80\ubd84\uc744 \ud655\uc778\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4. \\n\\n### \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)\\n\\n\uc784\uacc4 \uc9c0\uc810\uc744 \ucc3e\uae30 \uc704\ud574 \ubd80\ud558\ub97c \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a4\uba70 \uc9c4\ud589\ud558\ub294 \ud14c\uc2a4\ud2b8\\n\\n\ubb38\uc81c\ub418\ub294 \ubd80\ubd84\uc744 \ub354 \ube68\ub9ac \ucc3e\uae30 \uc704\ud574 \ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\ud55c \ub2e4\uc74c\uc5d0 \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud558\uace0, \uc774 \ub54c \uc810\uc9c4\uc801\uc73c\ub85c \ubd80\ud558\ub97c \ub298\ub824\ub098\uac00\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc131\ub2a5 \ud29c\ub2dd\uacfc \ubc18\ubcf5\ud574\uc11c \uc9c4\ud589\ud55c\ub2e4\uba74, \uc2dc\uc2a4\ud15c\uc744 \ub354\uc6b1 \ubc1c\uc804\uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\ub2e4\ub9cc Auto Scaling\uc774 \uc801\uc6a9\ub41c \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c\ub294 \uc9c4\ud589\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Load test types, k6](https://k6.io/docs/test-types/load-test-types/) \\n\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc \\n\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"},{"id":"db-replication","metadata":{"permalink":"/db-replication","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx","source":"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx","title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","description":"\ubcf5\uc81c(Replication)","date":"2023-08-22T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 22\uc77c","tags":[{"label":"mysql","permalink":"/tags/mysql"},{"label":"replication","permalink":"/tags/replication"}],"readingTime":21,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","slug":"db-replication","tags":["mysql","replication"]},"unlisted":false,"prevItem":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"}},"content":"## \ubcf5\uc81c(Replication)\\n\\n\ud55c \uc11c\ubc84\uc5d0\uc11c \ub2e4\ub978 \uc11c\ubc84\ub85c \ub370\uc774\ud130\ub97c \ub3d9\uae30\ud654\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4. \\n\uc6d0\ubcf8 \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Primary \ub610\ub294 Source \ub77c\uace0 \ubd80\ub974\uace0, \ubcf5\uc81c\ub41c \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Secondary \ub610\ub294 Replica \ub77c\uace0 \ubd80\ub978\ub2e4. \\n\\n### \ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720\\n\\n**1. \uc2a4\ucf00\uc77c \uc544\uc6c3**\\n\\n\uc0ac\uc6a9\uc790\uc758 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uac00\ud574\uc9c0\ub294 \ubd80\ud558\ub3c4 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc99d\uac00\ud55c\ub2e4. \\n\uc774\ub97c \ucc98\ub9ac\ud558\uae30 \uc704\ud574 \ubcf5\uc81c\ub97c \ud1b5\ud55c \uc2a4\ucf00\uc77c \uc544\uc6c3\uc744 \uc801\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucffc\ub9ac\ub4e4\uc744 \uac01\uac01\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c \ubd84\uc0b0 \uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\\n**2. \ub370\uc774\ud130 \ubc31\uc5c5**\\n\\n\uc2e4\uc81c \uc6b4\uc601\ub418\ub294 \uc11c\ube44\uc2a4\uac00 \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 DB\uc5d0\uc11c \ubc31\uc5c5\uc744 \uc9c4\ud589\ud558\ub294 \uacbd\uc6b0, \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc774 \uac00\uc9c0 \uc54a\ub3c4\ub85d \ubcf5\uc81c\ub97c \ud1b5\ud574 Replica \uc11c\ubc84\ub97c \uad6c\ucd95\ud558\uc5ec, Replica \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ub97c \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\uc73c\ub85c \uc601\ud5a5\uc744 \ucd5c\uc18c\ud654 \ud560 \uc218 \uc788\ub2e4. \\n\\n**3. \ub370\uc774\ud130 \ubd84\uc11d**\\n\\n\ubc31\uc5c5\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc7a1\ud558\uace0 \ubb34\uac70\uc6b4 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\uc758 \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4. \\n\ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc81c\ub97c \uc0ac\uc6a9\ud574 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \\n\\n**4. \ub370\uc774\ud130\uc758 \uc9c0\ub9ac\uc801 \ubd84\uc0b0**\\n\\n\ube60\ub978 \uc751\ub2f5\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc11c\ubc84\uc5d0 \uac00\uae5d\uac8c \uc11c\ubc84\ub97c \uad6c\uc131\ud558\uac70\ub098, \uace0\uac00\uc6a9\uc131(High Availability)\uc744 \uc704\ud574\uc11c\ub3c4 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c\\n\\nMySQL \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub85c\uadf8 \ud30c\uc77c\uc744 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub77c\uace0 \ud55c\ub2e4. \\n\ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ud1b5\ud574 \ub370\uc774\ud130 \ubcc0\uacbd, \ud14c\uc774\ube14 \uad6c\uc870 \ubcc0\uacbd, \uacc4\uc815\uc774\ub098 \uad8c\ud55c \ubcc0\uacbd\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc800\uc7a5\ub41c\ub2e4. \\nMySQL\uc758 \ubcf5\uc81c\ub294 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. \uc774\ub97c Replica \uc11c\ubc84\ub85c \uc804\ub2ec\ud558\uace0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph Replica\\n\\t\\tdirection TB\\n\\t\\tIO[Replication I/O thread] -- save --\x3e RL[Relay Log]\\n\\t\\tSQL[Replication SQL Thread] -- read --\x3e RL\\n\\tend\\n\\n\\tsubgraph Source\\n\\t\\tdirection TB\\n\\t\\tBLD[Binary Log Dump Thread] -- Send Binary Log Dump--\x3e IO\\n\\tend\\n\\n```\\n\\n:::note \uc2a4\ub808\ub4dc\ubcc4 \uc5ed\ud560\\n\\nBinary Log Dump Thread: \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc758 \ub0b4\uc6a9\uc744 Replica \uc11c\ubc84\ub85c \uc804\ub2ec \\nReplication I/O Thread: Binary \ub85c\uadf8 \uc774\ubca4\ud2b8\ub97c \uac00\uc838\uc640 \ub85c\uceec \uc11c\ubc84\uc758 \ud30c\uc77c(Relay Log)\ub85c \uc800\uc7a5 \\nReplication SQL Thread: \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc774\ubca4\ud2b8\ub97c \uc77d\uace0 \uc2e4\ud589\\n\\n:::\\n\\n### \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810\\n\\n\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc740 \uc11c\ubc84\uc5d0 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0 \ubcc0\uacbd\uc774 \uae4c\ub2e4\ub86d\ub2e4. \\n\ud1a0\ud3f4\ub85c\uc9c0\ub780 \ub124\ud2b8\uc6cc\ud06c\uc758 \uc694\uc18c\ub4e4\uc744 \ubb3c\ub9ac\uc801\uc73c\ub85c \uc5f0\uacb0\ud574 \ub193\uc740 \uac83, \ub610\ub294 \uadf8 \uc5f0\uacb0 \ubc29\uc2dd\uc744 \ub9d0\ud55c\ub2e4.\\n\\n```mermaid\\ngraph TD\\n\\tA[A binary-log:300] --\x3e B[B Binary-log:300]\\n\\tA[A binary-log:300] --\x3e C[C Binary-log:200]\\n```\\n\\n\uc704\uc640 \uac19\uc774 Source \uc11c\ubc84, Replica 2\ub300\uac00 \uc874\uc7ac\ud558\uace0, C \uc11c\ubc84\uc5d0 \ubcf5\uc81c \uc9c0\uc5f0\uc774 \ub418\uc5c8\uc744 \ub54c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\tA[A binary-log:300]\\n\\tB[B Binary-log:300] --\x3e C[C Binary-log:200 \ubb38\uc81c \ubc1c\uc0dd]\\n```\\n\\nA \uc11c\ubc84\uc5d0\uc11c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 B \uc11c\ubc84\ub97c Source \uc11c\ubc84\ub85c \uc2b9\uaca9\ud558\uace0, C\uc5d0\uac8c \uc870\ud68c \ucffc\ub9ac\ub97c \ubd84\uc0b0\uc2dc\ud0a8\ub2e4. \\n\ud558\uc9c0\ub9cc \uc5ec\uae30\uc11c C \uc11c\ubc84\uc5d0\ub294 A \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\uac00 \uc548\ub418\uc5c8\uc73c\ub2c8 \uc870\ud68c \uc2dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\ub4a4\ub2a6\uac8c B \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\ub97c \ud558\ub824\uace0 \ud574\ub3c4, \uc5b4\ub5a4 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8, \uc5b4\ub5a4 \uc704\uce58\uc640 \ub3d9\uae30\ud654\ud574\uc57c\ud558\ub294\uc9c0 \uc54c\uae30 \uc5b4\ub835\ub2e4. \\n\\n### \uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c\\n\\nGTID \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ubc1c\uc0dd\ud55c \uc774\ubca4\ud2b8\uc5d0 \uace0\uc720\ud55c \uc2dd\ubcc4\uac12\uc744 \ubd80\uc5ec\ud55c\ub2e4\uba74, \ub3d9\uae30\ud654\uc5d0 \ub300\ud55c \ubb38\uc81c\ub97c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4. \\n\uc704\uc758 \uc608\uc2dc\uc640 \uac19\uc774 \ubcf5\uc81c \uc9c0\uc5f0\uacfc \ud568\uaed8 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ud574\ub3c4 \ud2b9\uc815 GTID \ubd80\ud130 \ubcf5\uc81c\ub97c \uc7ac\uac1c\ud558\uba74 \ub41c\ub2e4. \\n\\n:::note GTID\\n\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\uc5d0 \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \uc11c\ubc84\uc5d0\uc11c \uace0\uc720\ud558\ub3c4\ub85d \uac01 \uc774\ubca4\ud2b8\uc5d0 \ubd80\uc5ec\ub41c \uc2dd\ubcc4\uac12 \\n[source_id]:[transaction_id]\ub85c \uad6c\uc131\ub418\uba70, source_id\ub294 \uc11c\ubc84\ub97c \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc774\uace0 transaction_id\ub294 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc73c\ub85c 1\uc529 \uc99d\uac00\ud558\ub294 \ud615\ud0dc\ub85c \ubc1c\uae09\ub41c\ub2e4. \\n:::\\n\\n### \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\\n\\n**\uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131**\\n\\n\uac00\uc7a5 \uac04\ub2e8\ud55c \uad6c\uc131\uc73c\ub85c \uc81c\uc77c \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4. \\nreplica \uc11c\ubc84\ub97c \uc77d\uae30 \uc804\uc6a9, \uc608\ube44 \uc11c\ubc84, \ubc31\uc5c5 \uc6a9\ub3c4\ub85c \ub9ce\uc774 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R\\n S[Source] --\x3e R[Replica]\\n```\\n\\n**\uba40\ud2f0 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131**\\n\\n2\uac1c\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4. \\n\ud558\ub098\uc758 replica\ub294 \uc608\ube44 \uc6a9\ub3c4\ub85c \ub0a8\uaca8\ub450\ub294 \ud615\ud0dc\ub2e4. \\n\ucd94\ud6c4\uc5d0 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 \uc608\ube44 \uc6a9\ub3c4\uc758 replica\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c \uc77d\uae30 \uc694\uccad\uc758 \ubd80\ud558 \ubd84\uc0b0\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R1\\n S[Source] --\x3e R1[Replica1]\\n S --\x3e R2[Replica2]\\n```\\n\\n**\uccb4\uc778 \ubcf5\uc81c \uad6c\uc131**\\n\\nreplica \uc11c\ubc84\uac00 \ub9ce\uc740 \uacbd\uc6b0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \uc804\ub2ec\ud558\ub294 \uc791\uc5c5 \uc790\uccb4\uac00 \ubd80\ud558\uac00 \ub420 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c 1:M:M \uad6c\uc870\ub85c \uccb4\uc778 \ubcf5\uc81c \uad6c\uc131\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R1\\n S[Source] --\x3e R1[Replica1]\\n S --\x3e R2[Replica2]\\n S --\x3e R3[Replica3]\\n\\n R3 --\x3e R3-1[Replica 3-1]\\n R3 --\x3e R3-2[Replica 3-2]\\n\\n B[Batch Server] --\x3e R3-2\\n```\\n\\n**\ub4c0\uc5bc \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131**\\n\\n2\uac1c\uc758 MySQL \uc11c\ubc84 \ubaa8\ub450 \uc77d\uae30\uc640 \uc4f0\uae30\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d \ud558\ub294 \uad6c\uc131\uc774\ub2e4. \\n\uac01 \uc11c\ubc84\uc5d0\uc11c \ubcc0\uacbd\ub41c \ub370\uc774\ud130\ub294 \ub2e4\ub978 \uc11c\ubc84\uc5d0 \ubc18\uc601\ub41c\ub2e4. \\n\ubaa9\uc801\uc5d0 \ub530\ub77c ACTIVE-ACTIVE \ud615\ud0dc \ub610\ub294 ACTIVE-PASSIVE \ud615\ud0dc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\nACTIVE-PASSIVE \ud615\ud0dc\uc778 \uacbd\uc6b0 \uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131\uacfc \ub3d9\uc77c\ud574\ubcf4\uc774\uc9c0\ub9cc, ACTIVE \uc11c\ubc84\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uba74 \uc124\uc815\uc758 \ubcc0\uacbd\uc5c6\uc774 PASSIVE \uc11c\ubc84\ub85c \uc4f0\uae30 \uc791\uc5c5\uc744 \uc804\ud658\ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc774 \uc7a5\uc810\uc774\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR1\\n W -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR2\\n SR1[Source/Replica 1] --\x3e SR2[Source/Replica 2]\\n```\\n\\n:::note ACTIVE-ACTIVE, ACTIVE-PASSIVE\\nACTIVE-ACTIVE: 2\uac1c\uc758 \uc11c\ubc84 \ubaa8\ub450 \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc \\nACTIVE-PASSIVE: \ud558\ub098\uc758 \uc11c\ubc84\uc5d0\uc11c\ub9cc \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc\\n:::\\n\\n**\uba40\ud2f0 \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131**\\n\\n\uc5ec\ub7ec\uac1c\uc758 source \uc11c\ubc84\uc640 \ud558\ub098\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \uad6c\uc131\uc774\ub2e4. \\n\uc774\ub294 source \uc11c\ubc84\uc758 \ub370\uc774\ud130\ub97c \ud55c \uacf3\uc5d0 \ubc31\uc5c5\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9, \uc5ec\ub7ec \uc11c\ubc84\uc5d0 \uc874\uc7ac\ud558\ub294 \ub370\uc774\ud130\ub97c \ud1b5\ud569, \uc0e4\ub529\ub418\uc5b4\uc788\ub294 \ud14c\uc774\ube14 \ub370\uc774\ud130\ub97c \ud1b5\ud569\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n S1[Source 1] --\x3e R[Replica]\\n S2[Source 2] --\x3e R\\n```\\n\\n## \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30\\n\\nmysql 2\ub300\ub97c \uc774\uc6a9\ud558\uc5ec replication\uc744 \uad6c\uc131\ud558\uace0, spring boot application\uc73c\ub85c source, replica \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\ubcf4\ub294 \uc608\uc81c\uc774\ub2e4. \\n[https://github.com/bbiac/db-replication](https://github.com/bbiac/db-replication) \\n\\n### MySQL \ud658\uacbd \uad6c\uc131\\n\\nMySQL \ubc84\uc804\uc740 8.1\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n13306, 13307 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud574\uc11c MySQL \uc11c\ubc84 2\ub300\ub97c \ub744\uc6e0\ub2e4. \\n\ub610\ud55c \uc0ac\uc2e4 IP \ub300\uc5ed\uc73c\ub85c \ud1b5\uc2e0\ud560 \uc218 \uc788\ub3c4\ub85d \ucee4\uc2a4\ud140 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud588\ub2e4. \\n\\n```yml\\nversion: \'3.8\'\\n\\nservices:\\n source:\\n platform: linux/x86_64\\n image: mysql:latest\\n restart: always\\n container_name: mysql-source\\n environment:\\n TZ: \'Asia/Seoul\'\\n MYSQL_DATABASE: \'db\'\\n MYSQL_USER: \'user\'\\n MYSQL_PASSWORD: \'password\'\\n MYSQL_ROOT_PASSWORD: \'password\'\\n ports:\\n - \\"13306:3306\\"\\n volumes:\\n - db-source:/var/lib/mysql\\n - db-source:/var/lib/mysql-files\\n - ./docker/source.cnf:/etc/mysql/my.cnf\\n networks:\\n - mysql_network\\n\\n replica:\\n platform: linux/x86_64\\n image: mysql:latest\\n restart: always\\n container_name: mysql-replica\\n environment:\\n TZ: \'Asia/Seoul\'\\n MYSQL_DATABASE: \'db\'\\n MYSQL_USER: \'user\'\\n MYSQL_PASSWORD: \'password\'\\n MYSQL_ROOT_PASSWORD: \'password\'\\n ports:\\n - \\"13307:3306\\"\\n volumes:\\n - db-replica:/var/lib/mysql\\n - db-replica:/var/lib/mysql-files\\n - ./docker/replica.cnf:/etc/mysql/my.cnf\\n networks:\\n - mysql_network\\n\\nvolumes:\\n db-source:\\n db-replica:\\n\\nnetworks:\\n mysql_network:\\n driver: bridge\\n```\\n\\n\ub610\ud55c source, replica \uac01\uac01 \ub2e4\uc74c\uacfc \uac19\uc774 db \uc124\uc815\uc744 \ud588\ub2e4. \\n\\n| \uc124\uc815 | \uc124\uba85 |\\n| --- | --- |\\n| server_id | \uac01\uac01\uc758 mysql \ub9c8\ub2e4 \uace0\uc720\ud55c \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4. |\\n| log_bin | \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815\uc73c\ub85c \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 /var/lib/mysql \uc544\ub798 \ud574\ub2f9 log_bin\uc5d0 \uc124\uc815\ub41c \uac12\uc73c\ub85c \ub85c\uadf8\uac00 \uc0dd\uc131\ub41c\ub2e4. |\\n| sync_binlog | N\uac1c\uc758 \ud2b8\ub79c\uc7ad\uc158 \ub2f9 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ub514\uc2a4\ud06c\uc640 \ub3d9\uae30\ud654 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d \ud55c\ub2e4.\xa01\uc740 \uae30\ubcf8\uac12\uc73c\ub85c \uc548\uc815\uc801\uc774\uc9c0\ub9cc, \uac00\uc7a5 \ub290\ub9ac\ub2e4. |\\n| relay_log | \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815 |\\n| relay_log_purge | \ud544\uc694 \uc5c6\ub294 \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \uc0ad\uc81c\ud558\ub294 \uc635\uc158 |\\n| read_only | \uc77d\uae30 \uc804\uc6a9 \uc124\uc815 |\\n| log_replica_updates | Replication SQL Thread\ub85c \uc778\ud574 \uc2e4\ud589\ub418\ub294 \uc815\ubcf4\ub97c \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc5d0 \uae30\ub85d \ucd94\ud6c4\uc5d0 \uc18c\uc2a4 \uc11c\ubc84\ub85c \uc2b9\uaca9\ub418\ub294 \uacbd\uc6b0\ub97c \uace0\ub824\ud558\uba74 \uc124\uc815\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. |\\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```cnf title=\\"/docker/source.cnf\\"\\n[mysqld]\\nserver_id=1\\nlog_bin=mysql-bin\\nsync_binlog=1\\n```\\n\\n\\n\\n\\n\\n```cnf title=\\"/docker/replica.cnf\\"\\n[mysqld]\\nserver_id=2\\nrelay_log=mysql-relay-bin\\nrelay_log_purge=ON\\nread_only\\nlog_replica_updates\\n```\\n\\n\\n\\n\\n### \ub3c4\ucee4 \uc2e4\ud589\\n\\ndocker-compose up \uba85\ub839\uc5b4\ub85c docker-compose \uc124\uc815\uc73c\ub85c docker\ub97c \ub744\uc6b4\ub2e4. \\n-d \uc635\uc158\uc744 \ubd99\uc774\uba74 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ubaa8\ub4dc\ub85c \uc2e4\ud589\ub41c\ub2e4. \\n\\n```\\ndocker-compose up -d\\n```\\n\\n### replication slave \uad8c\ud55c \uc124\uc815\\n\\nREPLICATION SLAVE \uad8c\ud55c\uc774 \uc124\uc815\ub418\uc5b4 \uc788\uc5b4\uc57c replica \uc11c\ubc84\uc5d0\uc11c source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec \ub85c\uadf8\ub97c \uc77d\uc5b4\uc62c \uc218 \uc788\ub2e4. \\nsource \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec user \uacc4\uc815\uc5d0 \ud574\ub2f9 \uad8c\ud55c\uc744 \uc124\uc815\ud574\uc900\ub2e4. \\n\\nSOURCE \uc811\uc18d\\n\\n```bash\\ndocker exec -it mysql-source mysql -u root -p\\n```\\n\\nuser \uacc4\uc815\uc5d0 REPLICATION SLAVE \uad8c\ud55c \ucd94\uac00\\n\\n```mysql\\nGRANT REPLICATION SLAVE ON *.* TO \'user\'@\'%\';\\nFLUSH PRIVILEGES;\\n```\\n\\n### SOURCE DB \uc815\ubcf4 \ud655\uc778\\n\\nreplica \uc124\uc815\uc5d0 \ud544\uc694\ud55c source db\uc758 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c\uba85\uacfc Position\uc744 \ud655\uc778\ud55c\ub2e4. \\nPosition \uac12\uc740 \uc2e4\uc81c \ud30c\uc77c\uc758 \ubc14\uc774\ud2b8 \uc218\ub97c \uc758\ubbf8\ud55c\ub2e4. \\n\ud655\uc778\ud55c File(SOURCE_LOG_FILE)\uacfc Position(SOURCE_LOG_POS) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n```mysql\\nSHOW MASTER STATUS;\\n\\n+------------------+----------+--------------+------------------+-------------------+\\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |\\n+------------------+----------+--------------+------------------+-------------------+\\n| mysql-bin.000003 | 1082 | | | |\\n+------------------+----------+--------------+------------------+-------------------+\\n```\\n\\n### SOURCE ip \uc8fc\uc18c \ud655\uc778\\n\\ndocker inspect -f \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ud574\ub2f9 \ucee8\ud14c\uc774\ub108\uc758 \uc138\ubd80 \uc815\ubcf4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud574 docker-compose \ud30c\uc77c\uc5d0 \uc124\uc815\ud574\ub454 mysql_network\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc124 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4. \\n\\n```bash\\ndocker inspect -f \\"{{with index .NetworkSettings.Networks \\\\\\"db-replication_mysql_network\\\\\\"}}{{.IPAddress}}{{end}}\\" mysql-source\\n```\\n\\nip \uc8fc\uc18c\uac00 \ub098\uc624\uc9c0 \uc54a\ub294 \uacbd\uc6b0 docker inspect mysql-source\ub85c \ud655\uc778\ud55c\ub2e4. \\n\ud655\uc778\ud55c IP\uc8fc\uc18c(SOURCE_HOST) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n### replica mysql \uc811\uc18d\\n\\nsource db\uc5d0 \uc811\uc18d\ud588\ub358 \ubc29\ubc95\uacfc \ub3d9\uc77c\ud558\uac8c replica db\uc5d0 \uc811\uc18d\ud55c\ub2e4. \\n\\n```bash\\ndocker exec -it mysql-replica mysql -u root -p\\n```\\n\\n### replica \uc124\uc815\\n\\n\uc774\uc804\uc5d0 source db\uc5d0\uc11c \uc5bb\uc5c8\ub358 \uc815\ubcf4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc5ec replica \uc124\uc815\uc744 \uc9c4\ud589\ud55c\ub2e4. \\n\uc2e4\uc81c DB \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc73c\ub85c source DB\uc758 \ud30c\uc77c\uc744 \ubcf5\uc81c\ud574\uc57c\ud558\uc9c0\ub9cc \ud604\uc7ac \ubcf5\uc81c\ud560 \ub370\uc774\ud130\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ubd80\ubd84\uc740 \uc0dd\ub7b5\ud588\ub2e4. \\nSOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS \ub97c \uc801\uc808\ud788 \ubcc0\uacbd\ud55c\ub2e4.\\n\\n```mysql\\nSTOP REPLICA;\\n\\nCHANGE REPLICATION SOURCE TO \\nSOURCE_HOST=\'172.29.0.2\', \\nSOURCE_USER=\'user\', \\nSOURCE_PASSWORD=\'password\', \\nSOURCE_LOG_FILE=\'mysql-bin.000001\', \\nSOURCE_LOG_POS=0, \\nGET_SOURCE_PUBLIC_KEY=1;\\n\\nSTART REPLICA;\\n```\\n\\n### \uc124\uc815 \ud655\uc778\\n\\n```mysql\\nSHOW REPLICA STATUS;\\n\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n| Waiting for source to send event | 172.25.0.3 | user | 3306 | 60 | mysql-bin.000003 | 1082 | mysql-relay-bin.000002 | 868 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 1082 | 1078 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | | | 1 | |\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n```\\n\\nReplica_IO_Running, Replica_SQL_Running \uac12\uc774 YES\ub77c\uba74 \uc815\uc0c1\uc801\uc73c\ub85c replication \uad6c\uc131\uc774 \uc644\ub8cc\ub41c \uac83\uc774\ub2e4. \\n\\n\uc124\uc815\uc744 \ub9c8\uce5c \ud6c4 source db\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 create table \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud55c\ub2e4. \\nreplica db\uc5d0 \ub3d9\uc77c\ud55c member table\uc774 \uc0dd\uc131\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\nCREATE TABLE member\\n(\\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\\n name VARCHAR(255)\\n);\\n```\\n\\n## \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30\\n\\n\uc77c\ubc18\uc801\uc778 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 source, \uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158\uc778 \uacbd\uc6b0 replica\ub85c \uc694\uccad\uc774 \uac00\ub3c4\ub85d \uad6c\uc131\ud574\ubcf4\uc790. \\n\\n### Environment \uc124\uc815\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 source, replica\ub85c \uad6c\ubd84\ud558\uc5ec \uc124\uc815\ud55c\ub2e4. \\n\\n```yml title=\\"application.yml\\"\\nspring:\\n datasource:\\n source:\\n username: user\\n password: password\\n driver-class-name: com.mysql.cj.jdbc.Driver\\n jdbc-url: jdbc:mysql://localhost:13306/db\\n replica:\\n username: user\\n password: password\\n driver-class-name: com.mysql.cj.jdbc.Driver\\n jdbc-url: jdbc:mysql://localhost:13307/db\\n```\\n\\n### DataSourceType \uc124\uc815\\n\\n\ub2e8\uc21c \ubb38\uc790\uc5f4\ub85c\ub3c4 \uad6c\ubd84\ud560 \uc218 \uc788\uc9c0\ub9cc, enum\uc744 \uc774\uc6a9\ud574\uc11c \ud2b8\ub79c\uc7ad\uc158\uc744 \uad6c\ubd84\ud558\ub3c4\ub85d \uc0dd\uc131\ud55c\ub2e4. \\nKey\ub294 \ucd94\ud6c4\uc5d0 \ube48 \uc124\uc815\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```java title=\\"DataSourceType\\"\\npublic enum DataSourceType {\\n SOURCE(SOURCE_NAME),\\n REPLICA(REPLICA_NAME),\\n ;\\n\\n private final String key;\\n\\n DataSourceType(String key) {\\n this.key = key;\\n }\\n\\n public static class Key {\\n public static final String ROUTING_NAME = \\"ROUTING\\";\\n public static final String SOURCE_NAME = \\"SOURCE\\";\\n public static final String REPLICA_NAME = \\"REPLICA\\";\\n }\\n}\\n```\\n\\n### AbstractRoutingDataSource \uc124\uc815\\n\\n\uc2a4\ud504\ub9c1\uc774 \uc9c0\uc6d0\ud574\uc8fc\ub294 AbstractRoutingDataSource\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSource\ub97c \ud5a5\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub294 `Map`\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\uc744 \ubc1b\uc544 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4. \\n- setDefaultTargetDataSource: \uae30\ubcf8 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4. \\n- setTargetDataSources: \ub9f5 \ud615\ud0dc\ub85c \ubc1b\uc740 \ub370\uc774\ud130 \uc18c\uc2a4 \uac12\ub4e4\uc744 \uc124\uc815\ud55c\ub2e4. \\n\\ndetermineCurrentLookupKey\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n- isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \ud2b8\ub79c\uc7ad\uc158\uc774 \uc77d\uae30 \uc804\uc6a9\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n- DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uace0, \ubc18\ud658\ud55c \uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ub370\uc774\ud130 \uc18c\uc2a4\uac00 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n```java title=\\"RoutingDataSource\\"\\npublic class RoutingDataSource extends AbstractRoutingDataSource {\\n\\n private final Logger log = LoggerFactory.getLogger(getClass());\\n\\n public static RoutingDataSource from(Map dataSources) {\\n RoutingDataSource routingDataSource = new RoutingDataSource();\\n routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));\\n routingDataSource.setTargetDataSources(dataSources);\\n return routingDataSource;\\n }\\n\\n @Override\\n protected Object determineCurrentLookupKey() {\\n boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();\\n\\n if (readOnly) {\\n log.info(\\"readOnly = true, request to replica\\");\\n return DataSourceType.REPLICA;\\n }\\n log.info(\\"readOnly = false, request to source\\");\\n return DataSourceType.SOURCE;\\n }\\n}\\n```\\n\\n### DataSource \uc124\uc815\\n\\n\uc704\uc5d0\uc11c\ubd80\ud130 \uc21c\uc11c\ub300\ub85c Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy \uc124\uc815\uc774\ub2e4. \\n\uc2a4\ud504\ub9c1\uc740 \ud2b8\ub79c\uc7ad\uc158 \uc2dc\uc791\uc2dc\uc5d0 \ucee4\ub125\uc158\uc758 \uc0ac\uc6a9\uc5ec\ubd80\uc640 \uc0c1\uad00\uc5c6\uc774 \ucee4\ub125\uc158\uc744 \ud655\ubcf4\ud55c\ub2e4. \\n\ub530\ub77c\uc11c readOnly \ud2b8\ub79c\uc7ad\uc158\uc774 \uc124\uc815\ub41c \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ubbf8\ub9ac \ud655\ubcf4\ub41c \ucee4\ub125\uc158\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 replica db\ub85c \uc694\uccad\uc744 \ud558\uc9c0 \uc54a\uace0 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4. \\n\\nTransactionSynchronizationManager.isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc \ud638\ucd9c \uc2dc currentTransactionReadOnly\ub77c\ub294 `ThreadLocal`\uc5d0 \uc124\uc815\ub41c \uac12\uc744 \ubc18\ud658\ud558\ub294\ub370 readOnly \uc124\uc815\uc774 \ub418\uba74 \uc774 \uac12\uc744 true\ub85c \uc124\uc815\ud55c\ub2e4. \ud558\uc9c0\ub9cc determineCurrentLookupKey\ub97c \ud638\ucd9c\ud558\uc5ec key \uac12\uc744 \uac00\uc838\uc624\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc774\ud6c4\uc5d0 \uc124\uc815\ub418\uae30 \ub54c\ubb38\uc5d0 determineCurrentLookupKey \uba54\uc11c\ub4dc\uc5d0\uc11c \ud56d\uc0c1 DataSourceType.SOURCE\uac00 \ubc18\ud658\ub418\uc5b4 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4. \\n\\nLazyConnectionDataSourceProxy\ub97c \uc124\uc815\ud558\ub294 \uacbd\uc6b0 \uc2e4\uc81c DataSource\ub97c \uc0ac\uc6a9\ud558\ub294 \uc2dc\uc810\uc5d0 \ucee4\ub125\uc158\uc744 \ud68d\ub4dd\ud574\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc124\uc815\ud55c\ub300\ub85c replica db\ub85c \uc870\ud68c \uc694\uccad\uc744 \ud55c\ub2e4. \\n\\n```java title=\\"DataSourceConfiguration\\"\\n@Configuration\\npublic class DataSourceConfiguration {\\n\\n @Bean\\n @Qualifier(SOURCE_NAME)\\n @ConfigurationProperties(prefix = \\"spring.datasource.source\\")\\n public DataSource sourceDataSource() {\\n return DataSourceBuilder.create().build();\\n }\\n\\n @Bean\\n @Qualifier(REPLICA_NAME)\\n @ConfigurationProperties(prefix = \\"spring.datasource.replica\\")\\n public DataSource replicaDataSource() {\\n return DataSourceBuilder.create().build();\\n }\\n\\n @Bean\\n @Qualifier(ROUTING_NAME)\\n public DataSource routingDataSource(\\n @Qualifier(SOURCE_NAME) DataSource sourceDataSource,\\n @Qualifier(REPLICA_NAME) DataSource replicaDataSource\\n ) {\\n return RoutingDataSource.from(Map.of(\\n DataSourceType.SOURCE, sourceDataSource,\\n DataSourceType.REPLICA, replicaDataSource\\n ));\\n }\\n\\n @Bean\\n @Primary\\n public DataSource dataSource(\\n @Qualifier(ROUTING_NAME) DataSource routingDataSource\\n ) {\\n return new LazyConnectionDataSourceProxy(routingDataSource);\\n }\\n}\\n```\\n\\n\ucd5c\uc885\uc801\uc73c\ub85c DataSource \ube48\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ud615\ud0dc\uac00 \ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n DSP[LazyConnectionDataSourceProxy] --\x3e RDS[RoutingDataSource]\\n\\tRDS --\x3e S[SourceDataSource]\\n\\tRDS --\x3e R[ReplicaDataSource]\\n```\\n\\n### \ub3d9\uc791 \ud655\uc778\\n\\n\uac04\ub2e8\ud558\uac8c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\uc11c \uc124\uc815\ud55c\ub300\ub85c \ub3d9\uc791\uc774 \ub418\ub294\uc9c0 \ud655\uc778\ud574\ubcf4\uc558\ub2e4. \\nsave \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 `@Transactional`, findById \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 `@Transactional(readOnly = true)`\uac00 \uc124\uc815\ub418\uc5b4\uc788\ub2e4. \\n\ub85c\uadf8\ub97c \ud1b5\ud574 save\uc758 \uacbd\uc6b0 source db\ub85c findById\uc758 \uacbd\uc6b0 replica db\ub85c \uc694\uccad\uc744 \ud558\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub2e4. \\n\\n```java title=\\"MemberServiceTest\\"\\n@SpringBootTest\\nclass MemberServiceTest {\\n\\n @Autowired\\n private MemberService memberService;\\n\\n @Test\\n void \uc0ac\uc6a9\uc790\ub97c_\uc800\uc7a5\ud55c\ub2e4() {\\n // RoutingDataSource log: readOnly = false\\n memberService.save(\\"bbiac\\");\\n }\\n\\n @Test\\n void \uc0ac\uc6a9\uc790\ub97c_\uc870\ud68c\ud55c\ub2e4() {\\n // RoutingDataSource log: readOnly = true\\n assertThatThrownBy(() -> memberService.findById(MAX_VALUE))\\n .isInstanceOf(NoSuchElementException.class);\\n }\\n}\\n```\\n\\nDB\uc5d0\uc11c\ub294 \ud655\uc778\ud558\ub824\uba74 root \uacc4\uc815\uc73c\ub85c \uc811\uc18d\ud55c \ud6c4 general log\ub97c \ud65c\uc131\ud654 \uc2dc\ud0a8\ub2e4. \\n\\n```sql\\nSET GLOBAL log_output = \'table\';\\nSET GLOBAL general_log = 1;\\n```\\n\\ngeneral log\ub97c \ud65c\uc131\ud654 \ud55c \ud6c4 \uc77d\uae30 \uc804\uc6a9 \uba54\uc11c\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4. \\nserver_id, \uc2e4\ud589\ud55c \ucffc\ub9ac\ubb38\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\nSELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like \'%select%\';\\n\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n| user_host | thread_id | server_id | convert(argument using utf8) |\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n| user[user] @ [172.25.0.1] | 277 | 2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n```\\n\\n\ud655\uc778 \ud6c4 general log\ub97c \ube44\ud65c\uc131\ud654 \ud55c \ud6c4 \ube44\ud65c\uc131\ud654 \ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\n```sql\\nSET GLOBAL general_log = 0;\\nSHOW VARIABLES LIKE \'%general%\';\\n\\n+------------------+---------------------------------+\\n| Variable_name | Value |\\n+------------------+---------------------------------+\\n| general_log | OFF |\\n| general_log_file | /var/lib/mysql/4b6b9db98290.log |\\n+------------------+---------------------------------+\\n```\\n\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n16\uc7a5 \ubcf5\uc81c, Real MySQL 8.0 - \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Replication, MySQL Docs](https://dev.mysql.com/doc/refman/8.1/en/replication.html) \\n[MySql - Master Slave Replication \uad6c\uc870 \ub9cc\ub4e4\uc5b4\ubcf4\uae30](https://huisam.tistory.com/entry/mysql-replication) \\n[Spring \ub808\ud50c\ub9ac\ucf00\uc774\uc158 \ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac \ubc29\uc2dd](https://cheese10yun.github.io/spring-transaction/) \\n[replication-datasource](https://github.com/kwon37xi/replication-datasource) \\n[Simplified Guide to MySQL Replication with Docker Compose](https://www.linkedin.com/pulse/simplified-guide-mysql-replication-docker-compose-rakesh-shekhawat/) \\n[Dockerfile\uc5d0\uc11c \uc790\uc8fc \uc4f0\uc774\ub294 \uba85\ub839\uc5b4](https://www.daleseo.com/dockerfile/) \\n[CHANGE REPLICATION SOURCE TO Statement](https://dev.mysql.com/doc/refman/8.1/en/change-replication-source-to.html) \\n[LazyConnectionDataSourceProxy](https://kwonnam.pe.kr/wiki/springframework/lazyconnectiondatasourceproxy) \\n[\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ub808\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ud1b5\ud55c \ucffc\ub9ac \uc131\ub2a5 \uac1c\uc120 (feat. Mysql, SpringBoot)](https://hudi.blog/database-replication-with-springboot-and-mysql/) \\n[\ubd80\ud558 \ubd84\uc0b0\uc744 \uc704\ud55c MySQL Replication \uad6c\uc131 \ubc0f \ucffc\ub9ac \uc694\uccad \ubd84\uae30](https://chagokx2.tistory.com/100) \\n[Use Docker Compose, Docker](https://docs.docker.com/get-started/08_using_compose/)"},{"id":"woowacourse-level3-retrospective","metadata":{"permalink":"/woowacourse-level3-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx","source":"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","description":"\ud68c\uace0","date":"2023-08-19T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 19\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.945,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","slug":"woowacourse-level3-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"},"nextItem":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","permalink":"/cloudwatch"}},"content":"import logo from \'./logo.png\';\\n\\n### \ud68c\uace0\\n\\n\uc9c0\ub09c 8\uc8fc\ub294 \ub808\ubca8 1, 2 \ub54c\ubcf4\ub2e4 5\ubc30 \uc815\ub3c4 \ube60\ub974\uac8c \uc9c0\ub098\uac04 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub808\ubca8 3\uc5d0\ub294 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4, \uae30\uc220 \uc678\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4 \ubd80\uc871\ud568\uc774 \ub9ce\uc774 \ubcf4\uc600\ub358 \uac83 \uac19\ub2e4. \\n\ubd80\uc871\ud55c \ubd80\ubd84\uc744 \uc54c\uc558\uae30\uc5d0, \uc55e\uc73c\ub85c \ub354\uc6b1 \uc131\uc7a5\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ub0b4\uac00 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \ud300\uc6d0\ub4e4\uc774 \uc798 \ubcf4\ucda9\ud574 \uc918\uc11c \ub4e0\ub4e0\ud588\ub2e4. \\n\\n### \uc544\uc26c\uc6b4 \uc810\\n\\n**\ubb38\uc11c\ud654**\\n\\n\uac1c\uc778\uc801\uc73c\ub85c\ub294 \uae30\uc220 \uc678\uc801\uc73c\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ub0b4\uac00 \ud55c \ubd80\ubd84\uc744 \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c, \uc774\ud574\ud558\uae30 \uc27d\uac8c \ubb38\uc11c\ud654\ub97c \ud588\ub354\ub77c\uba74 \ud300\uc6d0\ub4e4\uc5d0\uac8c \ub354\uc6b1 \ub3c4\uc6c0\uc774 \ub418\uc5c8\uc744 \ud150\ub370 \uc774 \ubd80\ubd84\uc5d0 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ud22c\uc790\ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc5d0\uc11c \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\ubc29\ud559 \uae30\uac04 \ub3d9\uc548 \ubb38\uc11c\ud654\ub97c \ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc778 \ube14\ub85c\uadf8 \uc62c\ub9ac\uba74\uc11c \uc870\uae08 \ub354 \ucc44\uc6cc\ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n**\ub0b4\uac00 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc774\uc790**\\n\\n\uc798 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc5ec\uc11c\ub77c\ub3c4 \uc911\uac04\uc740 \uac00\ub3c4\ub85d \ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub9d0\uc744 \ud558\uae30 \uc804\uc5d0 \uc815\ub9ac\ud574\uc11c \uc758\uacac\uc744 \ub0b4\ub294 \uac83, \ubc1c\ud45c \uc900\ube44, \uac10\uc815 \uc870\uc808 \ub4f1\ub4f1\\n\ubabb\ud558\ub294 \ubd80\ubd84\uc744 \uc778\uc9c0\ud558\uace0, \uac1c\uc120\ud558\uc790. \\n\\n**\ucef4\ud3ec\ud2b8 \uc874 \ubc97\uc5b4\ub098\uae30**\\n\\n\uc870\uae08 \ub354 \ub3c4\uc804\uc801\uc73c\ub85c \ubaa9\ud45c\ub97c \uc7a1\uc558\uc73c\uba74 \uc88b\uc558\uc744 \uac83 \uac19\ub2e4. \\n\ub9e4\ubc88 \uadfc\uac70\ub97c \uac00\uc9c0\uace0 \uae30\uc220\uc744 \ub3c4\uc785\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub824\uace0 \ud558\ub294 \ubd80\ubd84\uc774 \ub2e4\uc18c \ubd80\uc871\ud588\ub2e4. \\n\\n### \uc88b\uc558\ub358 \uc810\\n\\n**\uc88b\uc558\ub358 \uc810\ub3c4 \ubb38\uc11c\ud654**\\n\\n[\ud300 \ube14\ub85c\uadf8](https://tripdraw.blog)\ub3c4 \uba3c\uc800 \ub3c4\uc785\ud558\uc790\uace0 \uc81c\uc548\ud558\uace0, \ub0b4\uac00 \ud588\ub358 \ubd80\ubd84\uc740 \ubb38\uc11c\ud654\ub97c \uaf64 \ub9ce\uc774 \ud574\uc11c \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubc31\uc5d4\ub4dc \ud06c\ub8e8 4\uba85\uc774\uc11c \uac19\uc774 \ud55c \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c\ub294 \uae30\ub2a5 \uad6c\ud604\ud55c\ub2e4\uace0 \ubb38\uc11c\ud654\uac00 \uc870\uae08 \ubbf8\ud761\ud574\uc11c \ubcf4\ucda9\uc744 \ud574\uc57c\uaca0\ub2e4. \\n\\n**\ub0b4\uac00 \ub514\uc790\uc778\ud55c \ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0**\\n\\n\\n\\n\ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. \\n\ud300\uc6d0\ub4e4\uc774 \ub300\ud45c \uc0c9\uc0c1(\ud30c\ub780\uc0c9)\uc744 \uc815\ud574\uc92c\uace0, \uc8fc\ub9d0 \ub3d9\uc548 \uc2e0\ub098\uac8c \ub85c\uace0 \ub514\uc790\uc778\uc744 \ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc544\ub798\uc758 D \ubd80\ubd84\uc740 \uc720\ud29c\ube0c \uac15\uc758 \ub4e4\uc73c\uba74\uc11c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\uc11c \ubfcc\ub4ef\ud558\ub2e4. \\n\\n**\uae30\uc220 \uc120\ud0dd\uc758 \uc774\uc720**\\n\\n\uae30\uc220\uc758 \ud559\uc2b5 \ube44\uc6a9, \ud604\uc7ac \uad6c\uc870\uc5d0 \uc801\ud569\ud55c\uc9c0, \uc2e4\uc81c \uac00\uc9c0\uace0 \uc788\ub294 \ub9ac\uc18c\uc2a4\ub97c \uace0\ub824\ud574\uc11c \uae30\uc220 \uc120\ud0dd\uc744 \ud558\uace0, \ub3c4\uc785\ud588\ub358 \ubd80\ubd84\uc774 \uc88b\uc558\ub2e4. \\n100% \uc88b\uc740 \uc120\ud0dd\uc77c \uc21c \uc5c6\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \uc120\ud0dd\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \uc874\uc7ac\ud55c\ub2e4\uba74 \ud655\ub960\uc744 \ub192\ud600\uc8fc\ub294 \uac83 \uac19\ub2e4. \\n\\n### \ub9c8\uce58\uba70\\n\\n\ud50c\ub808\uc774\uc2a4\ud1a0\uc5b4\uc5d0 \uc571\uc774 \uc62c\ub77c\uac00 \uc788\ub294 \uac70 \ub108\ubb34 \uc2e0\uae30\ud558\ub2e4. \\n\uc548\ub4dc\ub85c\uc774\ub4dc \ube0c\ub808\uba58 \uc74c\uc545\ub300(\uba67\ub3fc\uc9c0, \uc218\ub2ec, \ud551\uad6c), \uadf8\ub9ac\uace0 \ubc31\uc5d4\ub4dc \ud300\uc6d0\ub4e4(\uccb4\uc778\uc800, \ud6c4\ucd94, \ub9ac\uc624) \ub108\ubb34 \uace0\uc0dd\uc774 \ub9ce\uc558\ub2e4."},{"id":"cloudwatch","metadata":{"permalink":"/cloudwatch","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md","source":"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md","title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","description":"CloudWatch","date":"2023-08-17T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 17\uc77c","tags":[{"label":"cloudwatch","permalink":"/tags/cloudwatch"},{"label":"log","permalink":"/tags/log"},{"label":"monitoring","permalink":"/tags/monitoring"}],"readingTime":5.35,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","slug":"cloudwatch","tags":["cloudwatch","log","monitoring"]},"unlisted":false,"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","permalink":"/route-image-async-with-event"}},"content":"## CloudWatch\\n\\nAWS \ub9ac\uc18c\uc2a4\uc640 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc9c0\ud45c\uc640 \ub85c\uadf8\uc5d0 \ub300\ud55c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc81c\uacf5\ud558\ub294 \uc11c\ube44\uc2a4\ub2e4. \\n\uc9c0\ud45c\ub97c \uac10\uc2dc\ud558\uc5ec \uc54c\ub9bc\uc744 \ubcf4\ub0b4\ub294 \uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4. \\n\ud504\ub9ac\ud2f0\uc5b4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \ub300\uc2dc\ubcf4\ub4dc\ub2f9 3$/M \uc758 \ube44\uc6a9\uc774 \uccad\uad6c\ub418\uace0, \uc9c0\ud45c\ub098 \ub85c\uadf8\uc758 \uc591\uc5d0 \ub530\ub77c \ube44\uc6a9\uc774 \ucd94\uac00\uc801\uc73c\ub85c \uccad\uad6c\ub41c\ub2e4. \\n\uc694\uae08 \uc815\ubcf4\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \uc815\ubcf4\ub294 [\ub2e4\uc74c \ub9c1\ud06c](https://aws.amazon.com/ko/cloudwatch/pricing/)\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n## CloudWatch Metrics\\n\\n\uae30\ubcf8\uc801\uc73c\ub85c 5\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc218\uc9d1\ub41c\ub2e4. \\n\uc138\ubd80 \ubaa8\ub2c8\ud130\ub9c1(Detailed Monitoring)\uc744 \ud65c\uc131\ud654\ud558\uba74 1\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\ub97c \uc218\uc9d1\ud55c\ub2e4. \\n\ub300\uc2dc\ubcf4\ub4dc\uc5d0\uc11c InstanceId\ub85c \uac80\uc0c9\ud558\uc5ec \uc218\uc9d1\ub41c \uc9c0\ud45c\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.\\n\\n![./cloudwatch1.png](./cloudwatch1.png)\\n\\nCPUUtilization, NetworkIn, NetworkOut\uacfc \uac19\uc740 \uae30\ubcf8\uc801\uc778 \uc9c0\ud45c\ub97c \uc81c\uacf5\ud558\uace0, \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud06c \uacf5\uac04\uacfc \uac19\uc740 \uc9c0\ud45c\ub97c \ud655\uc778\ud558\ub824\uba74 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\ub97c \uc124\uc815\ud574\uc57c \ud55c\ub2e4.\\n\\n## CloudWatch Agent \uc124\uce58\\n\\nCloudWatch Agent \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\uc640 \ub85c\uadf8\ub97c \uc218\uc9d1\ud560 \uc218 \uc788\ub2e4. \\n\\n### IAM \uc5ed\ud560 \uc124\uc815\\n\\n\uae30\ubcf8\uc801\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4\uac00 CloudWatchAgentServerPolicy\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4. \\nIAM \u2192 \uc5ed\ud560\uc5d0\uc11c \uc5ed\ud560 \uc0dd\uc131\uc744 \ud074\ub9ad\ud55c\ub2e4.\\n\\n![./cloudwatch2.png](./cloudwatch2.png)\\n\\nCloudWatchAgentServerPolicy \uad8c\ud55c \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uace0, \uc801\ub2f9\ud55c \uc5ed\ud560 \uc774\ub984\uc744 \uc785\ub825\ud574\uc11c \uc5ed\ud560\uc744 \uc0dd\uc131\ud55c\ub2e4.\\n\\n![./cloudwatch3.png](./cloudwatch3.png)\\n\\nEC2 \uc778\uc2a4\ud134\uc2a4 \ubaa9\ub85d\uc73c\ub85c \ub4e4\uc5b4\uac00\uc11c, CloudWatch Agent\ub97c \uc124\uce58\ud560 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud074\ub9ad\ud55c\ub2e4. \\n\uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc5d0\uc11c \uc774\uc804\uc5d0 \uc0dd\uc131\ud55c \uc5ed\ud560\uc744 \uc9c0\uc815\ud55c\ub2e4.\\n\\n![./cloudwatch4.png](./cloudwatch4.png)\\n\\n### \uc124\uce58\\n\\n\ud658\uacbd\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\nOS: ubuntu 22.04 \\n\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small (ARM64) \\n\\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uce58\ud55c\ub2e4.\\n\\n```bash\\nwget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb\\nsudo dpkg -i -E ./amazon-cloudwatch-agent.deb\\n```\\n\\n[\uc0ac\uc6a9 \uc124\uba85\uc11c](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html)\uc5d0 \uac01 \uc778\uc2a4\ud134\uc2a4 \uc720\ud615\ub9c8\ub2e4 \ub2e4\uc6b4\ub85c\ub4dc \ub9c1\ud06c\uac00 \uc790\uc138\ud558\uac8c \uc548\ub0b4\ub418\uc5b4 \uc788\ub2e4.\\n\\n### Wizard\\n\\nCloudWatch Wizard\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uc124\uc815 \ud30c\uc77c \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4. \\n\ub85c\uadf8\ub97c \uc218\uc9d1\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub294 \uacbd\uc6b0 Wizard \uc2e4\ud589 \uba85\ub839\uc5b4 \uc785\ub825 \uc804 log \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \ubcf5\uc0ac\ud574\ub450\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec Wizard\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nsudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard\\n```\\n\\n\uc124\uc815\uc744 \uc9c4\ud589\ud558\ub2e4 \ubcf4\uba74 \uc124\uc815 \ud30c\uc77c\uc774 \uc5b4\ub5bb\uac8c \uad6c\uc131\ub420\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\ub85c\uadf8\ub97c \ucd94\uac00\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \uc785\ub825\ucc3d\uc774 \ub098\uc624\uba74 \uc900\ube44\ud574\ub480\ub358 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \uc785\ub825\ud55c\ub2e4. \\n\\n![./cloudwatch5.png](./cloudwatch5.png)\\n\\n\uc911\uac04\uc5d0 SSM parameter store\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4. \\n\\n```bash\\nDo you want to store the config in the SSM parameter store?\\n1. yes\\n2. no\\n```\\n\\n\ucd94\uac00\uc801\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 2\ubc88\uc744 \uc120\ud0dd\ud55c\ub2e4. \\nParameter Store \uad00\ub9ac\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc758 [\ubb38\uc11c](https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/)\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac70 \uac19\ub2e4. \\n\uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 `/opt/aws/amazon-cloudwatch-agent/bin/config.json` \uc5d0 \uc124\uc815\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774 \uc800\uc7a5\ub41c\ub2e4. \\n\\n### \uc124\uc815 \ud30c\uc77c \uc801\uc6a9\\n\\n\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uc815\ud30c\uc77c\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4. \\nfile \ub4a4\uc5d0\ub294 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \uc808\ub300\uacbd\ub85c(\uc544\ub798 \uba85\ub839\uc5b4 \uae30\uc900 \uae30\ubcf8 \uc0dd\uc131 \uc704\uce58)\ub97c \uc785\ub825\ud558\uba74 \ub41c\ub2e4. \\n\\n```bash\\nsudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json\\n```\\n\\n### types.db: no such file or directory \uc5d0\ub7ec\\n\\n\ub2e4\uc74c\uacfc \uac19\uc740 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 types.db \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4.\\n\\n```bash\\nError running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory\\n```\\n\\ntypes.db \ud30c\uc77c \uc0dd\uc131\\n\\n```bash\\nsudo mkdir /usr/share/collectd\\nsudo touch /usr/share/collectd/types.db\\n```\\n\\n### \uc9c0\ud45c \ud655\uc778\\n\\nCloudWatch Metrics\uc5d0 \uac00\ubcf4\uba74 CWAgent\ub77c\ub294 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uac00 \ucd94\uac00\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4. \\n\\n![./cloudwatch6.png](./cloudwatch6.png)\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ucd94\uac00\ud558\uc5ec \uc9c0\ud45c\uc5d0 \ub300\ud55c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. \\n\\n```json\\n{\\n \\"metrics\\": {\\n \\"namespace\\": \\"2023-hello-world\\",\\n ......\\n },\\n} \\n```\\n\\n### \ub85c\uadf8\\n\\nCloudWatch \u2192 \ub85c\uadf8 \uadf8\ub8f9\uc73c\ub85c \uac00\uba74 Wizard\ub85c \ucd94\uac00\ud55c \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.\\n\\n![./cloudwatch7.png](./cloudwatch7.png)\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[CloudWatch\ub780 \ubb34\uc5c7\uc785\ub2c8\uae4c?](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) \\n[Amazon CloudWatch \uc694\uae08](https://aws.amazon.com/ko/cloudwatch/pricing/) \\n[Linux \uc778\uc2a4\ud134\uc2a4 \uc9c0\ud45c](https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) \\n[\uc11c\ubc84\uc5d0 CloudWatch \uc5d0\uc774\uc804\ud2b8 \uc124\uce58 \ubc0f \uc2e4\ud589](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html) \\n[CloudWatch Agent\ub97c Parameter Store\uc5d0\uc11c \uad00\ub9ac\ud574 \ubcf4\uae30](https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/) \\n[CloudWatch\uc5d0\uc774\uc804\ud2b8 \uad6c\uc131 \ud30c\uc77c](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html)"},{"id":"route-image-async-with-event","metadata":{"permalink":"/route-image-async-with-event","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx","source":"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","description":"\uc774\uc804 \uae00","date":"2023-08-13T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 13\uc77c","tags":[{"label":"async","permalink":"/tags/async"},{"label":"event","permalink":"/tags/event"}],"readingTime":11.2,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","slug":"route-image-async-with-event","tags":["async","event"]},"unlisted":false,"prevItem":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","permalink":"/cloudwatch"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","permalink":"/route-image-implementation"}},"content":"## \uc774\uc804 \uae00\\n\\n[\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd](./route-image-intro) \\n[\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604](./route-image-implementation)\\n\\n## \uac1c\uc694\\n\\n\ud604\uc7ac \uc5ec\ud589\uc744 \ub9c8\uce58\ub294 \uacbd\uc6b0, \uac10\uc0c1\uc744 \uc0dd\uc131\ud558\ub294 \uacbd\uc6b0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \uc704\uce58 \uc815\ubcf4\uc758 \uac1c\uc218\uc5d0 \uc815\ube44\ub840\ud558\uc5ec \uc0dd\uc131 \uc2dc\uac04\uc774 \uc99d\uac00\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ube44\ub3d9\uae30\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uc5ec \uc0ac\uc6a9\uc790\uc758 \uacbd\ud5d8\uc744 \uac1c\uc120\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n### \uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120\\n\\n\uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc774 \uc8fc\uae30\ub2a5\uc774\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ubd80\uae30\ub2a5\uc774\ub2e4. \\n\ud558\uc9c0\ub9cc \ud604\uc7ac \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc758 \uc751\ub2f5 \uc18d\ub3c4\uac00 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uace0 \uc788\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uc5ec\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4. \\n\uc18c\uc694 \uc2dc\uac04\uc774 1\ucd08 \uc774\uc0c1 \uac78\ub9ac\ub294 \uacbd\uc6b0\uac00 \uc874\uc7ac\ud558\uae30\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uace0 \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131 \uae30\ub2a5\uc758 \uc751\ub2f5 \uc2dc\uac04\uc744 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc911\uc694\ud558\ub2e4. \\n\\n### \ud655\uc7a5\uc131 \ub300\ube44\\n\\n\ud604\uc7ac 10\ubd84 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc11c\ubc84\uc5d0 \uc800\uc7a5\ud558\uace0 \uc788\ub2e4. \\n\uc870\uae08 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uadf8\ub9ac\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 \uc5ec\ud589\uc5d0 \ub9ce\uc740 \uc704\uce58 \uc815\ubcf4\uac00 \uc800\uc7a5\ub420 \uc218\ubc16\uc5d0 \uc5c6\uace0 \ub530\ub77c\uc11c \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uac78\ub9ac\ub294 \uc2dc\uac04\uc774 \ub354 \uae38\uc5b4\uc9c8 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ucd94\ud6c4\uc5d0 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0\ub97c \ub300\ube44\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \ud569\ub2f9\ud558\ub2e4. \\n\\n## \ube44\ub3d9\uae30 \ucc98\ub9ac\\n\\n@Async\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uba54\uc11c\ub4dc\ub97c \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \\n\\n### \ube44\ub3d9\uae30 \uc124\uc815\\n\\n\uc0ac\uc6a9\ud558\uae30 \uc804\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c EnableAsync \uc124\uc815\uc744 \ud574\uc57c\ud55c\ub2e4. \\n\ud574\ub2f9 \uc124\uc815\uc744 \uc801\uc6a9\ud558\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc\uc5d0 @Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uae30\ub9cc \ud558\uba74 \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud55c\ub2e4. \\n\\n```java title=\\"AsyncConfig\\"\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig {\\n}\\n```\\n\\n\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud560 \ub54c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ub808\ub4dc \ud480 \uc124\uc815\uc744 \ub530\ub85c \ud574\uc918\uc57c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ThreadPoolTaskExecutor\ub97c \ub530\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \uae30\ubcf8\uc801\uc73c\ub85c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uac00 \uc0dd\uc131\uc744 \ub3c4\uc640\uc900\ub2e4. \\n\\n> In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.\\n> 7.7. Task Execution and Scheduling, Spring Boot Docs\\n\\n### @Async \uc801\uc6a9\\n\\n\uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\uc5d0 Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud55c\ub2e4. \\n\\n```java title=\\"RouteImageGenerator\\"\\n@Async\\npublic void generate(\\n List latitudes,\\n List longitudes,\\n List pointedLatitudes,\\n List pointedLongitudes,\\n Long tripId\\n) {\\n // \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);\\n Coordinates coordinates = Coordinates.of(latitudes, longitudes);\\n Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);\\n drawImage(coordinates, routeImageDrawer, pointedCoordinates);\\n\\n // \uc774\ubbf8\uc9c0 \uc800\uc7a5\\n String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());\\n\\n // \uc790\uc6d0 \ud560\ub2f9 \ud574\uc81c\\n routeImageDrawer.dispose();\\n\\n // \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac12 \ubcc0\uacbd\\n Trip trip = tripRepository.findById(tripId)\\n .orElseThrow();\\n trip.changeRouteImageUrl(imageUrl);\\n tripRepository.save(trip);\\n}\\n```\\n\\n### \ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810\\n\\n\ud604\uc7ac \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uace0 \uc800\uc7a5 \ud6c4, \uc800\uc7a5 \uacbd\ub85c\ub97c DB\uc5d0 \ubc18\uc601\ud574\uc57c \ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ud615\ud0dc\uac00 \ub418\uba70 \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4. \\n\\n```mermaid\\ngraph LR\\n trip[trip: \uc5ec\ud589 \uad00\ub828 \ud328\ud0a4\uc9c0] --\x3e draw[draw: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294 \ud328\ud0a4\uc9c0]\\n draw --\x3e trip\\n```\\n\\n\uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uacfc \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph draw\\n\\t\\tdirection LR\\n\\t\\tRG[RouteImageGenerator] -- DB \ubc18\uc601 \uc694\uccad --\x3e ILR[ImageLinkTripRepository]\\n\\tend\\n subgraph trip\\n\\t\\tdirection LR\\n\\t\\tTS[TripService] -- \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e RG\\n\\t\\tILRI[ImageLinkTripRepositoryImpl] -- \uad6c\ud604 --\x3e ILR\\n\\tend\\n\\n\\ttrip --\x3e draw\\n```\\n\\n\ud328\ud0a4\uc9c0 \uac04 \uc758\uc874\uc131\uc740 \ud574\uacb0\ub418\uc5c8\uc9c0\ub9cc, \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5\uc744 \uc704\ud574 tripId\ub97c \ubc1b\uc544\uc57c\ud558\ub294 \ub4f1\uc758 \ub17c\ub9ac\uc801\uc778 \uc758\uc874\uc131\uc740 \uc544\uc9c1 \ud574\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4. \\n\ub530\ub77c\uc11c \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\n\\n## \uc774\ubca4\ud2b8 \uc0ac\uc6a9\\n\\n\uc2a4\ud504\ub9c1\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uba74 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ube44\uad00\uc2ec\uc0ac(ex. \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131)\uc744 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4.\\n\\n### \uc774\ubca4\ud2b8 \ubc1c\ud589\\n\\n\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud574\uc57c \ud55c\ub2e4. \\n\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 ApplicationEventPublisher \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \uc218 \uc788\ub2e4. \\n\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c ApplicationContext\uac00 \uad6c\ud604\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud55c\ub2e4. \\n\\n```java title=\\"TripService & TripUpdateEvent\\"\\npublic void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {\\n ...\\n\\n // \uc774\ubca4\ud2b8 \ubc1c\ud589\\n applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));\\n}\\n\\npublic record TripUpdateEvent(Long tripId) {\\n}\\n```\\n\\n\uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \ub54c \ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc774 \uc911\uc694\ud558\ub2e4. \\n\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\ub294 \ub3c4\uba54\uc778\uc758 \ud589\uc704\ub97c \ub2f4\uace0 \uc788\ub294 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589(ex. RouteImageGenerateEvent)\ud55c\ub2e4\uba74 \ub17c\ub9ac\uc801\uc778 \uc758\uc874 \uad00\uacc4\uac00 \ub0a8\uc544\uc788\uae30\uc5d0 \uc774\ubca4\ud2b8\ub97c \uc801\uc808\ud788 \uc0ac\uc6a9\ud588\ub2e4\uace0 \ubcf4\uae30 \uc5b4\ub835\ub2e4. \\n\ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc740 \uc8fc\uae30\ub2a5\uc774 \uc5b4\ub5a4 \ud589\uc704(ex. TripUpdateEvent)\ub97c \ud588\ub294\uc9c0\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 \uc774\ubca4\ud2b8\uba85\uc73c\ub85c \ubc1c\ud589\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4. \\n\\n### \uc774\ubca4\ud2b8 \uad6c\ub3c5\\n\\n\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc2e4\ud589\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\uae30 \uc704\ud558\uc5ec `@Async` \uc560\ub108\ud14c\uc774\uc158\uc744 \uc801\uc6a9\ud588\ub2e4. \\n\uc774\ubca4\ud2b8\uc758 \uad6c\ub3c5\uc740 \uc5ec\ud589\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc\ub420 \ub54c \uc5ec\ud589\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 `@TransactionalEventListener`\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\\n:::note TransactionPhase \uc124\uc815\\nTransactionPhase\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \uc774\ubca4\ud2b8\ub97c \uc5b4\ub5a4 \ub2e8\uacc4\uc5d0\uc11c \uc218\uc2e0\ud558\uace0 \ucc98\ub9ac\ud560\uc9c0\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n\\nAFTER_COMMIT(\uae30\ubcf8\uac12): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ucee4\ubc0b \ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nAFTER_ROLLBACK: \ud2b8\ub79c\uc7ad\uc158\uc774 \ub864\ubc31\ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nAFTER_COMPLETION: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub610\ub294 \ub864\ubc31 \ub418\uc5c8\uc744 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nBEFORE_COMMIT: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub418\uae30 \uc804 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\n:::\\n\\n\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uae30 \uc704\ud574 @Transactional \uc560\ub108\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\\n```java title=\\"TripUpdateEventHandler\\"\\n@Component\\npublic class TripUpdateEventHandler {\\n\\n private final RouteImageGenerator routeImageGenerator;\\n private final TripRepository tripRepository;\\n\\n public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {\\n this.routeImageGenerator = routeImageGenerator;\\n this.tripRepository = tripRepository;\\n }\\n\\n @Async\\n @TransactionalEventListener(phase = AFTER_COMMIT)\\n public void handle(TripUpdateEvent tripUpdateEvent) {\\n Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());\\n\\n String imageUrl = routeImageGenerator.generate(\\n trip.getLatitudes(),\\n trip.getLongitudes(),\\n trip.getPointedLatitudes(),\\n trip.getPointedLongitudes()\\n );\\n\\n trip.changeRouteImageUrl(imageUrl);\\n tripRepository.save(trip);\\n }\\n}\\n```\\n\\n\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c\uc368 \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ubb38\uc81c\uac00 \ub2e4\uc74c\uacfc \uac19\uc774 \ud574\uacb0\ub418\uc5c8\ub2e4. \\n\ub610\ud55c \uc8fc\uae30\ub2a5\uacfc \ubd80\uae30\ub2a5\uc744 \ubd84\ub9ac\ud568\uc73c\ub85c\uc368 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uc5c8\ub2e4.\\n\\n```mermaid\\ngraph LR\\n subgraph trip\\n TripServcie -- \ubc1c\ud589 --\x3e TripUpdateEvent\\n TripRepository\\n end\\n\\n subgraph draw\\n TripUpdateEventHandler -- \uad6c\ub3c5 \ud6c4 \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e TripUpdateEvent\\n TripUpdateEventHandler -- \uc0dd\uc131\ub41c \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5 --\x3e TripRepository\\n end\\n```\\n\\n### \ud14c\uc2a4\ud2b8\\n\\n\ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```java\\n@SpringBootTest\\npublic class TripUpdateEventHandlerIntegrationTest {\\n\\n ...\\n\\n @Test\\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\\n // given\\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\\n .willReturn(\uc5ec\ud589());\\n\\n // when\\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\\n\\n // then\\n then(routeImageGenerator)\\n .should(Mockito.timeout(5000).times(1))\\n .generate(any(), any(), any(), any());\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\n@ContextConfiguration(classes = TestSyncConfig.class)\\n@SpringBootTest\\npublic class TripUpdateEventHandlerIntegrationTest {\\n\\n ...\\n\\n @Test\\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\\n // given\\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\\n .willReturn(\uc5ec\ud589());\\n\\n // when\\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\\n\\n // then\\n then(routeImageGenerator)\\n .should(times(1))\\n .generate(any(), any(), any(), any());\\n }\\n}\\n```\\n\\n\\n\\n\\n\ucc98\uc74c\uc5d0\ub294 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub9cc \ub3d9\uae30\ub85c \uc124\uc815 \ud6c4 \uac80\uc99d\ud558\ub824\uace0 \ud588\ub2e4. \\n\ud1b5\ud569 \ud14c\uc2a4\ud2b8\uc5d0\uc120 `\ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1 \uc885\ub8cc\ub418\uc5c8\uc744 \ub54c \ube44\ub3d9\uae30\ub85c \uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0` \uac80\uc99d\uc774 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc885\uc801\uc73c\ub85c `Mockito.timeout` \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \ud1b5\uacfc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4. \\n\\n## \uacb0\uacfc\\n\\n![./time.png](./time.png)\\n\\n\uc704 \uc751\ub2f5 \uc2dc\uac04\uc740 \uc704\uce58 \uc815\ubcf4 1000\uac1c\ub97c \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud55c \uac12\uc774\ub2e4. \\n\uc751\ub2f5 \uc2dc\uac04\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ud3ec\ud568\ub418\uc9c0 \uc54a\uc544\uc11c \uc131\ub2a5\uc774 \uac1c\uc120\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4. \\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[7.7. Task Execution and Scheduling, Spring Boot Docs](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.task-execution-and-scheduling) \\n[Spring Events, Baeldung](https://www.baeldung.com/spring-events) \\n[\ud68c\uc6d0\uc2dc\uc2a4\ud15c \uc774\ubca4\ud2b8\uae30\ubc18 \uc544\ud0a4\ud14d\ucc98 \uad6c\ucd95\ud558\uae30](https://techblog.woowahan.com/7835/)"},{"id":"route-image-implementation","metadata":{"permalink":"/route-image-implementation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx","source":"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","description":"\uac1c\uc694","date":"2023-08-02T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 2\uc77c","tags":[{"label":"image","permalink":"/tags/image"},{"label":"awt","permalink":"/tags/awt"}],"readingTime":11.665,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","slug":"route-image-implementation","tags":["image","awt"]},"unlisted":false,"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","permalink":"/route-image-async-with-event"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","permalink":"/route-image-python"}},"content":"## \uac1c\uc694\\n\\n\uc5ec\ud589\uc5d0 \ub300\ud55c \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\uae30 \uc704\ud574 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d \ubc0f \uae30\uc220 \uc120\ud0dd\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 [\ub9c1\ud06c](./route-image-intro)\uc5d0 \uc788\ub2e4.\\n\\n### \uad6c\ud604 \uacb0\uacfc\\n\\n![./result.png](./result.png)\\n\\n\uc608\uc2dc \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n**\uc11c\uc6b8\uc5ed(\uc810)** \u2192 \uc2e0\uc0ac\uc5ed \u2192 \ub178\ub7c9\uc9c4\uc5ed \u2192 \ud64d\ub300\uc785\uad6c\uc5ed \u2192 \uc885\ub85c3\uac00\uc5ed \u2192 \uc625\uc218\uc5ed \u2192 **\uad6c\ub85c\uc5ed(\uc810)** \u2192 \uc2e0\ub9bc\uc5ed \u2192 \ubc1c\uc0b0\uc5ed\\n\\n```java title=\\"\uc608\uc2dc \ub370\uc774\ud130\\"\\nList x = List.of(\\n 126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,\\n 126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639\\n);\\nList y = List.of(\\n 37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,\\n 37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184\\n);\\nList xPoints = List.of(126.97094933811682, 126.88474839801178);\\nList yPoints = List.of(37.55302829553499, 37.50129417536773);\\n```\\n\\n### IMAGE_SIZE & ROUTE_SIZE\\n\\n```java title=\\"RouteImageGenerator.java\\"\\nprivate static final int IMAGE_SIZE = 800;\\nprivate static final int ROUTE_SIZE = 600;\\n```\\n\\n\ucf54\ub4dc\ub97c \ubcf4\uba74 IMAGE_SIZE\uc640 ROUTE_SIZE\uac00 \uc788\ub2e4. \\nIMAGE_SIZE\ub294 \ub9d0 \uadf8\ub300\ub85c \uc774\ubbf8\uc9c0\uc758 width\uc640 height\ub97c \uc758\ubbf8\ud55c\ub2e4. \\nROUTE_SIZE\uc758 \uacbd\uc6b0 \uc0c1\ud558\uc88c\uc6b0 100px \ub9cc\ud07c\uc758 \uac04\uaca9\uc744 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \uc2e4\uc81c \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub294 600 * 600 \uc0ac\uc774\uc988\ub85c \uc0dd\uc131\ub41c\ub2e4. \\n\\n![./600.png](./600.png)\\n\\n**\uc0ac\uc774\uc988 \ubcc0\uacbd\uc758 \uc774\uc720**\\n\\n255 * 255 \uc815\ub3c4\uc758 \uc791\uc740 \uc0ac\uc774\uc988\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud574\ubcf4\ub824\uace0 \ud588\ub294\ub370, \uc774\ubbf8\uc9c0\uc758 \uc120\uba85\ub3c4\uac00 \uc88b\uc9c0 \uc54a\uc544 800 * 800 \uc0ac\uc774\uc988\ub85c \ubcc0\uacbd\ud588\ub2e4.\\n\\n## \uc8fc\uc694 \ud074\ub798\uc2a4\\n\\n### \uc694\uc57d\\n\\n| \ud074\ub798\uc2a4\uba85 | \uc124\uba85 | \ud2b9\uc774\uc0ac\ud56d |\\n| --- | --- | --- |\\n| Coordinate | \uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \uc704\uce58 \uac12 | \uc88c\ud45c\ub97c \ub73b\ud558\uc9c0\ub9cc \uc5ec\ud589 \ub3c4\uba54\uc778\uc5d0 \ud3ec\ud568\ub41c Point \ud074\ub798\uc2a4\uc640 \uad6c\ubd84\ud558\uae30 \uc704\ud574 longitude, latitude\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 x, y \uc0ac\uc6a9 |\\n| Coordinates | Coordinate\uc758 \uc77c\uae09 \uceec\ub809\uc158 | - |\\n| Position | \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58 \uac12 | Integer \ud0c0\uc785\uc758 x, y \uc0ac\uc6a9 |\\n| Positions | Positions\uc758 \uc77c\uae09 \uceec\ub809\uc158 | - |\\n| RouteImageDrawer | \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4 BufferedImage, Graphics2D\ub97c \uac00\uc9c0\uace0 \uc788\uc74c | \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc0c1\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc74c |\\n| RouteImageUploader | BufferedImage\ub97c \ubc1b\uc544 \uc11c\ubc84\uc5d0 \uc5c5\ub85c\ub4dc \ud558\ub294 \ud074\ub798\uc2a4 | \ud604\uc7ac \uc5c5\ub85c\ub4dc \uc704\uce58\uac00 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc544 \uc77c\ub2e8 \uae30\ubcf8(\ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8) \uc704\uce58\uc5d0 \uc0dd\uc131 |\\n| RouteImageGenerator | \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uace0 \uc5c5\ub85c\ub4dc\ud558\ub294 \uc11c\ube44\uc2a4 | \uc5ec\ud589 \uc885\ub8cc, \uac10\uc0c1 \uc800\uc7a5\uc2dc \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad |\\n| BufferedImage(AWT) | \uc774\ubbf8\uc9c0 \ub370\uc774\ud130\ub97c \ucc98\ub9ac\ud558\uace0 \uc870\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9 | \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c\uac00 (0, 0) |\\n| Graphics2D(AWT) | \uc120 \uadf8\ub9ac\uae30, \uc0c9\uc0c1 \uad00\ub9ac \ub4f1\uc744 \uc9c0\uc6d0\ud558\ub294 \ud074\ub798\uc2a4 \uc2e4\uc81c \ud574\ub2f9 \ud074\ub798\uc2a4\uc758 draw \uba54\uc11c\ub4dc\ub97c \uacbd\ub85c\ub97c \uadf8\ub9bc | JDK 1.2 \uc774\ud6c4\uc5d0 \ucd94\uac00\ub428, 2D(\ud3c9\uba74) \uadf8\ub798\ud53d \ud658\uacbd\uc744 \uc9c0\uc6d0, bufferedImage.createGraphics \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \uc0dd\uc131 |\\n\\n### \uc758\uc874\uad00\uacc4\\n\\n```mermaid\\ngraph TD\\n C1[Coordinates] --\x3e C[Coordinate]\\n P1[Positions] --\x3e P[Position]\\n\\n\\tRID[RouteImageDrawer] -- \\"\uc911\uc559 \uc815\ub82c\ub41c Positions\ub97c \ubc1b\uc544 \uc774\ubbf8\uc9c0 \uc0dd\uc131\\" --\x3e P1\\n\\tRID --\x3e B[BufferedImage]\\n\\tRID --\x3e G[Graphics2D]\\n\\n\\tC1 -- \\"calculatePositions \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc704\uce58 \uacc4\uc0b0\\" --\x3e P1\\n\\n\\tRIU[RouteImageUploader] --\x3e B\\n\\tRIG[RouteImageGenerator] --\x3e RID\\n\\tRIG --\x3e RIU\\n\\tRIG --\x3e C1\\n\\tRIG --\x3e P1\\n```\\n\\n### Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)\\n\\n`List` 2\uac1c(\uc704\ub3c4, \uacbd\ub3c4)\uc778 \ud615\ud0dc\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uc5c8\uc9c0\ub9cc, \uc704\uce58 \uc810\uc744 \uc5ec\ub7ec\uac1c \ucc0d\ub294 \ubd80\ubd84\uc5d0\uc11c \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud574 \uc9c8 \uac83 \uac19\uc544\uc11c Coordinate(x, y)\uc640 \uc77c\uae09 \uceec\ub809\uc158\uc778 Coordinates\ub85c \uad00\ub9ac\ud558\uae30\ub85c \ud588\ub2e4. \\nCoordinates \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub450 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- calculatePositions: \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub97c \ubc1b\uc544 \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \uc0ac\uc6a9\ub420 Positions\ub97c \ubc18\ud658\\n- indexOf: \ub2e4\ub978 Coordinates\ub97c \ubc1b\uc544 \ub3d9\uc77c\ud55c \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4\ub97c \ubc18\ud658\ud558\ub294 \\n\\nPositions \uacc4\uc0b0 \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\uc704\ub3c4, \uacbd\ub3c4 \uac01\uac01\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \ud544\uc694\ud55c \uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4.\\n\\n```java title=\\"Coordinates.java\\"\\n// \ud638\ucd9c\\n// List xPositions = toPositions(xValues, maxDifference, routeImageSize);\\n// List yPositions = toPositions(yValues, maxDifference, routeImageSize);\\n\\nprivate List toPositions(List values, Double maxDifference, Integer routeImageSize) {\\n Double minValue = Collections.min(values);\\n return values.stream()\\n .map(value -> normalizeCoordinate(value, maxDifference, minValue))\\n .map(value -> mapToPosition(value, routeImageSize))\\n .toList();\\n}\\n\\nprivate double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {\\n return (coordinate - minValue) / maxDifference;\\n}\\n\\nprivate int mapToPosition(Double coordinate, Integer routeImageSize) {\\n return (int) (coordinate * routeImageSize);\\n}\\n```\\n\\n\uc704\ub3c4\ub85c \uc608\uc2dc\ub4e0 \ub0b4\uc6a9\uc774\ub2e4.\\n\\n1. Collections.min(values) \u2192 \uc704\ub3c4 \ub9ac\uc2a4\ud2b8\uc758 \ucd5c\uc18c\uac12\uc744 \uad6c\ud55c\ub2e4.\\n2. normalizeCoordinate \u2192 \uac01\uac01\uc758 \uc704\ub3c4 \uac12\uc5d0\uc11c \ucd5c\uc18c\uac12\uc744 \ube7c\uace0 0 ~ 1 \uc0ac\uc774 \uac12\uc73c\ub85c \ubcc0\ud658 \ud6c4 **\uc704\uacbd\ub3c4\uc758 \ucd5c\ub300 \ucc28\uc774**\ub85c \ub098\ub208\ub2e4.\\n3. mapToPosition \u2192 \uadf8\ub798\ud504 \ud06c\uae30\ub97c \ubc1b\uc544 0 ~ 1 \uc0ac\uc774 \uac12\uc744 \uc2e4\uc81c \uc774\ubbf8\uc9c0\ub97c \uc704\ud55c \uc704\uce58\uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4.\\n\\n### Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)\\n\\nPositions \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub2e4\uc12f \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- align: \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\uc640 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\ub97c \ubc1b\uc544 Position \uac12\ub4e4\uc744 \uc911\uc559 \uc815\ub82c\ud55c\ub2e4.\\n- getPositionsByIndexes: \uc778\ub371\uc2a4 \ub9ac\uc2a4\ud2b8\ub97c \ubc1b\uc544 \uc785\ub825\ubc1b\uc740 \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n- size: \ud06c\uae30\ub97c \ubc18\ud658\ud55c\ub2e4.\\n- xPositions: x \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n- yPositions: y \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n\uc911\uc559 \uc815\ub82c \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```java title=\\"Positions.java\\"\\npublic Positions align(int imageSize, int routeSize) {\\n int xOffset = calculateOffset(Position::x, imageSize);\\n int yOffset = calculateOffset(Position::y, imageSize);\\n\\n return items.stream()\\n .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))\\n .collect(collectingAndThen(toList(), Positions::new));\\n}\\n\\nprivate int calculateOffset(ToIntFunction positionToInteger, int imageSize) {\\n List positions = items.stream()\\n .mapToInt(positionToInteger)\\n .boxed()\\n .toList();\\n\\n int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;\\n return imageSize / 2 - midValue;\\n}\\n```\\n\\n\uc0c1\ud558\uc88c\uc6b0 \uc5ec\ubc31\uc744 \ub3d9\uc77c\ud558\uac8c \uc8fc\uae30 \uc704\ud574\uc11c offset \uac12\uc744 \uad6c\ud574\uc11c x, y \uac12\uc5d0 \uac01\uac01 \ub354\ud558\ub294 \ud615\ud0dc\ub85c \uc911\uc559 \uc815\ub82c\uc744 \uc218\ud589\ud588\ub2e4. \\nBufferedImage\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c (0, 0) \uae30\uc900\uc73c\ub85c \uc544\ub798\ub85c \ub0b4\ub824\uac08\uc218\ub85d y \uac12\uc774 \ucee4\uc9c0\uace0, \uc624\ub978\ucabd\uc73c\ub85c \uac08 \uc218\ub85d x \uac12\uc774 \ucee4\uc9c4\ub2e4. \\n\\n![./800.png](./800.png)\\n\\n\ub530\ub77c\uc11c \ucd5c\uc885\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c \uac12\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud588\ub2e4.\\n\\nx \uac12 \u2192 \uacc4\uc0b0\ud55c offset \uadf8\ub300\ub85c \ub354\ud55c\ub2e4. \\ny \uac12 \u2192 imageSize(800)\uc5d0\uc11c y + offset \uac12\uc744 \ube80\ub2e4. \\n\\n### RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)\\n\\nBufferedImage, Graphics2D\ub97c \ud544\ub4dc\ub85c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub2e4. \\n\uadf8\ub9bc\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \uc124\uc815\ud55c \uc0c1\uc218\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4.\\n\\n```java title=\\"RouteImageDrawer.java\\"\\n// RGB\uc5d0 \uac01\uac01 8\ube44\ud2b8\uc529 \ud560\ub2f9\ud55c \uac12\uc744 24\ube44\ud2b8 \ud2b8\ub8e8\uceec\ub7ec\ub77c \ubd80\ub978\ub2e4.\\n// \ud574\ub2f9 \uc124\uc815\uc740 24\ube44\ud2b8 + 8\ube44\ud2b8(alpha, \ud22c\uba85\ub3c4)\ub97c \ucd94\uac00\ud55c 32\ube44\ud2b8 \uc774\ubbf8\uc9c0 \ud0c0\uc785\uc774\ub2e4.\\n// \uc774\ub97c RGBA\ub77c\uace0 \ubd80\ub978\ub2e4.\\nprivate static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;\\n// \ubc30\uacbd \ud22c\uba85\uc0c9\\nprivate static final Color TRANSPARENT = new Color(0, 0, 0, 0);\\n// \uacbd\ub85c\ub97c \uc704\ud55c STROKE\\nprivate static final int LINE_STROKE_WIDTH = 7;\\nprivate static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\\n// \uc704\uce58 \uc810\uc744 \uc704\ud55c STROKE\\nprivate static final int POINT_STROKE_WIDTH = 20;\\nprivate static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\\n// \uc548\ud2f0\uc568\ub9ac\uc5b4\uc2f1 \ub4f1 \ud654\uc9c8 \uac1c\uc120\uc744 \uc704\ud55c \uc124\uc815\\nprivate static final Map renderingHints = Map.of(\\n RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,\\n RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,\\n RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC\\n);\\n```\\n\\nRouteImageDrawer \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \uc138 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- drawLine: \uc120\uc744 \uadf8\ub9b0\ub2e4.\\n- drawPoint: \uc810\uc744 \ucc0d\ub294\ub2e4.\\n- dispose: \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud55c\ub2e4. \\n\\ndispose\uc758 \uacbd\uc6b0 \ub0b4\ubd80\uc5d0\uc11c \uc0dd\uc131\ub41c graphics2D\uc5d0 \ub300\ud55c \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud558\ub294 \uba54\uc11c\ub4dc\uc778 graphics2D.dispose\ub97c \ud638\ucd9c\ud55c\ub2e4.\\n\\n## \uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow\\n\\n### 1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44\\n\\n```mermaid\\nsequenceDiagram\\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\\n\\n```\\n\\n### 2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\\n```\\n\\n### 3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\\n\\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n```\\n\\n### 4. \uc5c5\ub85c\ub4dc \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n \\tRouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\\n \\tRouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n \\tRouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n```\\n\\n### \uc804\uccb4 Flow\\n\\n```mermaid\\nsequenceDiagram\\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\\n\\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\\n RouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n RouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n\\t\\n```"},{"id":"route-image-python","metadata":{"permalink":"/route-image-python","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx","source":"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","description":"\uac1c\uc694","date":"2023-07-31T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 31\uc77c","tags":[{"label":"Image","permalink":"/tags/image"},{"label":"Python","permalink":"/tags/python"}],"readingTime":6.185,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","slug":"route-image-python","tags":["Image","Python"]},"unlisted":false,"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","permalink":"/route-image-implementation"},"nextItem":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","permalink":"/mock-static-method"}},"content":"### \uac1c\uc694\\n\\n\uc774\uc804\uc5d0 \uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\uc0ac\ud558\uba74\uc11c \ud30c\uc774\uc36c\uc744 \uc0ac\uc6a9\ud55c \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud55c \ub0b4\uc6a9\uc774\ub2e4. \\n\\n### \uc0ac\uc6a9 \uae30\uc220\\n\\n\uc5b8\uc5b4: Python 3.10 \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131: matplotlib \\n\uc11c\ube44\uc2a4: AWS Lambda, AWS API Gateway \\n\uc774\ubbf8\uc9c0 \uc800\uc7a5 \ubc0f URL: AWS S3, AWS CloudFront \\n\\n\ud50c\ub85c\uc6b0\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```mermaid\\ngraph LR\\n Server -- \uc0dd\uc131 \uc694\uccad --\x3e AG[API Gateway] --\x3e Lambda --\x3e S3\\n Client --\x3e CloudFront --\x3e S3\\n```\\n\\n### \uc694\uad6c\uc0ac\ud56d\\n\\n![./route.png](./route.png)\\n\\n\uc6b0\uce21 \uc0c1\ub2e8\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub824\uace0 \ud55c\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.\\n\\n- \uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \ubc30\uc5f4\uc744 \uc785\ub825\ubc1b\ub294\ub2e4. \\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n- \uc120\uacfc \uc810 \ud45c\ud604\\n- \ud22c\uba85\ud55c \ubc30\uacbd\uc0c9\\n- \uc704\uacbd\ub3c4 \ucc28\uc774\uac00 \ud06c\ub4e0 \uc791\ub4e0 \uc81c\uacf5\ud558\ub294 \uc774\ubbf8\uc9c0 \ub0b4\uc5d0 \uacbd\ub85c\uac00 \ub2e4 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### \uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\\n\\n1. \uc704\uacbd\ub3c4\ub97c \ucc98\ub9ac\ud55c \uac12\uc73c\ub85c \uc9c1\uc811 \uacbd\ub85c\ub97c \uadf8\ub9b0 \ub2e4\uc74c \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5\\n2. \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc0ac\uc6a9\ud558\uc5ec \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5\\n\\n\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\uc758 \uacbd\uc6b0 1\ubc88\uacfc 2\ubc88\uc744 \uace0\ubbfc\ud588\uc5c8\ub2e4. \\n\ud30c\uc774\uc36c\uc73c\ub85c\ub294 \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc778 matplotlib\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604\\n\\n```python\\nimport time\\n\\nimport matplotlib.pyplot as plt\\n\\n\\ndef draw(point):\\n start = time.time()\\n x, y = zip(*point)\\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\\n draw_lines(pixel_x, pixel_y)\\n end = time.time()\\n print(end - start)\\n \\ndef convert_to_pixel_values(x, y):\\n max_diff = max(max(x) - min(x), max(y) - min(y))\\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\\n\\n\\ndef scale_to_pixel_values(points, max_diff):\\n min_value = min(points)\\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\\n return scaled_coordinates\\n\\n\\ndef draw_lines(x, y):\\n figure = plt.gcf()\\n figure.set_size_inches(5, 5)\\n plt.plot(x, y, c = \'w\',linewidth=5)\\n plt.scatter(x[3],y[3], c = \'w\', s = 125)\\n plt.axis(\'off\')\\n plt.savefig(\'name.png\', transparent=True, format=\'png\')\\n\\npoint = [\\n [126.96352960597338, 37.590841000217125],\\n [126.96987292787792, 37.58435564234159],\\n [126.98128481452298, 37.58594375113966],\\n [126.99360339342958, 37.58248524741927],\\n [126.99867565340067, 37.56778118088622],\\n [127.001935378366117, 37.55985240444085],\\n [126.9831048919687, 37.548030119488665],\\n [126.97189273528845, 37.5119879225856],\\n [127.02689859997221, 37.48488593333883]\\n]\\n\\ndraw(point)\\n```\\n\\n\uc0dd\uc131 \uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4. (\uc608\uc2dc\ub97c \uc704\ud574 \uac80\uc740\uc0c9\uc73c\ub85c \ucd9c\ub825)\\n\\n![./routeImage.png](./routeImage.png)\\n\\n### AWS Lambda\\n\\n\uc378\ub124\uc77c \uc0dd\uc131 \uc11c\ubc84\ub97c \ub530\ub85c \ub450\uae30\ub294 \uae30\ub2a5 \ub300\ube44 \ube44\uc6a9\uc774 \ub108\ubb34 \ud074 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub530\ub77c\uc11c \uc11c\ubc84\ub9ac\uc2a4\ub85c \ud30c\uc77c\uc744 \ucc98\ub9ac\ud588\ub2e4. \\n\ucd94\uac00\ub85c s3 \uc811\uadfc\uc740 boto3\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131\\n\\nAmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy \ub450\uac00\uc9c0\ub97c \ucd94\uac00\ud574\uc11c Lambda \uc804\uc6a9 \uc5ed\ud560\uc744 \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc\\n\\n\uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \ud655\uc778\ud560 \ub550 \uc704\uce58 \uc810\uc744 \ucc0d\ub294 \uae30\ub2a5\uc744 \ub78c\ub2e4\uc5d0 \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\\n```python\\n\\nimport io\\nimport uuid\\n\\nimport boto3\\nimport matplotlib.pyplot as plt\\n\\nPIXEL = 255\\nBUCKET_NAME = \'image-plot\'\\nS3 = \'s3\'\\n\\ndef lambda_handler(event, context):\\n x = event[\'x\']\\n y = event[\'y\']\\n image_name = str(uuid.uuid4())\\n\\n img_data = draw(x, y)\\n s3 = boto3.client(S3)\\n s3.put_object(Body=img_data.getvalue(), ContentType=\'image/png\', Bucket=BUCKET_NAME, Key=image_name)\\n url = f\'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}\'\\n\\n return {\\n \'statusCode\': 200,\\n \'body\': url\\n }\\n\\ndef draw(x, y):\\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\\n img_data = draw_lines(pixel_x, pixel_y)\\n plt.close()\\n return img_data\\n\\ndef convert_to_pixel_values(x, y):\\n max_diff = max(max(x) - min(x), max(y) - min(y))\\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\\n\\ndef scale_to_pixel_values(points, max_diff):\\n min_value = min(points)\\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\\n pixel_values = [int(p * PIXEL) for p in scaled_coordinates]\\n return pixel_values\\n\\ndef draw_lines(x, y):\\n plt.plot(x, y, \'k-\', linewidth=10)\\n plt.axis(\'off\')\\n img_data = io.BytesIO()\\n plt.savefig(img_data, transparent=True, format=\'png\')\\n img_data.seek(0)\\n return img_data\\n\\n```\\n\\n### Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131\\n\\nmatplotlib\uc758 \uacbd\uc6b0 \uc678\ubd80 \ub77c\uc774\ube0c\ub7ec\ub9ac\uae30 \ub54c\ubb38\uc5d0 \ub530\ub85c Layer\ub97c \ucd94\uac00\ud574\uc57c \ud55c\ub2e4. \\nzip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \uc5c5\ub85c\ub4dc\ud574\uc57c\ud55c\ub2e4. \\n\uc774\ub54c python\uc758 Lambda \ub7f0\ud0c0\uc784\uc5d0 \ub300\ud55c \uacc4\uce35 \uacbd\ub85c\ub294 python\uc774\ub2e4. \\n\ub530\ub77c\uc11c \uc555\ucd95\ud55c zip \ud30c\uc77c\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \ub744\uc5b4\uc57c \ud55c\ub2e4. \\n\\n```\\npillow.zip\\n\u2502 python/PIL\\n\u2514 python/Pillow-5.3.0.dist-info\\n```\\n\\nUbuntu \uae30\uc900 \ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc0dd\uc131\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\\n```\\nsudo apt update\\nsudo apt install zip\\nsudo apt install python3-pip\\n\\nmkdir python\\npip3 install matplotlib -t python # pip3 install \uc124\uce58\ud560_\ud328\ud0a4\uc9c0 -t \uc124\uce58_\uacbd\ub85c\\nzip -r my_layer.zip python # zip -r \uc555\ucd95_\ud30c\uc77c\uba85 \uc555\ucd95_\ud30c\uc77c\uc774_\uc874\uc7ac\ud558\ub294_\uacbd\ub85c\\n```\\n\\n### `No module named \'numpy.core._multiarray_umath\'` \uc5d0\ub7ec\\n\\nLayer \ucd94\uac00 \ud6c4 \ub78c\ub2e4 \uc2e4\ud589 \uc2dc \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\uc600\ub2e4. \\n\ucc98\uc74c\uc5d0 mac\uc5d0\uc11c zip \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc5c5\ub85c\ub4dc\ud588\ub294\ub370 \ud574\ub2f9 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\uc774\ub294 lambda\uac00 \ub3cc\uc544\uac00\ub294 \ub3d9\uc77c\ud55c \ud658\uacbd\uc5d0\uc11c layer\ub97c \uc704\ud55c zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc9c0 \uc54a\uc544\uc11c \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub2e4. \\n\uac04\ub2e8\ud558\uac8c ec2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c \ub530\ub85c Layer\ub97c \uc0dd\uc131\ud558\uba74 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\n### \uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01\\n\\n\ud504\ub85c\uc81d\ud2b8\uc5d0 Lambda\uc640 Python\uc744 \uc0ac\uc6a9\ud558\ub824\uace0 \ud588\uc9c0\ub9cc \uc544\uc27d\uac8c\ub3c4 \ubc18\ub824\ub2f9\ud588\ub2e4. \\nAWS Lambda\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc778\uc2a4\ud134\uc2a4\uc5d0 \ud574\ub2f9 \ucf54\ub4dc\ub97c \ubc30\ud3ec\ud558\ub294 \uac83\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc77c \uc218 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uac00\uc6a9 \uac00\ub2a5\ud55c \uc790\uc6d0, \uae30\uc220\uc758 \ub09c\uc774\ub3c4, \uc0ac\uc6a9\ud558\ub294 \ud300\uc6d0\uc744 \uace0\ub824\ud55c\ub2e4\uba74 Lambda\ub294 \uc801\uc815\uae30\uc220\uc774 \uc544\ub2d0 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ud574\ub2f9 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\ub97c \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud560\uc9c0 \uc870\uae08 \ub354 \uace0\ub824\ub97c \ud574\uc57c \ub420 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4. \\n\\n**\ucd5c\uc885\uc801\uc73c\ub85c Java AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.**\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[AWS Lambda](https://aws.amazon.com/ko/lambda/) \\n[Lambda Layer](https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html) \\n[Python Lambda \ud568\uc218\uc5d0 \ub300\ud55c .zip \ud30c\uc77c \uc544\uce74\uc774\ube0c \uc791\uc5c5](https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html) \\n[No module named \'numpy.core._multiarray_umath\'](https://gist.github.com/ksmin23/0f3f243408a8497f766b43cf589fea7b) \\n[\uc0ac\ub840\ubcc4\ub85c \uc54c\uc544\ubcf8 \uc548\uc804\ud55c S3 \uc0ac\uc6a9 \uac00\uc774\ub4dc](https://techblog.woowahan.com/6217/)"},{"id":"mock-static-method","metadata":{"permalink":"/mock-static-method","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx","source":"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx","title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","description":"\uac1c\uc694","date":"2023-07-30T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 30\uc77c","tags":[{"label":"Mockito","permalink":"/tags/mockito"},{"label":"static","permalink":"/tags/static"}],"readingTime":2.635,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","slug":"mock-static-method","tags":["Mockito","static"]},"unlisted":false,"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","permalink":"/route-image-python"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","permalink":"/route-image-intro"}},"content":"### \uac1c\uc694\\n\\n\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud55c\ub2e4\ub294 \uac83\uc740 \uac1d\uccb4\uc9c0\ud5a5\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ubcfc \ub54c \uc548\ud2f0\ud328\ud134\uc774\ub2e4. \\n\ud558\uc9c0\ub9cc \ud2b9\uc218\ud55c \uacbd\uc6b0\uc5d0\ub294 \uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc774 \ud544\uc694\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n\uc608\ub97c \ub4e4\uc5b4 \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud55c\ub2e4\ub358\uc9c0, IO \uad00\ub828\ud55c \ubd80\ubd84\uc744 \ud14c\uc2a4\ud2b8 \ud560 \ub54c \uc815\ub9d0 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\ub9cc \uc801\uc6a9\ud560 \uc218 \uc788\uc744 \uac83\uc774\ub2e4. \\n\\n\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba70 ImageIo.write \uba54\uc11c\ub4dc\uac00 \ud638\ucd9c\ub418\ub294 \uc9c0 \uac80\uc99d\uc774 \ud544\uc694\ud588\ub2e4. \\n\ud574\ub2f9 static \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294 \ubd80\ubd84\uc744 \ub530\ub85c RouteImageUploader \ud074\ub798\uc2a4\ub85c \ucd5c\ub300\ud55c \ubd84\ub9ac\ud588\ub2e4. \\n\uc774\ubbf8\uc9c0 \uc800\uc7a5 \uae30\ub2a5 \uc790\uccb4\uac00 \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc774\uace0, \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294\ub370\ub294 mock\uc744 \uc0ac\uc6a9\ud558\ub294\uac8c \uc801\uc808\ud558\ub2e4\uace0 \ud310\ub2e8\ud588\ub2e4. \\n\\n```java\\npublic void upload(BufferedImage bufferedImage) {\\n File file = new File(\ud30c\uc77c\uacbd\ub85c);\\n try {\\n ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);\\n } catch (IOException e) {\\n throw new DrawException(IMAGE_SAVE_FAIL);\\n }\\n}\\n```\\n\\n### Mocking static methods\\n\\nMockito 3.4.0 \uc774\ud6c4\uc5d0\ub294 static method\ub97c \ubaa8\ud0b9\ud560 \uc218 \uc788\ub294 Mockito.mockStatic \uba54\uc11c\ub4dc\ub97c \uc9c0\uc6d0\ud55c\ub2e4. \\nmockStatic\uc744 \uc0ac\uc6a9\ud558\uba74 `MockedStatic`\uc774 \ubc18\ud658\ub418\ub294\ub370 \uc0ac\uc6a9 \ud6c4 \uaf2d close\ub97c \ud574\uc918\uc57c \ud55c\ub2e4. \\n\\nJUnit\uc758 @BeforeAll\ub85c \uc124\uc815\ud558\uace0 @AfterAll \uba54\uc11c\ub4dc\ub85c \uc885\ub8cc\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\uc9c0\ub9cc `MockedStatic`\uc758 \uc0c1\uc704 \uc778\ud130\ud398\uc774\uc2a4\uc778 ScopedMock\uc774 AutoCloseable\uc744 \uad6c\ud604\ud558\uace0 \uc788\uae30\uc5d0 try-with-resources\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \ub354\uc6b1 \uc88b\uc740 \uac83 \uac19\ub2e4. \\n\\n```java\\n// given\\nBufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);\\nRouteImageUploader routeImageUploader = new RouteImageUploader();\\n\\n// expect\\ntry (MockedStatic imageIO = Mockito.mockStatic(ImageIO.class)) {\\n routeImageUploader.upload(bufferedImage);\\n imageIO.verify(\\n () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),\\n times(1)\\n );\\n}\\n```\\n\\n### \ub9c8\uce58\uba70\\n\\n\uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc740 \uc548\ud2f0\ud328\ud134\uc774\uc73c\ub85c \uc801\uc808\ud55c \ucd94\uc0c1\ud654\ub97c \uc774\uc6a9\ud574 \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc88b\uc740 \ucf54\ub4dc\ub97c \ub9cc\ub4dc\ub294 \uc5f0\uc2b5\uc744 \ud558\uc790. \\n\ud558\uc9c0\ub9cc \ucd94\uc0c1\ud654\ub97c \ud558\uba74 \ud560 \uc218\ub85d \ucf54\ub4dc\uc758 \ubcf5\uc7a1\ub3c4\ub294 \uc99d\uac00\ud55c\ub2e4. \\n\ud56d\uc0c1 \uc0c1\ud669\uc744 \uace0\ub824\ud558\uace0 \uac04\uacb0\ud568\uc744 \ud3ec\uae30\ud560 \ub9cc\ud07c \uc911\uc694\ud55c \ubd80\ubd84\uc778\uc9c0 \uc801\uc808\ud55c \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uace0\ub824\ud558\uc790. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Mocking static methods](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks) \\n[Mockito mock static methods](https://www.baeldung.com/mockito-mock-static-methods) \\n[Enable mocking static methods in Mockito](https://github.com/mockito/mockito/issues/1013)"},{"id":"route-image-intro","metadata":{"permalink":"/route-image-intro","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx","source":"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","description":"./route.png","date":"2023-07-27T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 27\uc77c","tags":[{"label":"image","permalink":"/tags/image"},{"label":"awt","permalink":"/tags/awt"}],"readingTime":5.865,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","slug":"route-image-intro","tags":["image","awt"]},"unlisted":false,"prevItem":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","permalink":"/mock-static-method"},"nextItem":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","permalink":"/java-spring-springboot"}},"content":"![./route.png](./route.png)\\n\\n### \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784\\n\\n\uc704 \uc640\uc774\uc5b4 \ud504\ub808\uc784\uc5d0\uc11c `\uc5ec\ud589 \ud788\uc2a4\ud1a0\ub9ac`\uc640 `\uc5ec\ud589\uc5d0 \ub300\ud55c \uac10\uc0c1\uc744 \uc704\ud55c \uacbd\ub85c \uc774\ubbf8\uc9c0`\uc758 \uacbd\uc6b0 \ub124\uc774\ubc84 \uc9c0\ub3c4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \uc218 \uc5c6\uc73c\ub2c8 \ub2f9\uc5f0\ud788 \ub9f5 API\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub3c4\ud615 \uadf8\ub9ac\uae30 API(\ub124\uc774\ubc84 \ub9f5 API \uae30\uc900 Polyline)\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4. \\n\ub530\ub77c\uc11c \uc774\ubbf8\uc9c0\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uac70\ub098, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c1\uc811 \uc704\uacbd\ub3c4\ub97c \uc774\uc6a9\ud558\uc5ec \uadf8\ub824\uc57c \ud55c\ub2e4.\\n\\n\ud574\ub2f9 \uc694\uad6c\uc0ac\ud56d\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uae30\ub2a5\uc744 \uac00\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud544\uc694\ud558\ub2e4.\\n\\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n- \uc120\uacfc \uc810 \ud45c\ud604\\n- \ud22c\uba85\ud55c \ubc30\uacbd\uc0c9\\n\\n\ud604\uc7ac \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ubc14\uc05c \uc77c\uc815\uacfc \uae30\ub2a5 \uad6c\ud604\uc5d0 \uc788\uc5b4 \uc57d\uac04\uc758 \uc5f0\uc0b0\uc774 \ub4e4\uc5b4\uac04\ub2e4\ub294 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uc5ec \ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30\ub85c \uacb0\uc815\uc744 \ub0b4\ub838\ub2e4.\\n\\n### \uace0\ub824\ud55c \uae30\uc220\\n\\n\ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uae30 \uc704\ud574 \ub2e4\uc74c\uacfc \uac19\uc740 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 \uae30\uc220\ub4e4\uc744 \ud655\uc778\ud574 \ubcf4\uc558\ub2e4. \\n\\n- Python\uc758 Matplotlib\\n- **AWT(Abstract Window Toolkit) [\ucd5c\uc885 \uc120\ud0dd]**\\n- \uc774\ubbf8\uc9c0 \ucc98\ub9ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ubc0f Java\uc5d0\uc11c \ub0b4\ubd80\uc801\uc73c\ub85c Matplotlib \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac (\uc6d0\ud558\ub294 \uae30\ub2a5 \uc5c6\uc74c)\\n- Java Swing, Java FX (\ub2e8\uc21c\ud55c \uc120 \uadf8\ub9ac\uae30 + \uc810 \ucc0d\uae30\ub77c \ubd88\ud544\uc694)\\n\\n## Python & Matplotlib\\n\\n\ub370\uc774\ud130 \uc2dc\uac01\ud654 \ub77c\uc774\ube0c\ub7ec\ub9ac \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 0.2\ucd08 \\n\\n- \ucf54\ub4dc\uac00 \uac04\ub2e8\ud574\uc11c \uc720\uc9c0 \ubcf4\uc218\uc131\uc774 \uc88b\ub2e4. \\n- AWS Lambda \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ucef4\ud4e8\ud305 \uc11c\ube44\uc2a4\ub098 FastAPI\uc640 \uac19\uc740 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\ub85c \ucd94\uac00\uc801\uc778 API\ub97c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4.\\n- Spring Boot\uc5d0\uc11c \ucd94\uac00\uc801\uc778 API \ud638\ucd9c\uc744 \ud574\uc57c\ud558\uace0, \ud655\uc7a5\uc131\uacfc \ube44\ub3d9\uae30 \ucc98\ub9ac \ub4f1 \uace0\ub824 \ud574\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\ub2e4.\\n\\n### Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\\n\\nPython\uc774 \uc544\ub2cc Java\uc5d0\uc11c\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub3c4 \uace0\ub824\ub97c \ud574\ubd24\uc9c0\ub9cc \uc694\uad6c\uc0ac\ud56d\uc5d0 \uc801\ud569\ud558\uc9c0 \uc54a\uac70\ub098, \uc801\uc740 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac70\uc6b4 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\uc678\ud588\ub2e4.\\n\\n\ub77c\uc774\ube0c\ub7ec\ub9ac | \uc124\uba85 | \uc81c\uc678 \uc774\uc720\\n-- | -- | --\\nSwing | AWT \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, \ub124\uc774\ud2f0\ube0c UI\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubaa8\ub4e0 \uc6b4\uc601\uccb4\uc81c \uc0c1\uc5d0\uc11c \ub3d9\uc77c\ud55c UI\ub97c \uac00\uc9c0\ub3c4\ub85d \ud568 | \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c\\nJavaFX | Swing \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, 3\ucc28\uc6d0 \uadf8\ub798\ud53d\uc744 \uc9c0\uc6d0\ud568 | \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c\\n[simple-java-plot](https://github.com/yuriy-g/simple-java-plot) | AWT\ub85c \uad6c\ud604\ub41c \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac | AWT \uae30\ubc18\uc774\uae34 \ud558\uc9c0\ub9cc \uc9c1\uc811 AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc5d0 \ube44\ud574 \uba54\ub9ac\ud2b8\uac00 \uc5c6\uc74c, \ucee4\uc2a4\ud140 \uc124\uc815 \uae30\ub2a5\uc774 \uc5c6\uc74c\\n[matplotlib4j](https://github.com/sh0nk/matplotlib4j) | Matplotlib\ub97c Java\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud558\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac | \ub0b4\ubd80\uc801\uc73c\ub85c \ud30c\uc774\uc36c \uc0ac\uc6a9\ud558\uae30\uc5d0 \ubb34\uac70\uc6c0, \ubc30\uacbd \ud22c\uba85\ud654 \uae30\ub2a5 \uc5c6\uc74c\\n\\n### Java & AWT(Abstract Window Toolkit)\\n\\n\uadf8\ub798\ud53d\uacfc \uc774\ubbf8\uc9c0\ub97c \uadf8\ub9ac\uae30 \uc704\ud55c \ub3c4\uad6c \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 1.75\ucd08 \\n\\n- \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ubcf4\ub2e4 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc874\uc7ac\ud55c\ub2e4.\\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub2e4\uc18c \uc18c\uc694\ub418\uae30 \ub54c\ubb38\uc5d0 \ube60\ub978 \uc751\ub2f5 \ubc18\ud658\uc744 \uc704\ud574 \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.\\n- \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.\\n\\n### \uae30\uc220 \uc120\ud0dd\\n\\nAWT\uc758 \uacbd\uc6b0 Matplotlib\uc5d0 \ube44\ud574 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc788\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub354 \ub9ce\uc774 \uac78\ub9ac\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub418\ub294 \ubd80\ubd84, Python\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc778 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uace0\ub824\ud558\uc5ec AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.\\n\\n### \uc720\uc9c0 \ubcf4\uc218\\n\\nAWT\ub77c\ub294 \uc0dd\uc18c\ud55c \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc720\uc9c0 \ubcf4\uc218\uc131\uc744 \uc704\ud574 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub530\ub77c\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\ubc95\uc73c\ub85c \uacf5\uc720\ud558\uae30\ub85c \ud588\ub2e4. \\n\\n1. \ucf54\ub4dc \ub9ac\ubdf0\uc640 PR\uc744 \ud1b5\ud574 \uc791\uc131\ud55c AWT \ucf54\ub4dc\uc5d0 \ub300\ud55c \uc124\uba85 \ubc0f \ub9ac\ubdf0 \ubc1b\ub294\ub2e4. \\n2. AWT\ub97c \uc0ac\uc6a9\ud55c \ubd80\ubd84\uc744 \ubb38\uc11c\ud654\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4.\\n\\n### \ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00\\n\\n\uae30\uc220 \uc120\ud0dd\uc744 \ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815\uc5d0 \uc624\ub958\uac00 \uc788\uc5c8\ub2e4. \\nAWT\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589 \uc2dc\uac04\uc744 \uc81c\uc678\ud558\uba74 \ud30c\uc774\uc36c\uacfc \ube44\uc2b7\ud55c \uc2dc\uac04\uc548\uc5d0 \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud560 \uc218 \uc788\uc5c8\ub2e4."},{"id":"java-spring-springboot","metadata":{"permalink":"/java-spring-springboot","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx","source":"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx","title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","description":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","date":"2023-07-24T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 24\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Spring Boot","permalink":"/tags/spring-boot"},{"label":"Spring","permalink":"/tags/spring"}],"readingTime":4.725,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","slug":"java-spring-springboot","tags":["Java","Spring Boot","Spring"]},"unlisted":false,"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","permalink":"/route-image-intro"},"nextItem":{"title":"\uc6f9\uc18c\ucf13","permalink":"/websocket"}},"content":"## \uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\\n\\n\ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\uc744 \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\ub2e4. \\n2.7 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc5c8\uc9c0\ub9cc LTS \uae30\uac04\uacfc \ucde8\uc57d\uc810 \ud328\uce58\ub85c \uc778\ud55c \ubc84\uc804\uc5c5 \ub4f1\uc744 \uace0\ub824\ud588\uc744 \ub54c 3.1\uacfc \uc790\ubc14 17\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \ub354 \ud6a8\uc728\uc801\uc774\ub77c\uace0 \ud310\ub2e8\ud588\ub2e4.\\n\\n## \uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2\uae4c\uc9c0\ub294 \uc790\ubc14 11\uc744 \uc0ac\uc6a9\ud588\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \uc790\ubc14 11\ubd80\ud130 \uc790\ubc14 17\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d\uc744 \uc815\uc2dd \ub9b4\ub9ac\uc988 \uae30\uc900\uc73c\ub85c \uc815\ub9ac\ud574\ubcf4\ub824\uace0 \ud55c\ub2e4.\\n\\n### Switch Expressions(Java 14)\\n\\nJava 14\uc5d0\uc11c\ub294 \uae30\uc874\uc758 Switch \ubb38\uc744 \uac04\uacb0\ud558\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub294 Switch \uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n```java\\nenum RESULT {\\n WIN, LOSE, DRAW\\n}\\n\\nRESULT result = RESULT.WIN;\\n\\nint prize = switch (result) {\\n case WIN -> 10_000_000;\\n case LOSE, DRAW -> 5_000_000;\\n\\tdefault -> 0;\\n};\\n```\\n\\n\uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.\\n\\n- `->` \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 case\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc14\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub2e4.\\n- case\ub97c \ucf64\ub9c8(`,`)\ub85c \uc5f0\uacb0\ud558\uc5ec \ud558\ub098\uc758 case\uc5d0 \uc5ec\ub7ec \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n- break \ubb38\uc774 \ud544\uc694 \uc5c6\ub2e4.\\n- default \ube14\ub85d\uc744 \ud1b5\ud574 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n\\n### Text Block(Java 15)\\n\\nJava 15\uc5d0\ub294 \uc0c8\ub85c\uc6b4 \ubb38\uc790\uc5f4 \ud45c\ud604\ubc29\uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\uae34 \ubb38\uc790\uc5f4\uc744 + \uc5f0\uc0b0\uc790\uc758 \ub3c4\uc6c0 \uc5c6\uc774 \uac00\ub3c5\uc131\uc788\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n@Repository\\npublic interface PostRepository extends JpaRepository {\\n @Query(\\"\\"\\"\\n SELECT p FROM Post p\\n WHERE p.title LIKE %:keyword%\\n OR p.content LIKE %:keyword%\\n \\"\\"\\")\\n List findPostsByTitleOrContentContainingKeyword(String keyword);\\n}\\n```\\n\\n### NPE \uba54\uc2dc\uc9c0(Java 15)\\n\\n```java\\nString name = null;\\nname.chars();\\n\\n/** \\n# before\\njava.lang.NullPointerException\\n\\tat com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)\\n\\n# after\\nCannot invoke \\"String.chars()\\" because \\"name\\" is null\\njava.lang.NullPointerException: Cannot invoke \\"String.chars()\\" because \\"name\\" is null\\n*/\\n```\\n\\n### Record(Java 16)\\n\\nLombok\uc758 `@Data`, kotlin\uc758 data \ud074\ub798\uc2a4\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4. \\nRecord\ub97c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0 \uc811\uadfc\uc790, \uc0dd\uc131\uc790, equals & hashcode, toString\uc774 \uc81c\uacf5\ub41c\ub2e4. \\n\ub370\uc774\ud130 \uc804\uc1a1 \uc6a9\ub3c4\ub85c \uc801\ud569\ud574 \ubcf4\uc778\ub2e4. \\n\\n```java\\npublic record PostDto(String title, String content) {\\n}\\n```\\n\\n### \ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d\\n\\n\uc774\uc678\uc5d0\ub3c4 stream\uc758 toList, \uc778\uc2a4\ud134\uc2a4\uc758 \ud0c0\uc785\uc744 \uac04\ud3b8\ud558\uac8c \uccb4\ud06c\ud558\ub294 Pattern Matching Instanceof, Sealed class \ub4f1\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n## \uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d\\n\\n\uc2a4\ud504\ub9c1\uacfc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\ub3c4 \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \ud544\uc694\ud574\ubcf4\uc774\ub294 \uba87\uac1c \uc815\ub3c4\ub9cc \uc815\ub9ac\ud588\ub2e4. \\n\\n### \uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d\\n\\nJava 17, Jakarta EE 9 \uc774\uc0c1\uc774\uc5b4\uc57c \ud55c\ub2e4.\\n\\n### \ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd\\n\\nJakarta EE 9\uac00 \uc801\uc6a9\ub418\uba74\uc11c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub3c4 \uc804\ubc18\uc801\uc73c\ub85c javax -> jakarta\ub85c \ubcc0\uacbd\ub418\uc5c8\ub2e4. \\n\\n### PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c\\n\\n6.0 \uc774\uc804\uc758 \uacbd\uc6b0 \uae30\ubcf8 \uc124\uc815 \uae30\uc900\uc73c\ub85c `@GetMapping(\\"/hello\\")`\uc640 `@GetMapping(\\"/hello/\\")`\uac00 \ub3d9\uc77c\ud588\ub2e4. \\n6.0 \uc774\ud6c4\uc758 PathPatternParser\uac00 \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0, `/hello`\uc640 `/hello/`\ub294 \uc11c\ub85c \ub2e4\ub978 URL\ub85c \ub9e4\uce6d\ub41c\ub2e4. \\n\\n> PathPatternParser used by default (with the ability to opt into PathMatcher). \\n\\n### HTTP interface client\\n\\n\uc790\ubc14 \uc778\ud130\ud398\uc774\uc2a4\uc640 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc774\uc6a9\ud558\uc5ec HTTP \uc694\uccad\uc744 \uc704\ud55c \uc11c\ube44\uc2a4\ub97c \uc815\uc758\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [\ud1a0\ube44\ub2d8\uc758 \uac15\uc758](https://www.youtube.com/watch?v=Kb37Q5GCyZs)\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n### \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d\\n\\nGradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6 \\n\uc774\uc678\uc5d0\ub3c4 \uc11c\ub4dc\ud30c\ud2f0\ub4e4\uc758 \ucd5c\uc2e0 \ub9b4\ub9ac\uc988 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud568\uc73c\ub85c, \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ubc84\uc804\uc5d0 \ub9de\ub294 \ub9b4\ub9ac\uc988 \ub178\ud2b8\ub97c \ucc38\uace0\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[\uc5b4\ub290\xa0\uc6d4\uae09\uc7c1\uc774\uac1c\ubc1c\uc790\xa0\uc758 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ub530\ub77c\uc7a1\uae30](https://www.youtube.com/watch?v=1WT6oxchM9M) \\n[\uc790\ubc14 9-16 \uc8fc\uc694 \ud2b9\uc9d5 \ubcf5\uc2b5\ud558\uae30](https://www.youtube.com/watch?v=7SlDdzVk6GE) \\n[Java EE\uc5d0\uc11c Jakarta EE\ub85c\uc758 \uc804\ud658](https://www.samsungsds.com/kr/insights/java_jakarta.html) \\n[Spring 6\uc758 \uc0c8\ub85c\uc6b4 HTTP Interface\uc640 3 \uac00\uc9c0 REST Clients \ub77c\uc774\ube0c \ucf54\ub529](https://www.youtube.com/watch?v=Kb37Q5GCyZs) \\n[What\'s New in Spring Framework 6.x](https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-6.x) \\n[Spring Boot 3.0 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes) \\n[Spring Boot 3.1 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes)"},{"id":"websocket","metadata":{"permalink":"/websocket","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-26-WebSocket.mdx","source":"@site/blog/2023-2/2023-06-26-WebSocket.mdx","title":"\uc6f9\uc18c\ucf13","description":"\uc6f9\uc18c\ucf13","date":"2023-06-26T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 26\uc77c","tags":[{"label":"WebSocket","permalink":"/tags/web-socket"}],"readingTime":4.165,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9\uc18c\ucf13","slug":"websocket","tags":["WebSocket"]},"unlisted":false,"prevItem":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","permalink":"/java-spring-springboot"},"nextItem":{"title":"Docusaurus","permalink":"/docusaurus"}},"content":"### \uc6f9\uc18c\ucf13\\n\\n\ub2e8\uc77c TCP \uc5f0\uacb0\uc744 \ud1b5\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04 \uc804\uc774\uc911 \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\ud1a0\ucf5c \\n\uc6f9 \ud658\uacbd\uc5d0\uc11c \uc5f0\uc18d\ub41c \ub370\uc774\ud130\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4. \\n\\n\uc6f9\uc18c\ucf13\uc740 HTTP\uc758 \ud3ec\ud2b8\ub97c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud558\uace0 \uac01\uac01 \ud3ec\ud2b8 80\uacfc \ud3ec\ud2b8 443\uc744 \uc0ac\uc6a9\ud558\uc5ec HTTP(ws://) \ubc0f HTTPS(wss://)\ub85c \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud55c\ub2e4. \\n\\n### \uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd\\n\\n\uc6f9\uc18c\ucf13\uc774 \ub4f1\uc7a5\ud558\uae30 \uc774\uc804, \uc2e4\uc2dc\uac04\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 Polling, Long polling, Streaming \uac19\uc740 \uae30\uc220\uc744 \uc0ac\uc6a9\ud588\uc5b4\uc57c \ud588\ub2e4. \\n\uc774\ub294 \uc2e4\uc2dc\uac04\uc131\uc774\ub098 \uc591\ubc29\ud5a5\uc131\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \ubabb\ud588\uace0, HTTP\ub97c \uc774\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uacfc\ub3c4\ud55c \uc624\ubc84\ud5e4\ub4dc\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\\n:::note polling, long polling, streaming\\n\\nPolling: \uc8fc\uae30\uc801\uc73c\ub85c \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ubcf4\ub0b4 \uc218\uc2e0\ud560 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubc29\ubc95\\n- \uc11c\ubc84\uc5d0\uc11c \ubcf4\ub0bc \ub0b4\uc6a9\uc774 \uc5c6\uc5b4\ub3c4 \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc54c \uc218 \uc5c6\ub2e4. \\n- \uacc4\uc18d\ud574\uc11c \uc694\uccad\uc744 \ubcf4\ub0b4 \ud655\uc778\uc744 \ud574\uc57c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ubd88\ud544\uc694\ud55c \ubd80\ud558\ub97c \uc8fc\uc5b4\uc57c \ud55c\ub2e4. \\n\\nLong Polling: \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc5d0 \ub300\ud574 \uc751\ub2f5\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uace0 \uc788\ub2e4\uac00 \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud588\uc744\ub54c \uc751\ub2f5\ud558\ub294 \ubc29\ubc95\\n- \ud3f4\ub9c1 \ubc29\uc2dd\ubcf4\ub2e4 \uc11c\ubc84\uc5d0 \uc801\uc740 \ubd80\ud558\ub97c \uc904 \uc218 \uc788\uc9c0\ub9cc, \uc694\uccad\uc758 \uc8fc\uae30\uac00 \uc9e7\uc73c\uba74 \ud3f4\ub9c1\uacfc \ucc28\uc774\uac00 \uc5c6\uc5b4\uc9c4\ub2e4.\\n\\nStreaming: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 request\ub97c \ubcf4\ub0b4\uba74 \ucee4\ub125\uc158\uc744 \ub9fa\uace0, \uc774 \ucee4\ub125\uc158\uc744 \uc720\uc9c0\ud558\uba74\uc11c \uc11c\ubc84\uac00 \uacc4\uc18d \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95\\n- \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ud558\uace0 \uc2f6\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ucee4\ub125\uc158\uc744 \ub9fa\uc5b4\uc57c \ud55c\ub2e4. \\n:::\\n\\n### \uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791\\n\\n```mermaid\\nsequenceDiagram\\n participant Client\\n participant Server\\n Client->>Server: Handshake - Upgrade\ub97c \uc774\uc6a9\ud55c WebSocket \uc804\ud658 \uc694\uccad\\n Server->>Client: Handshake - HttpStatus 101(Switching Protocols)\\n\\n Client->>Server: \uc591\ubc29\ud5a5 \ud1b5\uc2e0\\n Server->>Client: \\n\\n Client->>Server: \uc885\ub8cc\\n Server->>Client: \\n```\\n\\n### 1. Upgrade \uc694\uccad\\n\\nWebSocket \ud504\ub85c\ud1a0\ucf5c\ub85c \uc804\ud658\ud558\ub294 HTTP \uc694\uccad\uc744 \ubcf4\ub0b8\ub2e4. \\n\uc774\ub294 HTTP\uc640 \uac19\uc774 80, 443 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud55c\ub2e4. \\n\uc6f9\uc18c\ucf13\uc73c\ub85c \uc804\ud658\ud558\uae30 \uc704\ud574\uc11c\ub294 Upgrade: websocket, Connection: Upgrade \ud5e4\ub354\uac00 \ud544\uc694\ud558\ub2e4. \\nSec-WebSocket-Key\ub294 \uc11c\ubc84\uc5d0\uc11c Sec-WebSocket-Accept\ub97c \uacc4\uc0b0\ud558\uc5ec \uc751\ub2f5\ud558\uace0 \uc774 \uac12\uc774 \uc608\uc0c1\ud55c \uac12\uacfc \ub2e4\ub974\uba74 \uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uc9c0 \uc54a\ub294\ub2e4. \\nSec-WebSocket-Protocol\uc758 \uacbd\uc6b0 \uc11c\ube0c\ud504\ub85c\ud1a0\ucf5c\uc758 \ubaa9\ub85d\uc73c\ub85c \uc11c\ubc84 \uce21\uc5d0\uc11c\ub294 \ud574\ub2f9 \ubaa9\ub85d \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud558\uc5ec \ubc18\ud658\ud574\uc57c \ud55c\ub2e4. \\n\ub9cc\uc57d \uc11c\ubc84\uce21\uc5d0\uc11c \uc5ec\ub7ec \uac1c \uc9c0\uc6d0\uc774 \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc9c0\uc6d0 \uac00\ub2a5\ud55c \ud504\ub85c\ud1a0\ucf5c \uc911 \uccab\ubc88\uc9f8 \ud504\ub85c\ud1a0\ucf5c\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc73c\ub85c \ubcf4\ub0b8\ub2e4. \\n\\n```\\nGET /chats HTTP/1.1\\nHost: localhost:8080\\nUpgrade: websocket\\nConnection: Upgrade\\nSec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==\\nSec-WebSocket-Protocol: v10.stomp, v11.stomp\\nSec-WebSocket-Version: 13\\nOrigin: http://localhost:8080\\n```\\n\\n### 2. Switching Protocols\\n\\n\uc11c\ubc84\ub294 101 Switching Protocols \uc751\ub2f5\uc744 \ubc18\ud658\ud55c\ub2e4. \\nSec-WebSocket-Accept\uc740 Sec-WebSocket-Key \ub4a4\uc5d0 `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`\ub97c \ubd99\uc774\uace0 SHA1\ub85c \ud574\uc2f1 \ud6c4 Base64\ub85c \uc778\ucf54\ub529\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4. \\n\uc774\ub294 \uc11c\ubc84 \uc6f9\uc18c\ucf13 \ud504\ub85c\ud1a0\ucf5c\uc758 \uc9c0\uc6d0 \uc5ec\ubd80\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uba85\ud655\ud788 \uc54c\ub9ac\uae30 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4. \\n\\n```\\nHTTP/1.1 101 Switching Protocols \\nUpgrade: websocket\\nConnection: Upgrade\\nSec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=\\nSec-WebSocket-Protocol: v10.stomp\\n```\\n\\n### 3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc\\n\\n\uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uba74 \uc6f9\uc18c\ucf13 \ud504\ub808\uc784 \ub2e8\uc704\ub85c \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \ud55c\ub2e4. \\n\uc5f0\uacb0 \uc885\ub8cc\ub97c \uc6d0\ud558\ub294 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8, \uc11c\ubc84 \ubaa8\ub450 \uc5f0\uacb0 \uc885\ub8cc\ub97c \uc694\uccad\ud560 \uc218 \uc788\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\nhttps://datatracker.ietf.org/doc/html/rfc6455 \\nhttps://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications \\nhttps://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers \\nhttps://docs.spring.io/spring-framework/reference/web/websocket.html"},{"id":"docusaurus","metadata":{"permalink":"/docusaurus","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx","source":"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx","title":"Docusaurus","description":"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4.","date":"2023-06-18T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 18\uc77c","tags":[{"label":"Documentation","permalink":"/tags/documentation"}],"readingTime":10.095,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Docusaurus","slug":"docusaurus","tags":["Documentation"]},"unlisted":false,"prevItem":{"title":"\uc6f9\uc18c\ucf13","permalink":"/websocket"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","permalink":"/woowacourse-level2-retrospective"}},"content":"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4. \\n\\n## \uc124\uce58\\n\\n[\uacf5\uc2dd \ud648\ud398\uc774\uc9c0](https://docusaurus.io/docs/installation)\uc5d0 \ub4e4\uc5b4\uac00\uc11c \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58\ud55c\ub2e4. \\n\\n```bash\\nyarn create docusaurus\\n````\\n\\n## \ubc30\ud3ec\\n\\n[\ubc30\ud3ec \uc548\ub0b4 \ubb38\uc11c](https://docusaurus.io/docs/next/deployment#deploying-to-github-pages) \\nnetlify\ub098 vercel \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ud50c\ub7ab\ud3fc\uc744 \ucd94\ucc9c\ud558\uace0 \uc788\uace0, \uac04\ub2e8\ud558\uace0, \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \ubc30\ud3ec\ub97c \ud560 \uc218 \uc788\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 github pages\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud55c\ub2e4.\\n\\n### \ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131\\n\\ngithub pages\ub97c \uc774\uc6a9\ud558\ub824\uba74 [\uc608\uc2dc](https://github.com/greeng00se/greeng00se.github.io)\uc640 \uac19\uc774 `username.github.io` \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4. \\n\uc774\ub54c organization\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 `organization.github.io` \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n### \uc124\uc815 \ud30c\uc77c \uc218\uc815\\n\\n```js title=\\"docusaurus.config\\"\\nmodule.exports = {\\n // ...\\n url: \'https://greeng00se.github.io\',\\n baseUrl: \'/\',\\n projectName: \'greeng00se.github.io\',\\n organizationName: \'greeng00se\',\\n trailingSlash: false,\\n // ...\\n};\\n```\\n\\n### \ud1a0\ud070 \uc124\uc815\\n\\ngithub action\uc744 \uc704\ud574 \ubc30\ud3ec\uc6a9 \ud1a0\ud070\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uc5ec \uc0dd\uc131\ud55c \ub808\ud3ec\uc9c0\ud1a0\ub9ac\uc5d0 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 \ud1a0\ud070\uc744 \ud074\ub798\uc2dd \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ud588\uace0 \uc2a4\ucf54\ud504\ub294 [repo, user, workflow] \uc744 \uc124\uc815\ud588\ub2e4. \\n\\n![github](./github.png)\\n\\n### \ube0c\ub79c\uce58 \uc0dd\uc131\\n\\ngithub\uc5d0\uc11c gh-pages \ube0c\ub79c\uce58\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4. \\nrepository -> settings -> pages -> branch\uc5d0\uc11c \uc0dd\uc131\ud55c gh-pages\ub85c \ube0c\ub79c\uce58\ub97c \ubcc0\uacbd\ud55c\ub2e4. \\n\uc124\uc815\ud55c \ube0c\ub79c\uce58\uac00 \ubc30\ud3ec \ube0c\ub79c\uce58\uac00 \ub418\uba70, \ud574\ub2f9 \ube0c\ub79c\uce58\uc5d0 \uc788\ub294 \ud30c\uc77c\ub4e4\uc744 \uc774\uc6a9\ud574\uc11c \uc815\uc801 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc81c\uacf5\ud55c\ub2e4. \\n\\n### \uc6cc\ud06c\ud50c\ub85c \uc791\uc131\\n\\nDocusaurus 2.0 \uae30\uc900 Node.js 16.14 \uc774\uc0c1\uc758 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4. \\n\ubc30\ud3ec\uc2dc\uc5d0\ub294 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c DEPLOY_TOKEN \uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4. \\n\\n```yml title=\\".github/workflows/deploy.yml\\"\\nname: blog\\n\\non:\\n push:\\n branches: [main]\\n\\njobs:\\n deploy:\\n name: Deploy to GitHub Pages\\n runs-on: ubuntu-latest\\n steps:\\n - uses: actions/checkout@v2\\n - uses: actions/setup-node@v3\\n with:\\n node-version: 18\\n cache: yarn\\n\\n - name: Install dependencies\\n run: yarn install --frozen-lockfile\\n - name: Build website\\n run: yarn build\\n\\n - name: Deploy to GitHub Pages\\n uses: peaceiris/actions-gh-pages@v3\\n with:\\n github_token: ${{ secrets.DEPLOY_TOKEN }}\\n publish_dir: ./build\\n user_name: github-actions[bot]\\n user_email: 41898282+github-actions[bot]@users.noreply.github.com\\n```\\n\\n## \ub313\uae00 \uae30\ub2a5\\n\\ngiscus\ub97c \uc774\uc6a9\ud558\uc5ec \ub313\uae00 \uae30\ub2a5\uc744 \ucd94\uac00\ud55c\ub2e4. \\n\\n### giscus \uc124\uc815\\n\\n1. \uacf5\uac1c \uc800\uc7a5\uc18c\uc5ec\uc57c \ud55c\ub2e4.\\n2. giscus \uc571\uc774 \uc124\uce58\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4.\\n3. Discussions \uae30\ub2a5\uc774 \ud574\ub2f9 \uc800\uc7a5\uc18c\uc5d0\uc11c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4.\\n\\n\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [giscus](https://giscus.app/ko)\ub97c \ud655\uc778\ud558\uc790.\\n\\n### docusaurus \uc124\uc815\\n\\n[swizzling](https://docusaurus.io/ko/docs/next/swizzling)\uc744 \uc774\uc6a9\ud558\uc5ec \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac10\uc2fc\ub2e4. \\n\uae30\uc874\uc5d0 \uac8c\uc2dc\ubb3c\uc744 giscus\uac00 \ud3ec\ud568\ub41c \ub9ac\uc561\ud2b8 \ucef4\ud3ec\ub10c\ud2b8\ub85c \uac10\uc2f8\ub294 \ud615\ud0dc\uac00 \ub41c\ub2e4. \\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec BlogPostItem\uc744 \ucd94\ucd9c\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nyarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap\\n```\\n\\n\uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uba74 `/src/theme/BlogPostItem/index.js` \uc704\uce58\uc5d0 \ud30c\uc77c\uc774 \uc0dd\uc131\ub41c\ub2e4. \\n\ud30c\uc77c\uc758 \ub0b4\uc6a9\uc744 \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud558\uace0, \uc774\ub54c setAttribute \ubd80\ubd84\uc740 \uc801\uc808\ud558\uac8c \uc790\uc2e0\uc758 giscus \uc124\uc815\uc744 \uc774\uc6a9\ud55c\ub2e4. \\n\\n```js title=\\"/src/theme/BlogPostItem/index.js\\"\\nimport OriginalBlogPostItem from \\"@theme-original/BlogPostItem\\";\\nimport React, { useEffect, useRef } from \\"react\\";\\n// @ts-expect-error internal code\\nimport { useColorMode } from \\"@docusaurus/theme-common\\";\\nimport { useBlogPost } from \\"@docusaurus/theme-common/internal\\";\\n\\nconst giscusSelector = \\"iframe.giscus-frame\\";\\n\\nfunction BlogPostItem(props) {\\n const { colorMode } = useColorMode();\\n const { isBlogPostPage } = useBlogPost();\\n const giscusTheme = colorMode === \\"dark\\" ? \\"dark\\" : \\"light\\";\\n const containerRef = useRef(null);\\n\\n useEffect(() => {\\n if (!isBlogPostPage) return;\\n\\n const giscusEl = containerRef.current.querySelector(giscusSelector);\\n\\n const createGiscusEl = () => {\\n const script = document.createElement(\\"script\\");\\n\\n script.src = \\"https://giscus.app/client.js\\";\\n script.setAttribute(\\"data-repo\\", \\"teco-chat/teco-chat.github.io\\");\\n script.setAttribute(\\"data-repo-id\\", \\"R_kgDOJZ5j0Q\\");\\n script.setAttribute(\\"data-category\\", \\"Announcements\\");\\n script.setAttribute(\\"data-category-id\\", \\"DIC_kwDOJZ5j0c4CXS_Q\\");\\n script.setAttribute(\\"data-mapping\\", \\"pathname\\");\\n script.setAttribute(\\"data-strict\\", \\"0\\");\\n script.setAttribute(\\"data-reactions-enabled\\", \\"1\\");\\n script.setAttribute(\\"data-emit-metadata\\", \\"0\\");\\n script.setAttribute(\\"data-input-position\\", \\"bottom\\");\\n script.setAttribute(\\"data-theme\\", giscusTheme);\\n script.setAttribute(\\"data-lang\\", \\"ko\\");\\n script.crossOrigin = \\"anonymous\\";\\n script.async = true;\\n \\n containerRef.current.appendChild(script);\\n };\\n\\n const postThemeMessage = () => {\\n const message = {\\n setConfig: {\\n theme: giscusTheme,\\n }\\n };\\n\\n giscusEl.contentWindow.postMessage({ giscus: message }, \\"https://giscus.app\\");\\n };\\n\\n giscusEl ? postThemeMessage() : createGiscusEl();\\n }, [giscusTheme]);\\n\\n return (\\n <>\\n \\n {isBlogPostPage &&
}\\n \\n );\\n}\\n\\nexport default BlogPostItem;\\n```\\n\\n## \uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30\\n\\n\uc54c\uace0\ub9ac\uc544\ub97c \uc0ac\uc6a9\ud558\uba74 \uac80\uc0c9 \uae30\ub2a5\uc744 \ucd94\uac00\ud560 \uc218 \uc788\ub2e4. \\n\uc720\ub8cc \ud50c\ub79c\uc774\ub098 netlify\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ud06c\ub864\ub7ec\ub97c \ub530\ub85c \uc81c\uacf5\ud574 \uc8fc\ub294 \uac83 \uac19\ub2e4. \\n\\n\ubb34\ub8cc \ud50c\ub79c\uc740 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uacfc, [docsearch](https://docsearch.algolia.com/)\ub97c \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4. \\ndocsearch\uc5d0 \ub4f1\ub85d\ud55c\ub2e4\uba74 \uc77c\uc8fc\uc77c\uc5d0 \ud55c \ubc88\uc529 \ud06c\ub864\ub9c1\uc774 \uc9c4\ud589\ub41c\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n- [\uc9c1\uc811 \uc778\ub371\uc2a4 \uc218\uc9d1](https://docsearch.algolia.com/docs/legacy/run-your-own/) \\n- [\uc124\uc815 \ud30c\uc77c](https://docsearch.algolia.com/docs/legacy/config-file)\\n\\n### \uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778\\n\\n\ud68c\uc6d0\uac00\uc785\uc744 \ud558\uace0 \uc0c8\ub85c\uc6b4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131\uc744 \ub204\ub978\ub2e4. \\n\uc0dd\uc131\uc744 \ub2e4 \ub9c8\uce58\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 api \ud0a4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n![algolia](./algolia.png)\\n\\n### \ud0a4 \uc0dd\uc131\\n\\n\uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\uae30 \uc704\ud55c \ud0a4\ub97c \uc0dd\uc131\ud55c\ub2e4. \\naddObject, editSettings, deleteIndex acl(\uc811\uadfc \uc81c\uc5b4 \ubaa9\ub85d)\uc774 \uc788\uc73c\uba74 \ub41c\ub2e4. \\n\\n![key](./key.png)\\n\\n### .env \ud30c\uc77c \uc0dd\uc131\\n\\n\ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0c1\ub2e8\uc5d0 .env \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4. \\n\\n```bash title=\\".env\\"\\nAPPLICATION_ID=MVIU5UEMOM\\nAPI_KEY=\uc778\ub371\uc2a4_\uc0dd\uc131\uc6a9_\ud0a4\\n```\\n\\n### config \ud30c\uc77c \uc0dd\uc131\\n\\n\ub9c8\ucc2c\uac00\uc9c0\ub85c \ucd5c\uc0c1\ub2e8\uc5d0 config.json \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4.\\n\uc124\uc815 \ud30c\uc77c\uc740 \ud574\ub2f9 [\ub9c1\ud06c](https://docsearch.algolia.com/docs/legacy/config-file)\ub97c \ucc38\uace0\ud55c\ub2e4. \\n\ub610\ub294 Docusaurus\uc758 [\uc124\uc815 \ud30c\uc77c](https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json)\uc744 \ucc38\uace0\ud55c\ub2e4.\\n\\n```json title=\\"config.json\\"\\n{\\n \\"index_name\\": \\"teco\\",\\n \\"start_urls\\": [\\n \\"https://teco-chat.github.io/\\"\\n ],\\n \\"sitemap_urls\\": [\\n \\"https://teco-chat.github.io/sitemap.xml\\"\\n ],\\n \\"sitemap_alternate_links\\": true,\\n \\"stop_urls\\": [\\n \\"/tests\\"\\n ],\\n \\"selectors\\": {\\n \\"lvl0\\": {\\n \\"selector\\": \\"(//ul[contains(@class,\'menu__list\')]//a[contains(@class, \'menu__link menu__link--sublist menu__link--active\')]/text() | //nav[contains(@class, \'navbar\')]//a[contains(@class, \'navbar__link--active\')]/text())[last()]\\",\\n \\"type\\": \\"xpath\\",\\n \\"global\\": true,\\n \\"default_value\\": \\"Documentation\\"\\n },\\n \\"lvl1\\": \\"header h1\\",\\n \\"lvl2\\": \\"article h2\\",\\n \\"lvl3\\": \\"article h3\\",\\n \\"lvl4\\": \\"article h4\\",\\n \\"lvl5\\": \\"article h5, article td:first-child\\",\\n \\"lvl6\\": \\"article h6\\",\\n \\"text\\": \\"article p, article li, article td:last-child\\"\\n },\\n \\"strip_chars\\": \\" .,;:#\\",\\n \\"custom_settings\\": {\\n \\"separatorsToIndex\\": \\"_\\",\\n \\"attributesForFaceting\\": [\\n \\"language\\",\\n \\"version\\",\\n \\"type\\",\\n \\"docusaurus_tag\\"\\n ],\\n \\"attributesToRetrieve\\": [\\n \\"hierarchy\\",\\n \\"content\\",\\n \\"anchor\\",\\n \\"url\\",\\n \\"url_without_anchor\\",\\n \\"type\\"\\n ]\\n },\\n \\"conversation_id\\": [\\n \\"833762294\\"\\n ],\\n \\"nb_hits\\": 46250\\n}\\n```\\n\\n### docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\\n\\ndocker\uc640 jq\uac00 \ud544\uc694\ud558\ub2e4. \\njq\uac00 \uc124\uce58\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74 mac \uae30\uc900 brew\ub97c \uc774\uc6a9\ud574\uc11c \uc124\uce58\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nbrew install jq\\n```\\n\\n\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec .env\uc640 config.json\uc744 \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\uc744 \ud55c\ub2e4. \\n\\n```bash\\ndocker run -it --env-file=.env -e \\"CONFIG=$(cat ./config.json | jq -r tostring)\\" algolia/docsearch-scraper\\n```\\n\\n### docusaurus \uc124\uc815\\n\\n\uc804\uc5d0 \ud655\uc778\ud55c APP ID, Search-Only API KEY, IndexName\uc744 \uc774\uc6a9\ud558\uc5ec docusaurus.config \ud30c\uc77c\uc5d0 \uc124\uc815\ud55c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nthemeConfig:\\n /** @type {import(\'@docusaurus/preset-classic\').ThemeConfig} */\\n ({\\n ...\\n algolia: {\\n appId: \'MVIU5UEMOM\', // Application ID\\n apiKey: \'b68f378013817d9a190df88cdde226a0\', // Search-Only API Key\\n indexName: \'teco\', // config.json\uc5d0 \uc124\uc815\ud55c \uc778\ub371\uc2a4\uba85\\n contextualSearch: true,\\n },\\n })\\n```\\n\\n## \ubd80\uac00 \uc124\uc815\\n\\n### \ud654\uba74 \uc0c1\ub2e8 Github Icon\\n\\n\ud30c\uc77c \ucd5c\ud558\ub2e8\uc5d0 \uc544\ub798 css \uad6c\ubb38\uc744 \ucd94\uac00\ud55c\ub2e4.\\n\\n```css title=\\"/src/css/custom.css\\"\\n.header-github-link:hover {\\n opacity: 0.6;\\n}\\n\\n.header-github-link:before {\\n content: \'\';\\n width: 24px;\\n height: 24px;\\n display: flex;\\n background: url(\\"data:image/svg+xml,%3Csvg viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\'/%3E%3C/svg%3E\\")\\n no-repeat;\\n}\\n\\nhtml[data-theme=\'dark\'] .header-github-link:before {\\n background: url(\\"data:image/svg+xml,%3Csvg viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath fill=\'white\' d=\'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\'/%3E%3C/svg%3E\\")\\n no-repeat;\\n}\\n```\\n\\nthemeconfig -> navbar\uc5d0 github link\ub97c \uc124\uc815\ud55c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nnavbar: {\\n title: \'HELLO\',\\n items: [\\n {\\n href: \'https://github.com/greeng00se\',\\n position: \'right\',\\n className: \'header-github-link\',\\n \'aria-label\': \'GitHub repository\',\\n },\\n ],\\n},\\n```\\n\\n### \ucf54\ub4dc\ube14\ub7ed\\n\\njava\ub098 kotlin\uc758 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ub77c\uc774\ud305\uc744 \uc9c0\uc6d0\ud574 \uc8fc\uc9c0 \uc54a\ub294\ub2e4. \\nprism \uc124\uc815\uc744 \uc544\ub798\uc640 \uac19\uc774 \ubcc0\uacbd\ud574 \uc900\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nprism: {\\n theme: lightCodeTheme,\\n darkTheme: darkCodeTheme,\\n additionalLanguages: [\'java\', \'kotlin\'],\\n}\\n```\\n\\n### mermaid\\n\\nmermaid\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 `@docusaurus/theme-mermaid` \ub97c \uc124\uce58\ud574\uc57c \ud55c\ub2e4.\\n\\n```bash\\nyarn add @docusaurus/theme-mermaid\\n```\\n\\n\uc124\uce58 \ud6c4 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\uc744 \ucd94\uac00\ud55c\ub2e4.\\n\\n```js title=\\"docusaurus.config\\"\\nconst config = {\\n ...\\n markdown: {\\n mermaid: true,\\n },\\n themes: [\\n \'@docusaurus/theme-mermaid\'\\n ],\\n};\\n```\\n\\nthemeConfig\uc5d0\uc11c mermaid\uc758 \ud14c\ub9c8\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nthemeConfig:\\n /** @type {import(\'@docusaurus/preset-classic\').ThemeConfig} */\\n ({\\n ...\\n mermaid: {\\n theme: {\\n light: \'neutral\', \\n dark: \'dark\'\\n },\\n },\\n }),\\n```\\n\\n### \uad6d\uc81c\ud654 \uc124\uc815\\n\\n\uad6d\uc81c\ud654 \uc124\uc815\uc744 \ud55c\ub2e4\uba74 `Older Entries` \ud615\ud0dc\uc758 \uc124\uba85\uc774 `\ub2e4\uc74c \ud398\uc774\uc9c0` \ub85c \ubcc0\uacbd\ub41c\ub2e4. \\n\uc124\uc815\ud30c\uc77c\uc5d0\uc11c i18n\uc5d0 \uc788\ub294 \ub85c\ucf00\uc77c \uc124\uc815\uc744 ko\ub85c \ubcc0\uacbd\ud558\uba74 \ub41c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\ni18n: {\\n defaultLocale: \\"ko\\",\\n locales: [\\"ko\\"],\\n},\\n```\\n\\n### \ube14\ub85c\uadf8 \uae00 author\\n\\n\ud300\uc6d0 \ubcc4\ub85c \ubb38\uc11c\ub97c \uad00\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc5b4\ub5a4 \ud300\uc6d0\uc774 \uae00\uc744 \uc791\uc131\ud588\ub294\uc9c0 \uc124\uc815\ud574\uc57c \ud55c\ub2e4. \\n\\n![author](./author.png)\\n\\n`authors.yml` \ud30c\uc77c\uc744 \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \uae30\ubcf8 \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n```yml title=\\"/blog/authors.yml\\"\\nherb:\\n name: \ud5c8\ube0c\\n title: Backend\\n url: https://github.com/greeng00se\\n image_url: https://github.com/greeng00se.png\\n\\nmallang:\\n name: \ub9d0\ub791\\n title: Backend\\n url: https://github.com/shin-mallang\\n image_url: https://github.com/shin-mallang.png\\n```\\n\\n\ube14\ub85c\uadf8 \uae00\uc744 \uc791\uc131\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc774 authors\uc5d0 \ub123\uc5b4\uc8fc\uae30\ub9cc \ud558\uba74 \ub41c\ub2e4. \\n\\n```mdx\\n---\\nslug: 1\\ntitle: Hello World\\nauthors: [herb, mallang]\\ntags: [hello, docusaurus]\\n---\\n\\n\uccab \ubc88\uc9f8 \ubb38\uc11c \ub0b4\uc6a9\\n```"},{"id":"woowacourse-level2-retrospective","metadata":{"permalink":"/woowacourse-level2-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","description":"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.","date":"2023-06-11T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 11\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":2.545,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","slug":"woowacourse-level2-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"Docusaurus","permalink":"/docusaurus"},"nextItem":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","permalink":"/level2-interview-retrospective"}},"content":"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4. \\n\ube60\ub974\uac8c \uc9c0\ub098\uac00\uc11c \uc870\uae08 \uc544\uc27d\ub2e4. \\n\\n### \ud559\uc2b5\\n\\n\ud68c\uace0\ub97c \uc791\uc131\ud558\uae30 \uc804\uc5d0 \ub808\ubca8 2 \ub3d9\uc548 \ubcf4\ub0c8\ub358 PR\uacfc \ud68c\uace0\ub97c \ucb49 \uc77d\uc5b4\ubd24\ub2e4. \\n\ud56d\uc0c1 \uc544\uc26c\uc6b4 \uacf3\uc740 \uc788\uae30 \ub9c8\ub828\uc774\uc9c0\ub9cc, \uc798 \ud559\uc2b5\ud55c \uac83 \uac19\ub2e4. \\n\ubbf8\uc158\uc744 \ud558\uba74\uc11c \uae30\uc220\uc744 \uc5b4\ub5bb\uac8c \uc120\ud0dd\ud558\uace0, \uc801\uc6a9\ud560 \uac83\uc778\uc9c0 \uace0\ubbfc\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \uaf64\ub098 \ub9ce\uc740 \uc131\uc7a5\uc744 \ud55c \uac83 \uac19\ub2e4. \\n\\n\uace0\ubbfc\uc740 \uae4a\uc5c8\uc9c0\ub9cc \uc774\ub860\uc801\uc778 \ud559\uc2b5\uc774 \ubd80\uc871\ud55c \ub808\ubca8 2\uc600\ub2e4. \\n\ubc29\ud559 \uadf8\ub9ac\uace0 \ub808\ubca8 3 \ub54c\ub294 \uc870\uae08 \ub354 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc744 \ud559\uc2b5\ud558\ub294\ub370 \uc9d1\uc911\ud574\uc57c\uaca0\ub2e4. \\n\\n\uc810\ucc28 \ud559\uc2b5 \ubc94\uc704\uac00 \ub113\uc5b4\uc9c0\uba74\uc11c \uc790\uc5f0\uc2a4\ub7fd\uac8c \ubaa8\ub974\ub294 \ub0b4\uc6a9\uc774 \uc313\uc5ec\uac04\ub2e4. \\n\ud544\uc694\ud55c \ub0b4\uc6a9\uc740 \uc55e\uc73c\ub85c \ucc9c\ucc9c\ud788 \ud559\uc2b5\ud558\uba74 \ub418\ub2c8\uae4c \uc870\uae09\ud574\uc9c0\uc9c0 \ub9d0\uc544\uc57c\uaca0\ub2e4. \\n\\n### \uc218\uba74\\n\\n\ub808\ubca8 2\ub97c \uc9c4\ud589\ud558\ub294 \ub3d9\uc548 \uc218\uba74\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\uc5c8\uace0, \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \uadf8\ub0a0\uc758 \ucee8\ub514\uc158\uc744 \ub9ce\uc774 \uc88c\uc6b0\ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c \uc218\uba74 \uc2dc\uac04\uc744 \ub298\ub9ac\uace0, \uc88b\uc740 \uc218\uba74 \uc2b5\uad00\uc744 \uac00\uc9c0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### \ud611\uc5c5\\n\\n\ub808\ubca8 2 \ub9c8\uc9c0\ub9c9\uc5d0 \ud611\uc5c5 \ubbf8\uc158\uc774 \uc788\uc5c8\ub2e4. \\n\uc9c0\uae08\uae4c\uc9c0\ub294 \ubc31\uc5d4\ub4dc \ud06c\ub8e8\ub4e4\uacfc \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \ud611\uc5c5\uc744 \uacbd\ud5d8\ud588\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \ud504\ub7f0\ud2b8\uc5d4\ub4dc \ud06c\ub8e8\uc640 \ud611\uc5c5\uc744 \ud588\ub2e4. \uc18c\ud1b5\uc740 \uc798 \ub41c \uac83 \uac19\uc9c0\ub9cc API \uba85\uc138\ub97c \uc815\ud558\ub294 \ubd80\ubd84\uc774 \uc544\uc9c1 \ubbf8\uc219\ud55c \uac83 \uac19\ub2e4. \\n\\n\ub808\ubca8 3 \ub54c\ubd80\ud130 \ubcf8\uaca9\uc801\uc73c\ub85c \ud504\ub85c\uc81d\ud2b8\uac00 \uc2dc\uc791\ub41c\ub2e4. \\n\ud300\uc744 \uc704\ud574 \uc5b4\ub5a4 \uac83\uc744 \ud560 \uc218 \uc788\uc744\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud574\ubd10\uc57c\uaca0\ub2e4. \\n\\n### \ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70\\n\\n\ud68c\uace0 \uc791\uc131\ud558\uba74\uc11c \ub808\ubca8 2\uc5d0\uc11c \ud588\ub358 \uac83\ub4e4\uc744 \ubc18\ucd94\ud574 \ubd24\ub294\ub370 \ubd80\uc871\ud55c \uc810\uc740 \ub9ce\uc558\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \uac00\uace0 \uc788\ub294 \uac83 \uac19\ub2e4.\\n\uc77d\uace0 \uc2f6\uc740 \ucc45\ub3c4 \uc77d\uace0, \ubd80\uc871\ud55c \ubd80\ubd84 \ucc44\uc6b0\uba74\uc11c \uc26c\uc5b4\uc57c\uaca0\ub2e4."},{"id":"level2-interview-retrospective","metadata":{"permalink":"/level2-interview-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx","title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","description":"\ub808\ubca8 \uc778\ud130\ubdf0","date":"2023-06-08T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 8\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.435,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","slug":"level2-interview-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","permalink":"/woowacourse-level2-retrospective"},"nextItem":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","permalink":"/order-retrospective"}},"content":"### \ub808\ubca8 \uc778\ud130\ubdf0\\n\\n\ub808\ubca8 1 \ub54c\ub294 \uc900\ube44\ud574\ub454 \ub0b4\uc6a9\uc73c\ub85c \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud574\uc11c \uadf8\ub807\uac8c \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc774 \uc5c6\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \ub808\ubca8 1 \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0\ub294 \ub808\ubca8 1 \ud68c\uace0\ub97c \uc791\uc131\ud560 \ub54c \ub07c\uc6cc\ub123\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \ubc94\uc704\ub3c4 \uc81c\ud55c\ub418\uc5b4 \uc788\uc5b4 \uc5b4\ub5bb\uac8c \uc900\ube44\ud574\uc57c \ud560\uc9c0 \ub2f9\ud669\ud588\uace0, \ub2f5\ubcc0\uc5d0\ub3c4 \ubd80\uc871\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4. \\n\uae30\uc5b5\uc774 \uc0ac\ub77c\uc9c0\uae30 \uc804\uc5d0 \ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\ud55c \ub0b4\uc6a9\uc744 \uc81c\uc678\ud558\uace0, \uae30\uc5b5 \ub0a8\ub294 \uac83 \uc704\uc8fc\ub85c \uc791\uc131\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n### API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd\\n\\n\ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\uc744 \ud588\ub294\ub370 \uc55e\uc73c\ub85c\ub3c4 \ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \ud558\uba74\uc11c \ub3c4\uc6c0 \ub420 \uac83 \uac19\uc740 \ub0b4\uc6a9\uc774 \uc788\uc5b4\uc11c \ub0a8\uaca8\ub450\ub824\uace0 \ud55c\ub2e4. \\n\ubc31\uc5d4\ub4dc \ud300\uc6d0\uc774 \ud568\uaed8 \uc758\uc0ac\uacb0\uc815\uc744 \ud588\uace0, \ubbf8\uc158 \uae30\uac04\uc774 \uc9e7\uc740 \ub9cc\ud07c \ud300 \ucc28\uc6d0\uc5d0\uc11c \ube44\uad50\uc801 \ud559\uc2b5\ud558\uae30 \uc26c\uc6b4 Swagger\ub97c \uc120\ud0dd\ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub4e4\uc5b4\uac00\ub294 \uc2dc\uac04 \ub300\ube44 \ud558\uc774 \ub9ac\ud134\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4\uace0 \ub2f5\ubcc0\ud588\ub2e4.\\n\\n\ud300 \ucc28\uc6d0\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uc5b8\uae09\ud574\uc11c, \ub2e4\uc74c\uacfc \uac19\uc740 \uc88b\uc740 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4.\\n\\n> \ud2b9\ud788 \ud300\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\ud558\ub294 \uacfc\uc815\uc744 \uacf5\uc720\ud574 \uc900 \uc810\uc774 \uc88b\uc558\uace0 \uae30\uc220\uc801 \uc758\uc0ac\uacb0\uc815 \uacfc\uc815\uc5d0\uc11c \ud300\uc758 \ud559\uc2b5\ube44\uc6a9\uc744 \uace0\ub824\ud55c \uc810\uc774 \uc88b\uc558\uc74c. \\n> \uc55e\uc73c\ub85c\ub3c4 \ud559\uc2b5 \ube44\uc6a9\uc740 \uc8fc\uc694\ud558\uac8c \uace0\ub824\ud574\uc57c \ud560 \uc0ac\ud56d\\n>\\n\\n### PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158\\n\\nPUT\uacfc PATCH \ucc28\uc774\ub97c \uc124\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c\ub294 PATCH\ub97c \uc0ac\uc6a9\ud560 \ub54c \ud398\uc774\ub85c\ub4dc\uac00 \uc801\uc5b4\uc9c4\ub2e4\ub294 \ub0b4\uc6a9\uc744 \ube7c\uba39\uace0 \ub2f5\ubcc0\uc744 \ud588\ub2e4. \\n\ud1a0\ud070\uacfc \uc138\uc158\uc758 \uacbd\uc6b0 \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud574\ub2ec\ub77c\ub294 \uc81c\uc57d\uc870\uac74\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n\ud574\ub2f9 \ub0b4\uc6a9\uc744 \ub2f5\ubcc0\ud558\uba74\uc11c \uae30\uc220\uc801\uc778 \uae4a\uc774\uac00 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\uc2e4\uc81c\ub85c \ub808\ubca8 2 \ub54c \uc774\ub860\uc801\uc778 \ud559\uc2b5 \uc2dc\uac04\uc774 \ub9e4\uc6b0 \uc801\uc5c8\uace0, \uc9d1\uc911\ub825\ub3c4 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4. \\n\uc55e\uc73c\ub85c \uc5b4\ub5bb\uac8c \uae4a\uc774\ub97c \ucc44\uc6b8\uc9c0 \uace0\ubbfc\uc744 \ud560 \uc218 \uc788\ub294 \uc9c8\ubb38\ub4e4\uc774\uc5c8\ub2e4. \\n\\n\ucd94\uac00\ub85c \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud558\ub294 \uac00\uc815\uc744 \ub450\uace0 \ud559\uc2b5\uc744 \ud55c\ub2e4\uba74 \ud070 \ub3c4\uc6c0\uc774 \ub420 \uac70\ub77c\ub294 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4. \\n\\n### \uadf8 \uc678 \uac1c\uc120\ud560 \uc810\\n\\n\uc778\ud130\ubdf0\ud560 \ub54c \ud2b9\uc720\uc758 \ub9d0\ubc84\ub987\uc744 \uac1c\uc120\ud558\uae30 \\n\uc0dd\uac01\ud560 \uc2dc\uac04\uc744 \uac00\uc84c\uc744 \ub54c \\"\ub2e4\uc2dc \ub9d0\uc500\ub4dc\ub824\ub3c4 \ub420\uae4c\uc694?\\"\ub77c\uace0 \ub9d0\ud558\uace0 \ub2f5\ubcc0\uc744 \uc774\uc5b4\ub098\uac00\uae30 \\n\uae30\uc220\uc801\uc73c\ub85c \uae4a\uc774\uac00 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5b4\uc11c \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\uae30 \\n\uc774\uc804\uc5d0 \uacf5\ubd80\ud588\ub358\uac70 \ub418\ub3cc\uc544 \ubcf4\ub294 \uc2dc\uac04 \uac00\uc9c0\uae30"},{"id":"order-retrospective","metadata":{"permalink":"/order-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4: AWS \ubc30\ud3ec","date":"2023-06-04T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 4\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.67,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","slug":"order-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","permalink":"/level2-interview-retrospective"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","permalink":"/tecochat-retrospective-3"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: AWS \ubc30\ud3ec \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-shopping-order/pull/7 \\n:::\\n\\n### \uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158\\n\\n\ubc30\ud3ec \ubc0f \ud611\uc5c5\uc744 \ud560 \uc218 \uc788\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ub9c8\ucf54, \uc6b0\uac00, \uc6b0\ucf54, \uc6b0\uc2a4 \uadf8\ub9ac\uace0 \ub098\uae4c\uc9c0 \ud569\uccd0\uc11c 5\uba85\uc774 \ud55c \ud300\uc774 \ub418\uc5c8\ub2e4. \\n\\n### \ubc30\ud3ec\\n\\n\uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac AWS\ub97c \uc774\uc6a9\ud574 \ubc30\ud3ec\ub97c \ud574\uc57c \ud588\ub2e4. \\n\uac01\uc790 \ud558\ub098\uc758 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc744 \uc218 \uc788\uc5c8\uace0, \ud300 \ubcc4\ub85c DB\ub97c \uc704\ud55c \ucd94\uac00 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc558\ub2e4. \\n\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uacbd\ud5d8\uc744 \ud574\ubcfc \uc218 \uc788\uc5c8\ub2e4. \\n\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ud22c\uc790\ud558\uc9c4 \uc54a\uc558\uace0, \ub2e4\uc74c\uacfc \uac19\uc774 \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4.\\n\\n```bash\\necho \\"Start Deploy Script\\"\\nREPOSITORY_NAME=/home/ubuntu/jwp-shopping-order\\nPROJECT_NAME=jwp-shopping-order\\n\\necho \\"Change Directory\\"\\ncd $REPOSITORY_NAME\\n\\necho \\"Git Pull\\"\\ngit pull origin step2\\n\\necho \\"Build\\"\\n./gradlew bootJar\\n\\necho \\"Copy, Start Server\\"\\nmv ./build/libs/$PROJECT_NAME.jar .\\n\\nPID=$(pgrep -f $PROJECT_NAME)\\n\\nif [ -n $PID ]; then\\n kill -9 $PID\\n\\tsleep 5\\nfi\\n\\nnohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &\\n```\\n\\n### \ud611\uc5c5\\n\\n\uc77c\ub2e8 \uc6b0\uc2a4\ub791 \uc6b0\ucf54\uac00 \uba3c\uc800 \uc7a0\uc2e4\ub85c \uc640\uc918\uc11c \ub108\ubb34 \uac10\uc0ac\ud588\ub2e4. \\n\ubc31\uc5d4\ub4dc\uac00 \uc544\ub2cc \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \ud574\ubcf4\ub294 \uccab \ud611\uc5c5\uc774\ub77c \uc57d\uac04 \ub450\uadfc\uac70\ub838\ub2e4. \\n\uc608\uc0c1\uc678\ub85c \ub300\ud654\uac00 \uc798 \ub418\uc5b4\uc11c, \ube60\ub974\uac8c \uba85\uc138\ub97c \uc815\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uc5ec\ub7ec\uac00\uc9c0 \ubc29\ubc95\uc5d0 \ub300\ud55c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud574\ubcf4\uae30**\\n\\n\ubc31\uc5d4\ub4dc\uc640 \ud14c\uc774\ube14 \uba85\uc138\ub098 \ucfe0\ud3f0 \uad6c\ud604\uc5d0 \ub300\ud574\uc11c \uc774\uc57c\uae30\ud560 \ub54c \uc7a5\ub2e8\uc5d0 \ub300\ud574 \ub9ce\uc774 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4. \\n\uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc5ec\uc11c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud588\ub2e4\uba74 \ub354 \uc88b\uc740 \uacb0\uacfc\ubb3c\uc774 \ub098\uc624\uc9c0 \uc54a\uc558\uc744\uae4c? \\n\uc55e\uc73c\ub85c \uc120\ud0dd\uc758 \uc21c\uac04\uc5d0\uc11c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub4e4\uc5ec\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4. \\n\\n### \uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84\\n\\n**expose headers**\\n\\n\uc6f9 \ud398\uc774\uc9c0\uc5d0\uc11c Location \ud5e4\ub354\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \uc788\uc5c8\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c [\ud5c8\uc6a9 \ubaa9\ub85d\uc5d0 \uc874\uc7ac\ud558\ub294 \uc751\ub2f5\ud5e4\ub354](https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header)\ub9cc \ubc18\ud658\ud55c\ub2e4\ub294 \uac83\uc744 \ubaa8\ub974\uace0 \uc788\uc5c8\ub2e4. \\n\uc774\ub97c expose headers \uc124\uc815\uc744 \ud1b5\ud574 \ud574\uacb0\ud560 \uc218 \uc788\uc5c8\ub2e4. \\nnginx \uc124\uc815\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \ucd94\uac00\ud574 \uc8fc\uc5c8\ub2e4. \\n\\n```bash\\nadd_header \'Access-Control-Expose-Headers\' \'Location\'\\n```\\n\\n**\uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158** \\n\\n\ub2e8\uc21c \uc870\ud68c \uc694\uccad\uc5d0 \ub300\ud55c \uc131\ub2a5\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc900\ub2e4\ub294 \uac83\uc774\ub77c\uace0 \uac04\ub2e8\ud788\ub9cc \uc54c\uace0 \uc788\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0 \ucf54\uba58\ud2b8\uac00 \ub2ec\ub824\uc11c \uc870\uae08 \ub354 \uc790\uc138\ud788 \uacf5\ubd80\ud574 \ubcf4\uae30\ub85c \ud588\ub2e4. \\nTransactional(readOnly = true)\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc774 \ub3d9\uc791\ud55c\ub2e4.\\n\\nsetReadOnly(true) \uc124\uc815\uc774 \ub41c Connection\uc73c\ub85c \uc5f0\uacb0\uc744 \uc2dc\ub3c4\ub97c \ud55c\ub2e4. \uc774 \uc124\uc815\uc744 \ud558\ub294 \uacbd\uc6b0 DB\ub9c8\ub2e4 \ub2e4\ub974\uac8c \ub3d9\uc791\ud55c\ub2e4.\\n- h2\uc758 Connection \uad6c\ud604\uccb4\ub294 readOnly \uc124\uc815\uc744 \ubb34\uc2dc\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 Transactional \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4. \\n- MySQL 8.0(InnoDB \uc0ac\uc6a9 \uc2dc)\uc758 \uacbd\uc6b0 \uc77d\uae30 \uc804\uc6a9\uc73c\ub85c \uc54c\ub824\uc9c4 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158 ID\ub97c \uc124\uc815\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uc870\ud68c \uc18d\ub3c4\uac00 \ub354 \ube68\ub77c\uc9c4\ub2e4.\\n\\nORM \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 prepareTransactionalConnection\ub97c \ud638\ucd9c\ud55c\ub2e4\uace0 \ud55c\ub2e4. \\n\ucd94\uac00\ub85c \ud604\uc5c5\uc5d0\uc11c\ub294 \uace0\uac00\uc6a9\uc131 \ub0b4\uacb0\ud568\uc131 \ub4f1\uc744 \uc704\ud558\uc5ec \ud074\ub7ec\uc2a4\ud130\ub97c \uad6c\uc131\ud558\uc5ec \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uace0, \uc774 \uacbd\uc6b0 readOnly \uc124\uc815\uc774 \ub418\uc5b4\uc788\ub2e4\uba74 \uc77d\uae30 \uc804\uc6a9 DB\ub85c \uc9c8\uc758\uac00 \ub4e4\uc5b4\uac00\uc11c \ubd80\ud558 \ubd84\uc0b0\uc758 \ud6a8\uacfc\uac00 \uc788\ub2e4\uace0 \ud55c\ub2e4. \\n\\n**DAO\uc5d0 `@Transactional` \uc801\uc6a9** \\n\\nDAO\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \ubcf4\ub294 \uac74 \uc5b4\ub5bb\uaca0\ub0d0\uace0 \ub9ac\ubdf0\uac00 \ub2ec\ub824\uc11c \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\nService \uacc4\uce35\uc5d0 \uc774\ubbf8 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \uc8fc\uace0 \uc788\uae30\uc5d0 \ud544\uc694 \uc5c6\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4. \\nDAO\ub97c \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574(\ud655\uc7a5\uc131 \uace0\ub824) `@Transactional`\uc744 \uc801\uc6a9\ud558\ub294 \uac83\ub3c4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."},{"id":"tecochat-retrospective-3","metadata":{"permalink":"/tecochat-retrospective-3","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx","source":"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx","title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","description":"\uac1c\uc694","date":"2023-06-01T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 1\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.005,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","slug":"tecochat-retrospective-3","tags":["TecoChat","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","permalink":"/order-retrospective"},"nextItem":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","permalink":"/composite"}},"content":"### \uac1c\uc694\\n\\n\uc6d0\ub798 \ubaa9\uc801\uc778 `\ud06c\ub8e8\ub4e4\uc758 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0`\uc744 \uc8fc\uae30 \uc704\ud574 \uc5b4\ub5a4 \uae30\ub2a5\uc744 \ucd94\uac00\ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\ub808\ubca8 2\uac00 \uac70\uc758 \ub05d\ub098\uac00\ub294 \uc2dc\uc810, \uadf8\ub3d9\uc548 \ud588\ub358 \uac83\uc744 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n### \ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5\\n\\nGPT\uc5d0\ub3c4 \uc788\ub294 \uae30\ub2a5\uc778\ub370, \ub0b4\uac00 \uc774\uc804\uc5d0 \ud588\ub358 \ucc44\ud305\uc744 \uc774\uc5b4\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\uc608\uc804\uc5d0 \uc5b4\ub5a4 \uc9c8\ubb38\uc744 \ub0a8\uacbc\ub294\uc9c0, \ub610\ud55c \ud574\ub2f9 \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub2e4. \\n\\n![chat1](./chat1.png)\\n\\n### \uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5\\n\\n\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc5d0 \ubc18\uc751\ud560 \uc218 \uc788\ub294 \ubb34\uc5b8\uac00\uac00 \uc788\uc5c8\uc73c\uba74 \uc88b\uaca0\ub2e4\ub294 \uc758\uacac\ub4e4\uc774 \ub9ce\uc558\ub2e4. \\n\ub204\uac00 \uc88b\uc544\uc694\ub97c \ub20c\ub800\ub294\uc9c0, \uc5b4\ub5a4 \ucc44\ud305\uc774 \uc88b\uc544\uc694\ub97c \uac00\uc7a5 \ub9ce\uc774 \ubc1b\uc558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\ub610\ud55c \ub313\uae00 \ucd94\uac00 \ubc0f \uc0ad\uc81c \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4.\\n\\n### \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\\n\\n\uc5b4\ub5bb\uac8c \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\uc744 \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub294\ub370, \uc77c\ub2e8 GPT\ub97c \uc774\uc6a9\ud574\uc11c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\uae30\ub85c \ud588\ub2e4. \\n\ud574\ub2f9 \ubd80\ubd84\uc740 \uccab \uc9c8\ubb38\uc5d0 \ub300\ud55c \ud0a4\uc6cc\ub4dc\ub9cc \ucd94\ucd9c\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\ubc31\uc5d4\ub4dc\uc5d0\uc120 \ub9d0\ub791\uc774 \uc774\ubca4\ud2b8 \uc774\uc6a9\ud574\uc11c \uccab \ucc44\ud305 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74, \ube44\ub3d9\uae30\ub85c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\ub294 \uc9c8\ubb38\uc744 \ucd94\uac00\ub85c \ub0a0\ub9ac\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4. \\nCSV \ud615\uc2dd\uc73c\ub85c GPT\uc5d0\uac8c \ub2f5\ubcc0\uc744 \uc785\ub825\ud574\ub2ec\ub77c\uace0 \uc694\uccad\ubc1b\ub294\ub370, \uc774 \ubd80\ubd84\uc774 \ubb38\uc81c(\ud504\ub86c\ud504\ud2b8 \uc5d4\uc9c0\ub2c8\uc5b4\ub9c1 \ubd80\ubd84\uc774 \ubc18\ud658\ub41c\ub2e4.)\uac00 \uc880 \uc788\ub294 \uac83 \uac19\uc544\uc11c \uac1c\uc120\uc774 \ud544\uc694\ud55c \uac83 \uac19\ub2e4. \\n\\n![chat2](./chat2.png)\\n\\n### \ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5\\n\\n\ub2e4\ub978 \ud06c\ub8e8\ub4e4\uc758 \ucc44\ud305\uc744 \uc77d\ub2e4\uac00 \uad81\uae08\ud55c \uc810\uc774 \uc788\ub2e4\uba74 \ubcf5\uc0ac\ud574\uc11c \ubc14\ub85c \uc9c8\ubb38\uc744 \ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\ucc44\ud305\uc774 \ubcf5\uc0ac\ub41c \ud6c4 \ubc14\ub85c GPT\uc640 \ub300\ud654\ub97c \ud560 \uc218 \uc788\ub294 \uba54\uc778 \ud654\uba74\uc73c\ub85c \uc774\ub3d9\ud55c\ub2e4. \\n\\n### \uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30\\n\\n![chat3](./chat3.png)\\n\\n\uc704 \ud654\uba74\uc740 \ud68c\uc6d0\uac00\uc785 \ucc3d\uc774\ub2e4. \\n\uc0ac\uc2e4 \uac00\uc7a5 \ub9c8\uc74c\uc5d0 \ub4dc\ub294 \ubd80\ubd84\uc774\uace0, \ud68c\uc6d0\uac00\uc785(\ub2c9\ub124\uc784\ub9cc \uc785\ub825\ud558\uc9c0\ub9cc)\ud560 \ub54c \uc775\uba85\uc744 \uc6d0\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uace0\ubbfc\uc744 \ub3c4\uc640\uc8fc\uac8c \ub054 \uc74c\uc2dd, \uacfc\uc77c, \uacfc\uc790 \ub4f1\uc758 \uc694\uc18c\ub4e4\uc744 \uc785\ub825\ud558\ub3c4\ub85d \uc720\ub3c4\ud588\ub2e4!\\n\ucd94\uac00\ub85c GPT\uc758 \ub2f5\ubcc0\uc774 \uc624\uba74 \uc790\ub3d9\uc73c\ub85c \ud654\uba74\uc744 \uc2a4\ud06c\ub864 \ud574\uc8fc\ub294 \uac83\uacfc \uac19\uc774 \uc0ac\uc6a9\uc131\uc744 \uac1c\uc120\ud574 \ubcf4\ub824\uace0 \ub178\ub825\ud588\uc9c0\ub9cc \uc27d\uc9c0 \uc54a\uc558\ub2e4. \\n\uc81c\uc77c \ud558\uace0 \uc2f6\uc740 \uac83\uc740 \uc2e4\uc81c GPT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ucc98\ub7fc stream/text \uac12\uc744 \ucc98\ub9ac\ud558\uace0 \uc2f6\uc740\ub370 \uc774 \ubd80\ubd84\uc740 \ubc29\ud559 \ub54c \uae30\ud68c\uac00 \ub418\uba74 \ub3c4\uc804\ud574 \ubd10\uc57c\uaca0\ub2e4. \\n\\n### \ud5a5\ud6c4 \uacc4\ud68d\\n\\n\uc2e4\uc81c \ud06c\ub8e8\ub4e4\uc774 \uc0ac\uc6a9\ud574 \uc8fc\ub294 \uc11c\ube44\uc2a4\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\ubcf4\uba74\uc11c \uc0ac\uc6a9\uc790\uc758 \uc785\uc7a5\uc5d0\uc11c \uace0\ubbfc\ub3c4 \ud558\uac8c \ub418\ub294 \uac83 \uac19\ub2e4. \\n\ud06c\ub8e8\ub4e4\uc774 \uc9c1\uc811 \uc0ac\uc6a9\ud574 \uc8fc\ub2c8\uae4c \ub108\ubb34 \uace0\ub9d9\uace0, \ud55c\ud3b8\uc73c\ub85c\ub294 \uc2e0\uae30\ud558\ub2e4. \\n\uc77c\ub2e8 \ubc29\ud559 \ub54c stream/text \uad00\ub828\ub41c \ubd80\ubd84 \ub3d9\uc791\ub418\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\ub824\uace0 \ud558\uace0, \uadf8 \uc678\uc758 \ubd80\ubd84\uc740 \uc870\uae08 \ub354 \uace0\ubbfc\ud574\uc57c\ub420 \uac83 \uac19\ub2e4."},{"id":"composite","metadata":{"permalink":"/composite","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx","source":"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx","title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","description":"\uc694\uad6c\uc0ac\ud56d","date":"2023-05-26T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 26\uc77c","tags":[{"label":"Pattern","permalink":"/tags/pattern"},{"label":"Composite","permalink":"/tags/composite"}],"readingTime":4.74,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","slug":"composite","tags":["Pattern","Composite"]},"unlisted":false,"prevItem":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","permalink":"/tecochat-retrospective-3"},"nextItem":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","permalink":"/subway-retrospective"}},"content":"### \uc694\uad6c\uc0ac\ud56d\\n\\n\uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.\\n\\n- \uac70\ub9ac\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45\\n- \ub178\uc120\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45\\n- \uc5f0\ub839\ubcc4 \uc694\uae08 \ud560\uc778 \uc815\ucc45\\n\\n### \uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9\\n\\n\uc694\uae08 \uc815\ucc45\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud45c\ud604\ud560 \uc218 \uc788\ub2e4. \\n\uc694\uae08\uc744 \uacc4\uc0b0\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ucd5c\ub2e8 \uacbd\ub85c \uacc4\uc0b0\uc758 \uacb0\uacfc, \uc0ac\uc6a9\uc790\uc758 \uc815\ubcf4, \uc694\uae08\uc744 \ubc1b\uc544 \uc694\uae08\uc744 \uacc4\uc0b0\ud55c\ub2e4.\\n\\n```java\\npublic interface FarePolicy {\\n int calculate(Path path, Passenger passenger, int fare);\\n}\\n\\npublic class BaseFarePolicy implements FarePolicy { ... }\\npublic class DistanceFarePolicy implements FarePolicy { ... }\\npublic class AgeDiscountFarePolicy implements FarePolicy { ... }\\n```\\n\\n![composite1](./composite1.png)\\n\\n### \ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30\\n\\n\ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub97c \ubaa8\ub450 \uac00\uc9c0\uace0 \uc788\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. \\n\uc774 \ub610\ud55c FarePolicy\ub97c \uad6c\ud604\ud55c \ud615\ud0dc\uac00 \ub418\uace0, \ud544\ub4dc\ub85c\ub294 \ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub4e4\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4.\\n\\n```java\\npublic class SubwayFarePolicy implements FarePolicy {\\n\\n private final List farePolicies;\\n\\n public SubwayFarePolicy(final List farePolicies) {\\n this.farePolicies = farePolicies;\\n }\\n\\n @Override\\n public int calculate(final Path path, final Passenger passenger, final int fare) {\\n int calculatedFare = fare;\\n for (FarePolicy farePolicy : farePolicies) {\\n calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);\\n }\\n return calculatedFare;\\n }\\n}\\n```\\n\\n\ub530\ub77c\uc11c \uadf8\ub9bc\uc73c\ub85c \ubcf8\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4.\\n\\n![composite2](./composite2.png)\\n\\n### \uc815\ucc45\uc758 \uc21c\uc11c\\n\\n\uc9c0\ud558\ucca0 \uc694\uad6c\uc0ac\ud56d\uc740 \uc21c\uc11c\uac00 \uc911\uc694\ud588\ub2e4. \\n\uae08\uc561\uc758 \ucd1d\ud569\uc744 \uad6c\ud558\uace0, \uadf8 \ud6c4\uc5d0 \ud560\uc778 \uc815\ucc45\uc774 \ub4e4\uc5b4\uac00\uc57c\ud588\ub2e4. \\n\ub530\ub77c\uc11c \uc790\uc2dd\ub4e4\uc758 \uc21c\uc11c\ub97c \uad00\ub9ac\ud560 \ub54c \uc8fc\uc758\ub97c \uae30\uc6b8\uc5ec\uc57c \ud588\ub2e4. \\nConfiguration \ud074\ub798\uc2a4\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc21c\uc11c\ub97c \uc9c1\uc811 \uc801\uc6a9\uc2dc\ucf30\ub2e4. \\n\\n```java\\n@Configuration\\npublic class FareConfiguration {\\n\\n @Bean\\n public FarePolicy farePolicy() {\\n return new SubwayFarePolicy(List.of(\\n new BaseFarePolicy(),\\n new DistanceFarePolicy(),\\n new AgeDiscountFarePolicy()\\n ));\\n }\\n}\\n```\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?\\n\\n![composite3](./composite3.png)\\n\\nGOF\uc758 \ub514\uc790\uc778 \ud328\ud134 \ucc45\uc5d0\uc11c\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uba85\ud558\uace0 \uc788\ub2e4.\\n\\n> \ubd80\ubd84\uacfc \uc804\uccb4\uc758 \uacc4\uce35\uc744 \ud45c\ud604\ud558\uae30 \uc704\ud574 \uac1d\uccb4\ub4e4\uc744 \ubaa8\uc544 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ud569\ub2c8\ub2e4. \\n\uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ubcf5\ud569 \uac1d\uccb4\ub97c \ubaa8\ub450 \ub3d9\uc77c\ud558\uac8c \ub2e4\ub8f0 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc785\ub2c8\ub2e4.\\n> \\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4. \\n\uc774 \ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c\\n\\nComponent\\n\\n- \uc9d1\ud569 \uad00\uacc4\uc5d0 \uc815\uc758\ub420 \ubaa8\ub4e0 \uac1d\uccb4\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4 \\n- ex) \uc694\uae08 \uc815\ucc45(FarePolicy) \\n\\nLeaf\\n\\n- \uac1c\ubcc4 \uac1d\uccb4, \uac1d\uccb4 \ud569\uc131\uc5d0 \uae30\ubcf8\uc774 \ub418\ub294 \uac1d\uccb4\uc758 \ud589\ub3d9 \\n- ex) \uac70\ub9ac \ubcc4 \uc694\uae08 \uc815\ucc45(DistanceFarePolicy) \\n\\nComposite\\n\\n- \uc5ec\ub7ec \uac1c\uc758 \uac1c\ubc1c \uac1d\uccb4\ub97c \ud3ec\ud568\ud558\ub294 \ud569\uc131 \uac1d\uccb4 \\n- ex) \uc9c0\ud558\ucca0 \uc694\uae08 \uc815\ucc45(SubwayFarePolicy) \\n\\nClient\\n\\n- \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c\\n\\n\ubd80\ubd84 - \uc804\uccb4\uc758 \uad00\uacc4\ub97c \ud45c\ud604\ud558\uace0 \uc2f6\uc744 \ub54c \\nClient \uae30\uc900\uc73c\ub85c Composite\uc640 Leaf\uc758 \ucc28\uc774\ub97c \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc798 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud574\uc57c\ub420 \ub54c\\n\\n### \ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84\\n\\n\ud328\ud134\uc740 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc758 \ud15c\ud50c\ub9bf\uc774\ub2e4. \\n\ubc18\ubcf5\ub418\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc788\uc9c0\ub9cc \ud328\ud134\uc5d0 \ub9e4\ubab0\ub418\uc11c\ub294 \uc548\ub41c\ub2e4. \\n\ud328\ud134\uc744 \ub9f9\ubaa9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548\ub418\uace0, \ud604\uc7ac\uc758 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub530\ub77c \ud328\ud134\uc744 \uc720\ub3d9\uc801\uc73c\ub85c \uc218\uc815\ud574\uac00\uba74\uc11c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\ud56d\uc0c1 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uc0dd\uac01\ud558\uc790!\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134, GoF\uc758 \ub514\uc790\uc778 \ud328\ud134 \\n\ub514\uc790\uc778 \ud328\ud134\uacfc \ud504\ub808\uc784\uc6cc\ud06c, \uc624\ube0c\uc81d\ud2b8"},{"id":"subway-retrospective","metadata":{"permalink":"/subway-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-subway-path/pull/16","date":"2023-05-25T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 25\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.98,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","slug":"subway-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","permalink":"/composite"},"nextItem":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","permalink":"/accidental-duplication"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-subway-path/pull/16 \\n2, 3\ub2e8\uacc4: https://github.com/woowacourse/jwp-subway-path/pull/126 \\n:::\\n\\n### \uc9c0\ud558\ucca0 \ubbf8\uc158\\n\\n\uc810\uc810 \uc77c\uc815\uc774 \ub9ce\uc544\uc9c0\ub294 \ub290\ub08c\uc774 \ub4e4\uba74\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc9c4\ub2e4. \\n\uc9c0\ud558\ucca0 \ubbf8\uc158\uc740 \ubc00\ub9ac\ub791 \ud398\uc5b4\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\uac04\ub2e8\ud55c CRUD\ub9cc \uc788\ub358 \uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac, \uc870\uae08 \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\uc774\ub54c API, \ud14c\uc774\ube14, \ub3c4\uba54\uc778 \uc124\uacc4\ub97c \ud574\uc57c \ud588\ub294\ub370 \uc5b4\ub5a4 \uac83\ubd80\ud130 \ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\nAPI\uc640 \ud14c\uc774\ube14 \uad6c\uc870\ub97c \uc6b0\ub9ac\uac00 \uc815\ud560 \uc218 \uc788\ub294 \uc0c1\ud669\uc774\uc5c8\uace0, \ub3c4\uba54\uc778 \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \ub3c4\uba54\uc778\uc744 \uba3c\uc800 \uad6c\ud604\ud588\ub2e4.\\n\\n**\ub178\uc120\uc758 \uad6c\uac04 \ucd94\uac00 \ubc0f \uc0ad\uc81c**\\n\\n\ub178\uc120\uc744 \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \ubc00\ub9ac\uc640 \uc774\uc57c\uae30\ub97c \ub098\ub234\ub2e4.\\n\\n1. \uad6c\uac04\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc804\ubd80 \uc81c\uac70\ud558\uace0 \uc804\ubd80 \ucd94\uac00\ud558\ub294 \ubc29\ubc95\\n2. \ubcc0\uacbd\ub41c \uc694\uc18c\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ubc18\uc601\ud558\ub294 \ubc29\ubc95\\n\\n\ud398\uc5b4 \uc2dc\uac04\uc774 \uc9e7\uc544\uc11c \ub354\uc6b1 \uac04\ub2e8\ud55c 1\ubc88\uc744 \uc120\ud0dd\ud588\uace0, \uc2dc\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0a4\uae30 \uc704\ud574 \ub354 \uac04\ub2e8\ud558\uac8c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud558\ub294 \uac83\ub3c4 \uc88b\uc740 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\uc600\ub358 \uac83 \uac19\ub2e4. \\n\ucd94\ud6c4 \ud398\uc5b4\uac00 \ub05d\ub098\uace0 \ub9ac\ubdf0\uc5b4\uc778 \uc11c\ube0c\uc6e8\uc774\uac00 \uc77c\ubd80\ubd84\ub9cc \ubc18\uc601\ud558\ub294 \uac83\uc73c\ub85c \uac1c\uc120\ud574 \ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4\uace0 \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c \uc694\uc18c\ub9cc \ubc18\uc601\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ubbf8\uc158\uc758 \ub09c\uc774\ub3c4\uac00 \uc62c\ub77c\uac04 \ub9cc\ud07c, \ud398\uc5b4 \ud560 \ub550 \ucee8\ub514\uc158 \uad00\ub9ac\ub3c4 \uc798\ud558\ub824\uace0 \ub178\ub825\ud558\uace0 \ubbf8\uc158 \ud560 \ub54c\ub3c4 \uc9d1\uc911\ud574\uc11c \uc798 \ub05d\ub0b8 \uac83 \uac19\ub2e4. \\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc54c\uc544\uc57c \ud558\ub294 \uac8c \ub9ce\uc544\uc9c0\uba74\uc11c \uac00\ub054 \uc870\ubc14\uc2ec\uc744 \uac00\uc9c8 \ub54c\uac00 \uc788\ub294 \uac83 \uac19\uc740\ub370, \uc870\ubc14\uc2ec\uc744 \uacbd\uacc4\ud560 \ud544\uc694\uac00 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ubd80\uc871\ud55c \ubd80\ubd84\uc740 \uc778\uc815\ud558\uace0, \uc55e\uc73c\ub85c \ub098\uc544\uac00\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654**\\n\\n\uc694\uae08 \uc815\ucc45\uc740 \uae30\ubcf8\uc694\uae08 \uc815\ucc45, \uac70\ub9ac\ubcc4 \uc694\uae08 \uc815\ucc45, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc774 \uc788\uc5c8\ub2e4. \\n\uc694\uae08\uc744 \ub354\ud558\ub294 \ubd80\ubd84\uacfc, \ud560\uc778\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5b4\uc11c \uc774 \ub458\uc744 \ubd84\ub9ac\ud560\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc, \uc774 \uc815\ub3c4 \ud06c\uae30\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc624\ud788\ub824 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uace0 \ud558\ub098\ub85c \ud569\uce58\ub294 \uac8c \ub354 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub610\ud55c \ubd84\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \uc815\ucc45\uc758 \uc21c\uc11c\uac00 \uc911\uc694\ud55c\ub370, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc744 \ub9c8\uc9c0\ub9c9\uc5d0 \ub450\uc5b4\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ucc45\uc784 \uc5f0\uc1c4 \ud328\ud134\ub3c4 \uace0\ub824\ub97c \ud588\uc9c0\ub9cc \uc870\uae08 \ub354 \uac04\uacb0\ud574 \ubcf4\uc774\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \uc120\ud0dd\ud588\ub2e4.\\n\\n**\ub3c4\uba54\uc778\uc5d0 \ud2b9\uc815 \uae30\uc220\uc758 \uc758\uc874\uc131\uc744 \ubd84\ub9ac**\\n\\n\ucc98\uc74c\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uc5d0 jgrapht \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc758\uc874\ud558\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \ub450\uc5b4\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uac00 jgrapht\uc640 \uac15\uacb0\ud569\uc774 \ub418\uc5b4\ubc84\ub838\ub2e4. \\n\ub530\ub77c\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\uc5d0\ub294 \uacbd\ub85c \uac80\uc0c9\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0, \uc138\ubd80 \uad6c\ud604\uc740 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \uc678\ubd80\ub85c \ubd84\ub9ac\ud588\ub2e4. \\n\ucd5c\ub300\ud55c \uac04\uacb0\ud558\uac8c \uad6c\ud604\ud55c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud574\ub3c4, \uc774\ub7f0 \ubd80\ubd84\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uc5b4 \uacb0\ud569\uc744 \ud53c\ud558\ub294 \uac83\uc774 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n:::note \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4. \\n\uc774\ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n:::\\n\\n**\uc778\uc218 \ud14c\uc2a4\ud2b8 \uc791\uc131**\\n\\n\uc778\uc218 \ud14c\uc2a4\ud2b8\ub294 \uc0ac\uc6a9\uc790 \uc2a4\ud1a0\ub9ac \uc2dc\ub098\ub9ac\uc624 \uae30\ubc18 \ud14c\uc2a4\ud2b8\ub2e4. \\n\ube0c\ub77c\uc6b4\uc774 \ud574\uc8fc\uc2e0 \uac15\uc758 + \uc720\ud29c\ube0c\uc5d0 \uc788\ub294 \ube0c\ub77c\uc6b4\uc758 \uac15\uc758\ub97c \ubcf4\uace0 \uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0 \uc778\uc218 \ud14c\uc2a4\ud2b8\ub97c \uc801\uc6a9\ud574 \ubcf4\uc558\ub2e4. \\n\uba54\uc11c\ub4dc, \ubcc0\uc218\uba85\uc744 \uc804\ubd80 \ud55c\uae00\ub85c \uc791\uc131\ud588\ub294\ub370 \uc804\uccb4\uc801\uc778 \ud750\ub984\uc744 \uc54c\uae30 \ud3b8\ud558\uace0 \uc77d\uae30\ub3c4 \uc88b\uc558\ub2e4. \\n\uadf8\ub9ac\uace0 \uc778\uc218 \ud14c\uc2a4\ud2b8\uc5d0 \ud544\uc694\ud55c Steps\ub97c \ub9cc\ub4dc\ub294 \uacfc\uc815\uc774 \ub108\ubb34 \uc7ac\ubc0c\uc5c8\ub2e4.\\n\\n\uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4.\\n\\n```java\\n@Nested\\npublic class \ub178\uc120\uc744_\uc804\uccb4_\uc870\ud68c\ud560_\ub54c {\\n\\n @Test\\n void \uc0c1\ud589\uc885\uc810\uc5ed_\ubd80\ud130_\ud558\ud589\uc885\uc810\uc5ed\uc73c\ub85c_\uc815\ub82c\ub41c_\uacb0\uacfc\ub97c_\ubc18\ud658\ud55c\ub2e4() {\\n // given\\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\ucd08\ub85d\\", 0);\\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\uc7a0\uc2e4\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", 5);\\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \uc624\ub978\ucabd, 5);\\n\\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\uace0\ub3d9\\", 0);\\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\ubd09\uc740\uc0ac\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", 3);\\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \\"\uc0bc\uc804\\", \uc624\ub978\ucabd, 7);\\n\\n // when\\n final var \uc870\ud68c_\uacb0\uacfc = \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uc694\uccad();\\n\\n // then\\n \uc694\uccad_\uacb0\uacfc\uc758_\uc0c1\ud0dc\ub97c_\uac80\uc99d\ud55c\ub2e4(\uc870\ud68c_\uacb0\uacfc, \uc815\uc0c1_\uc694\uccad);\\n \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uacb0\uacfc\ub97c_\ud655\uc778\ud55c\ub2e4(\\n \uc870\ud68c_\uacb0\uacfc,\\n \ub178\uc120_\uc815\ubcf4(\\"2\ud638\uc120\\", \\"\ucd08\ub85d\\", 0, \\"\uc7a0\uc2e4\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\"),\\n \ub178\uc120_\uc815\ubcf4(\\"9\ud638\uc120\\", \\"\uace0\ub3d9\\", 0, \\"\ubd09\uc740\uc0ac\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \\"\uc0bc\uc804\\")\\n );\\n }\\n}\\n```\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uc758\uacac \uc870\uc728\ud558\uae30**\\n\\n\ubc00\ub9ac\uac00 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\uc11c \uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \uc9c4\ud589\uc774 \uc218\uc6d4\ud588\ub2e4. \\n\uc758\uc0ac\uc18c\ud1b5\uc774 \ub9e4\uc6b0 \uc798 \ub3fc\uc11c \uc88b\uc558\uace0 \ub355\ubd84\uc5d0 \uc2dc\uac04 \ub0b4\uc5d0 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574 \ubbf8\uc158\uc744 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\\n**\uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\ud558\uae30**\\n\\n\ubc00\ub9ac\ub294 \ucf54\ub529\uc744 \uc5c4\uccad \uaf3c\uaf3c\ud558\uac8c \ud558\ub294 \uac83 \uac19\ub2e4. \\n\ubcc0\uc218\uba85, \uba54\uc11c\ub4dc\uba85\uc744 \uc911\uc694\ud558\uac8c \uc0dd\uac01\ud588\uace0, \uc88b\uc740 \ubcc0\uc218\uba85\uc744 \uc798 \uc9d3\ub294 \uac83 \uac19\ub2e4. \\n\ub610\ud55c \ucf54\ub529\ud560 \ub54c \ub0b4\uac00 \ud3c9\uc18c\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub529 \ucee8\ubca4\uc158\uc5d0 \ub9de\ucdb0\uc8fc\ub294 \uac83 \uac19\uc544\uc11c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud588\ub2e4! \\n\\n**\ud3b8\ud55c \ubd84\uc704\uae30**\\n\\n\uc804\uccb4\uc801\uc73c\ub85c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud558\uac8c \uc9c4\ud589\ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc77c\uc815\ub3c4 \uadf8\ub807\uace0, \ud398\uc5b4 \uc9c4\ud589\ud560 \ub54c\ub3c4 \uadf8\ub807\uace0 \ud070 \ubb38\uc81c\uac00 \uc5c6\uc5c8\ub358 \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ub098\ub294 \uacfc\uc5f0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \ud3b8\ud55c \uc0ac\ub78c\uc77c\uae4c?"},{"id":"accidental-duplication","metadata":{"permalink":"/accidental-duplication","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx","source":"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx","title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","description":"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.","date":"2023-05-24T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 24\uc77c","tags":[{"label":"DTO","permalink":"/tags/dto"}],"readingTime":7.525,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","slug":"accidental-duplication","tags":["DTO"]},"unlisted":false,"prevItem":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","permalink":"/subway-retrospective"},"nextItem":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","permalink":"/shopping-cart-retrospective"}},"content":"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\uc694\uccad\uc5d0 \ub2f4\uae34 Body\ub97c \ud1b5\ud574 \uc804\ub2ec\ubc1b\uc740 \uac12\uc744 DTO\ub85c \ub9e4\ud551\ud558\uc5ec \ucd94\uac00\uc640 \uc218\uc815\uc744 \ud588\ub2e4.\\n\\n### \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815\\n\\n![\uc911\ubcf51](./\uc911\ubcf51.png)\\n\\n\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d\ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0\uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4. \\n\uc704 \uacbd\uc6b0\ub294 \uc911\ubcf5\uc77c\uae4c? \uc911\ubcf5\uc774 \uc544\ub2d0\uae4c?\\n\\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ub9ac\ubdf0\ub97c \ubc1b\uc558\ub2e4.\\n\\n> `ProductSaveRequest`\uc640 `ProductUpdateRequest`\uac00 \uc644\uc804\ud788 \ub3d9\uc77c\ud55c\ub370, \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc744\uae4c? \ub77c\ub294 \ub9ac\ubdf0\ub97c \ub0a8\uacbc\uc5c8\uc5b4\uc694. \uc0ac\uc2e4 \uc0dd\uc131\uacfc \uc218\uc815\uc740 \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac1c\uc5f0\uc131\uc774 \ub192\uc544\uc11c \ubbf8\ub9ac \ubd84\ub9ac\ud574\ub193\ub294 \uac8c \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\uae34 \ud55c\ub370, \uadf8\ub798\ub3c4 \uc911\ubcf5\uc740 \uc2eb\uc5b4\uc11c \uc800\ub3c4 \uc694\uc998 \uc774\ub7f0\uc800\ub7f0 \ubc29\ubc95\ub4e4\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub294 \uc911 \uc785\ub2c8\ub2e4. \ud5c8\ube0c\ub294 \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc5b4\ub5a4 \uc0dd\uac01\uc744 \uac00\uc9c0\uace0 \uc788\uc744\uc9c0 \uad81\uae08\ud558\ub124\uc694 \u314e\u314e\\n> \\n\\n\uc9c8\ubb38\uc5d0 \ub300\ud574 \uc544\ub798\uc640 \uac19\uc774 \ub2f5\ubcc0\uc744 \ud588\ub2e4.\\n\\n> \uc800\uc7a5\uacfc \uc218\uc815\ud560 \ub54c \ud544\uc694\ud55c \ud544\ub4dc\uac12\uc774 \ub3d9\uc77c\ud558\uc5ec \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c\ub294 \ud558\ub098\ub85c \uc0ac\uc6a9\ud574\ub3c4 \ub41c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud558\uc9c0\ub9cc, \ub9d0\uc500\ud574\uc8fc\uc2e0\ub300\ub85c \uc694\uad6c\uc0ac\ud56d\uc774 \ubcc0\uacbd\ub41c\ub2e4\uba74 \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\ub2e4\uace0 \ud310\ub2e8\ud558\uc600\uc2b5\ub2c8\ub2e4!\\n> \\n\\n### \uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5\\n\\n\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec\uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4.\\n\\n- \uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n- \uac70\uc9d3\ub41c \uc911\ubcf5, \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4.\\n\\n\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131\uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.\\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc704 \uc0c1\ud669\uc740 \uc6b0\ubc1c\uc801 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc778\ub2e4. \uadf8\ub798\ub3c4 \uc911\ubcf5\uc744 \uc81c\uac70\ud574\ubcfc \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?\\n\\n### \ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\\n\\n\uc9c0\uae08\uc740 \ucd94\uac00, \uc218\uc815 2\uac00\uc9c0 \uacbd\uc6b0 \ubc16\uc5d0 \uc5c6\uc9c0\ub9cc \uc870\uae08 \ub354 \ubcf5\uc7a1\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc8fc\uc5b4\uc838\uc11c 10\uac00\uc9c0 \uacbd\uc6b0\ub85c \uc785\ub825\uc744 \ubc1b\uc73c\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c? \\n\uc11c\ube44\uc2a4 \uacc4\uce35\uc5d0\uc11c\ub3c4 \uacc4\uce35\uc758 \ubd84\ub9ac\ub97c \uc704\ud574\uc11c \ub2e4\ub978 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uba74 20\uac1c\uc758 DTO\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud560\uae4c? \\n\ub9ac\ubdf0\uc5b4\uac00 \uc54c\ub824\uc900 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud55c \ubc29\ubc95\uc744 \ud1b5\ud574 \uc774\ub97c \ud574\uacb0\ud574\ubcf4\uc790! \\n\\n### \uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc\\n\\n\ud604\uc7ac \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\ub2e4. \\nController\uc640 Service\uc5d0\uc11c \uc800\uc7a5, \uc218\uc815\ud560 \ub54c \uac01\uac01\uc758 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.\\n\ud604\uc7ac DTO\ub294 controller, service \ud328\ud0a4\uc9c0 \ub0b4\uc5d0 \uc788\ub294 \uac83\uc774 \uc544\ub2c8\ub77c dto\ub77c\ub294 \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\ud558\uace0 \uc788\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductService\\n\u251c\u2500\u2500 dto\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n![\uc911\ubcf52](./\uc911\ubcf52.png)\\n\\n### \uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30\\n\\n![\uc911\ubcf53](./\uc911\ubcf53.png)\\n\\n\uc11c\ube44\uc2a4 \ub808\uc774\uc5b4\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uac12\ub4e4\uc744 \uc778\ud130\ud398\uc774\uc2a4\ub85c \uc815\uc758\ud55c\ub2e4. \\n\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 service \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub85c \uc62e\uaca8\uc900\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n```java\\npublic interface ProductSaveRequest {\\n\\n String getName();\\n\\n String getImage();\\n\\n Long getPrice();\\n}\\n\\n// ProductService\\npublic Long save(final ProductSaveRequest request) {\\n final Product product = new Product(request.getName(), request.getImage(), request.getPrice());\\n return productDao.saveAndGetId(product);\\n}\\n```\\n\\n### \uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30\\n\\n![\uc911\ubcf54](./\uc911\ubcf54.png)\\n\\n\uc704\uc5d0\uc11c \uc791\uc131\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc791\uc131\ud55c\ub2e4. \\n\uc694\uccad\uc740 ProductRequest \ud074\ub798\uc2a4\ub85c \ubc1b\uace0, \uc11c\ube44\uc2a4\uc5d0 \uc804\ub2ec\ud560 \ub550 \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\uc758 \uba85\uc138\ub9cc \ub9de\ucd94\uba74 \ubb38\uc81c\uc5c6\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductController\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductRequest\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n```java\\npublic class ProductRequest implements ProductSaveRequest, ProductUpdateRequest {\\n\\n @NotBlank(message = \\"\uc774\ub984\uc740 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\")\\n @Size(min = 1, max = 100, message = \\"\uc774\ub984\uc740 \ucd5c\uc18c {min}\uc790 \uc774\uc0c1, {max}\uc790 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.\\")\\n private final String name;\\n\\n @NotBlank(message = \\"\uc774\ubbf8\uc9c0\ub294 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\")\\n private final String image;\\n\\n @Range(message = \\"\uac00\uaca9\uc740 \ucd5c\uc18c {min}\uc6d0 \uc774\uc0c1, {max}\uc6d0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.\\")\\n private final long price;\\n\\n public ProductRequest(final String name, final String image, final long price) {\\n this.name = name;\\n this.image = image;\\n this.price = price;\\n }\\n\\n @Override\\n public String getName() {\\n return name;\\n }\\n\\n @Override\\n public String getImage() {\\n return image;\\n }\\n\\n @Override\\n public long getPrice() {\\n return price;\\n }\\n}\\n\\n// ProductController\\n@PostMapping(\\"/products\\")\\npublic ResponseEntity save(@Valid @RequestBody final ProductRequest request) {\\n final Long id = productService.save(request);\\n return ResponseEntity.created(URI.create(\\"/products/\\" + id)).build();\\n}\\n```\\n\\n### \uc815\ub9ac\\n\\n\uc704\uc640 \uac19\uc774 \uad6c\ud604\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\ub2e4. \\n\\n1. Service\uc5d0\uc11c \ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc5d0 \ub300\ud55c DTO\ub97c \uc54c\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.\\n2. \uacf5\ud1b5\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 DTO\ub97c \uc81c\uc678\ud558\uace0 DTO \ud328\ud0a4\uc9c0\uc5d0 \ub300\ud55c \uacb0\ud569\ub3c4\uac00 \ub0ae\uc544\uc9c0\uace0, \uac01 \ub808\uc774\uc5b4\uc758 \uc751\uc9d1\ub3c4\uac00 \uc99d\uac00\ud55c\ub2e4.\\n3. \uc694\uccad \uac1d\uccb4\ub9cc \ub2e4\ub974\uace0 \uc11c\ube44\uc2a4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ud589\uc704\ub97c \uc218\ud589\ud558\ub294 \uacbd\uc6b0 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc704 \ubc29\ubc95\uc744 \uc9c0\uae08 \ubbf8\uc158\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560\uae4c \ud558\ub2e4\uac00, \ub098\uc911\uc5d0 \ud544\uc694\ud560 \ub54c \uc801\uc6a9\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\uc544\uc11c \ubbf8\uc158\uc5d0\ub294 \uc801\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\uc0c1\ud669\uc5d0 \ub9de\ucdb0 \uc801\uc7ac\uc801\uc18c\uc5d0 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud574\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98 16\uc7a5 \ub3c5\ub9bd\uc131, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 \\n[https://techblog.woowahan.com/2647/](https://techblog.woowahan.com/2647/) \\n[https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/](https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/)"},{"id":"shopping-cart-retrospective","metadata":{"permalink":"/shopping-cart-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-shopping-cart/pull/244","date":"2023-05-12T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 12\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.845,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","slug":"shopping-cart-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","permalink":"/accidental-duplication"},"nextItem":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","permalink":"/web-racing-car-retrospective"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-shopping-cart/pull/244 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-shopping-cart/pull/300 \\n:::\\n\\n### \uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\\n\\n\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc740 \ube14\ub799\ucea3\uc774\ub791 \uc9c4\ud589\ud588\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d\uc774 \uc5c4\uccad \ubcf5\uc7a1\ud55c \ubbf8\uc158\uc740 \uc544\ub2c8\uc5c8\uace0, \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\ubcf8\uc801\uc778 CRUD\ub97c \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n2\ub2e8\uacc4\uc5d0\uc11c\ub294 Basic \uc778\uc99d\uc744 \ud1b5\ud574 \uc790\uc2e0\uc758 \uc7a5\ubc14\uad6c\ub2c8\uc5d0\ub9cc \uc0c1\ud488\uc744 \ub2f4\uace0, \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \uad6c\ud604\ud558\ub294 \uc694\uad6c\uc0ac\ud56d\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\nInterceptor\ub098 Argument Resolver\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\uac00 \ub192\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc870\uae08 \ub354 \uc54c\uc544\uac04 \ub290\ub08c\uc774\ub2e4. \\n\uc774\uc804\uc5d0 \uc2a4\ud504\ub9c1 \uc0ac\uc6a9\ud560 \ub54c\ub294 \uc544\ubb34 \uc0dd\uac01 \uc5c6\uc774 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub294\ub370, \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \ub54c \uadfc\uac70\uac00 \uc0dd\uae30\uace0 \uc788\ub294 \uac83 \uac19\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**DTO \uc6b0\ubc1c\uc801 \uc911\ubcf5**\\n\\n\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\\n![dto1](./dto1.png)\\n\\n\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d \ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0 \uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\uc744 \ud588\uace0, \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4. \\n\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec \uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4. \\n\\n- \uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n- \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4.\\n\\n\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131 \uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4. \\n\ub530\ub77c\uc11c \ub9ac\ubdf0\uc5b4 \uc6e8\uc9c0\uac00 \uc544\ub798\uc640 \uac19\uc774 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\uace0 \uc54c\ub824\uc8fc\uc168\ub2e4. \\n\\n![dto2](./dto2.png)\\n\\n**Interceptor\uc5d0\uc11c \uc778\uc99d\ud55c \uac12 \uc7ac\uc0ac\uc6a9**\\n\\n\uc0ac\uc2e4 \uc870\ud68c\ub97c \ub450 \ubc88 \ud558\uae30 \uc2eb\uc5b4\uc11c \ub2e4\uc591\ud55c \ubc29\ubc95\uc744 \uc0dd\uac01\ud588\uc5c8\ub294\ub370 \uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 ThreadLocal\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n\uc77c\ub2e8 Tomcat\uc740 \uc694\uccad\ub9c8\ub2e4 \ub2e4\ub978 \uc2a4\ub808\ub4dc\ub97c \uc0ac\uc6a9\ud558\uace0, Interceptor\uc5d0\uc11c \uc870\ud68c\ud574\uc11c \ub9cc\ub4e0 Credential\uc744 ThreadLocal\uc5d0 \ub123\uc5b4\ub450\uc5c8\ub2e4\uac00 ArgumentResolver\uc5d0\uc11c \uaebc\ub0b8 \ub2e4\uc74c ThreadLocal\uc744 clear \ud558\uba74 \ubb38\uc81c\uac00 \uc5c6\uc744 \uac70\ub77c \ud310\ub2e8\ud588\ub2e4. \\n\\n\ub9ac\ubdf0\uc5b4\uc778 \uc6e8\uc9c0\uc5d0\uac8c\ub3c4 \uc5b4\ub5a4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560\uc9c0 \uad81\uae08\uc99d\uc744 \uc791\uc131\ud588\uc5c8\ub2e4. \\n\uc6e8\uc9c0\ub294 email\uc5d0 index\ub97c \uac78\uc5b4\ub450\uace0 dao \uc7ac\uc870\ud68c\ub97c \uc0ac\uc6a9\ud560 \uac83\uc774\ub77c\uace0 \ud588\ub2e4. \\n\uc7ac\uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 db\uc5d0 \uc778\ub371\uc2a4\ub97c \uac78 \uc0dd\uac01\uc740 \ud558\uc9c0 \ubabb\ud588\ub294\ub370, \uc81c\uc77c \uc9c1\uad00\uc801\uc774\uace0 \uc88b\uc740 \ubc29\ubc95\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uae30\ub85d**\\n\\n\ube14\ub799\ucea3\uc740 \uae30\ub85d\uc744 \uad49\uc7a5\ud788 \uc798 \ud558\ub294 \ud06c\ub8e8\uc600\ub2e4. \\n\ub178\uc158\uc5d0 \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ud588\ub358 \ub0b4\uc6a9 + \uace0\ubbfc\ud588\ub358 \ubd80\ubd84 + \ud68c\uace0\ub97c \uaf3c\uaf3c\ud558\uac8c \uae30\ub85d\ud574\uc11c \uacf5\uc720\ud574 \uc8fc\uc5c8\ub2e4. \\n\ucd94\uac00\uc801\uc73c\ub85c \uc774\ubaa8\uc9c0\ub97c \uc801\uadf9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uc5ec \ub354\uc6b1 \uc88b\uc558\ub2e4!\\n\\n**\uc758\uacac \uc77c\uce58\uc2dc\ud0a4\uae30**\\n\\n\ud398\uc5b4 \uc2dc\uac04\uc740 \ud55c\uc815\ub418\uc5b4 \uc788\uace0, \uae30\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574\uc57c \ud55c\ub2e4. \\n\ub530\ub77c\uc11c \uc801\ub2f9\ud788 \ud0c0\ud611\uc744 \ubd10\uc11c \uc758\uacac\uc744 \ube60\ub974\uac8c \uc218\uc6a9\ud574 \ub370\ub4dc\ub77c\uc778\uc744 \ub9de\ucd94\ub294 \uac83\ub3c4 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ube14\ub799\ucea3\uc740 \ub0b4 \uc758\uacac\uc744 \uc798 \ub4e4\uc5b4\uc92c\uace0, \ub355\ubd84\uc5d0 \ub9c9\ud788\ub294 \ubd80\ubd84 \uc5c6\uc774 \ube60\ub974\uac8c \ubbf8\uc158\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\ube68\ub9ac \uce5c\ud574\uc84c\uace0, \uc758\uc0ac\uc18c\ud1b5\uc774 \uc798 \ub3fc\uc11c \uc7ac\ubc0c\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uc5c8\ub2e4!"},{"id":"web-racing-car-retrospective","metadata":{"permalink":"/web-racing-car-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/jwp-racingcar/pull/24","date":"2023-05-02T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 2\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.6,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","slug":"web-racing-car-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","permalink":"/shopping-cart-retrospective"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","permalink":"/tecochat-retrospective-2"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/jwp-racingcar/pull/24 \\n2\ub2e8\uacc4: https://github.com/woowacourse/jwp-racingcar/pull/128 \\n:::\\n\\n### \uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\\n\\n\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud55c\ub2e4\uace0 \uc2dc\uac04\uc774 \ub9ce\uc774 \uc5c6\uc5b4\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc84c\ub2e4. \\n\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\uc5d0\uc11c\ub294 \ube44\ubc84\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\ub808\ubca8 2\uc5d0\uc11c \uc9c4\ud589\ud558\ub294 \uccab \ubbf8\uc158\uc774\ub77c \ub9ce\uc774 \uae34\uc7a5\ub418\uc5c8\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ube44\ubc84\ub791 \ucd08\ubc18\uc5d0 \ub9db\uc788\ub294 \uac83\ub3c4 \ub9ce\uc774 \uba39\uc73c\uba74\uc11c \ube68\ub9ac \uce5c\ud574\uc838\uc11c \uc7ac\ubc0c\uac8c \ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\uc2a4\ud504\ub9c1\uc744 \uc870\uae08 \uc0ac\uc6a9\ud560 \uc904 \uc54c\uc544\uc11c, \ube44\ubc84\ub791 \uac19\uc774 \ud559\uc2b5\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\uccab \ubbf8\uc158\uc774\ub77c \uadf8\ub7f0\uc9c0 \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc740 \uc5c6\uc5c8\uace0, \ucd5c\ub300\ud55c \uae54\ub054\ud558\uac8c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ub09c\uc774\ub3c4 \ub192\uc740 \ubbf8\uc158\uc774 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ub9ac\ubdf0\uc5b4\uc778 \ub77c\ube48\uc5d0\uac8c \uce6d\ucc2c\uc744 \ub9ce\uc774 \ubc1b\uc544\uc11c \uae30\ubd84\uc774 \uc88b\uc558\ub2e4. \\n\ub77c\ube48 \uac10\uc0ac\ud569\ub2c8\ub2e4! \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ucee8\ub514\uc158\ub3c4 \uc88b\uc9c0 \uc54a\uace0 \uc5f4\uc815\ub3c4 \uc2dd\uc740 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4. \\n\ubbf8\uc158\uc774 \ub2e4\uc18c \uc5ec\uc720\ub86d\ub2e4\uace0 \ub290\uaef4\uc838\uc11c, \uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ubd84\ub3c4 \uc798 \uad00\ub9ac\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4. \\n\ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud574\uc11c \ud398\uc5b4\uc5d0\uac8c \ub9ce\uc774 \ubbf8\uc548\ud588\uace0, \ub098 \uc790\uc2e0\uc5d0\uac8c \uc544\uc26c\uc6e0\ub358 \ubd80\ubd84\uc774 \ub9ce\uc558\ub2e4. \\n\\n\uc9c0\ub09c\ubc88 \ud68c\uace0\ub97c \ub2e4\uc2dc \ubcf4\ub294\ub370 \uc9d1\uc911\uc744 \uc798 \ubabb\ud55c \uacbd\uc6b0\uac00 \ub9ce\uc740 \uac83 \uac19\ub2e4. \\n\ub3c4\uc804\uc801\uc774\uc9c0 \uc54a\uac70\ub098 \uc2dc\uac04\uc774 \ubd80\uc871\ud558\uc9c0 \uc54a\uc73c\uba74 \uc9d1\uc911\uc744 \uc798 \ubabb\ud558\ub294 \uac83 \uac19\ub2e4. \\n\uba38\ub9bf\uc18d\uc5d0\uc11c \uc2dc\uac04\uc801 \uc5ec\uc720\uac00 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \ub54c\uac00 \uac00\uc7a5 \uc704\ud5d8\ud55c \uc21c\uac04\uc778 \uac83 \uac19\ub2e4. \\n\\n\ud568\uaed8 \uc790\ub77c\uae30\uc5d0\uc11c \ub098\uc628 `\ub09c\uc774\ub3c4 \ub192\uc774\uae30`\uac00 \ud544\uc694\ud574\uc9c0\ub294 \uc21c\uac04\uc774\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uc911\uc694\ub3c4\uac00 \uc788\ub294 \uc5b4\ub178\ud14c\uc774\uc158\ubd80\ud130 \ud074\ub798\uc2a4 \uc774\ub984\uc5d0 \uac00\uae5d\uac8c \uba85\uc2dc\ud558\uae30**\\n\\n```java\\n@SuppressWarnings(\\"NonAsciiCharacters\\")\\n@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)\\n@Transactional\\n@AutoConfigureMockMvc\\n@SpringBootTest\\npublic class RacingGameIntegrationTest {\\n```\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\ube44\ubc84\uc758 \uc131\uaca9** \\n\ube44\ubc84\uac00 \uc131\uaca9\uc774 \uc88b\uc544\uc11c \ud3b8\ud558\uac8c \ud398\uc5b4\ub97c \ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc131\uae09\ud558\uc9c0 \uc54a\uace0 \uc5ec\uc720\ub85c\uc6cc\uc11c \uc88b\uc558\ub2e4. \\n\\n**\ubbf8\uc158\uc5d0 \uc9d1\uc911\ud558\ub294 \ubd80\ubd84** \\n\ub0b4\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud588\ub294\ub370\ub3c4 \uac19\uc774 \ud398\uc5b4\ub97c \uc798 \uc9c4\ud589\ud55c \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ube44\ubc84\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud574\uc11c \uadf8\ub807\uc9c0 \uc54a\uc558\ub098 \uc0dd\uac01\ud588\ub2e4. \\n\uadfc\uc721\ub9e8 \ube44\ubc84\ub77c \uadf8\ub7f0\uc9c0 \uccb4\ub825\uc774 \uc88b\uc544\uc11c \uadf8\ub7f0\uac00? \\n\uc911\uac04\uc5d0 \uc798 \uc548 \uc26c\uace0\ub3c4 \uc9d1\uc911\ud574\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac78 \ubcf4\uace0 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n**\ud559\uc2b5\uc5d0 \ub300\ud55c \uc5f4\uc815** \\n\ucd94\uac00\uc801\uc73c\ub85c \uc54c\uace0 \uc2f6\uc740 \ubd80\ubd84\uc744 \ub530\ub85c \ud559\uc2b5\ud558\ub294 \uc5f4\uc815\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ube44\ubc84\uc640 \uc2a4\ud504\ub9c1\uc5d0 \ub300\ud574 \uc54c\uc544\uac00\ub294 \uc2dc\uac04\uc744 \ub9ce\uc774 \uac00\uc9c4 \ubd80\ubd84\uc774 \ub9e4\uc6b0 \uc88b\uc558\ub2e4. \\n\ub098\ub3c4 5\uc6d4\ubd80\ud130 \uc870\uae08 \ub354 \ud654\uc774\ud305 \ud574\uc57c\uaca0\ub2e4."},{"id":"tecochat-retrospective-2","metadata":{"permalink":"/tecochat-retrospective-2","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx","source":"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx","title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","description":"\ud504\ub860\ud2b8\uc5d4\ud2b8","date":"2023-05-01T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 1\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.67,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","slug":"tecochat-retrospective-2","tags":["TecoChat","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","permalink":"/web-racing-car-retrospective"},"nextItem":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","permalink":"/jenkins"}},"content":"### \ud504\ub860\ud2b8\uc5d4\ud2b8\\n\\n\ub2c9\ub124\uc784\uc744 \uc785\ub825\ud558\uc5ec \uac04\ub2e8\ud788 \ub85c\uadf8\uc778\ud558\ub294 \ud654\uba74, \ucc44\ud305 \ubaa9\ub85d\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\uace0 \ub2e8\uc77c \ucc44\ud305\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\ub2e4. \\n\ucd94\uac00\ub85c \ucc44\ud305\uc744 \uc774\uc5b4\ub098\uac08 \uc218 \uc788\uac8c \ud558\ub294 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4. \\n\uc790\uc798\ud558\uac8c \uc2e0\uacbd \uc4f8 \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c, \ud504\ub860\ud2b8\uc5d4\ub4dc \ud558\ub294 \uc0ac\ub78c\ub4e4\uc774 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4. \\n\uc5ec\uc720\uac00 \ub41c\ub2e4\uba74 \uc790\uc2e0\uc758 \ucc44\ud305\uc744 \ubcfc \uc218 \uc788\ub294 \uae30\ub2a5\uc774\ub098, \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub294 \uae30\ub2a5, \ub313\uae00 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud560 \uc608\uc815\uc774\ub2e4. \\n\\n### \ubc31\uc5d4\ub4dc\\n\\n\ucd5c\ub300\ud55c \ube68\ub9ac \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uae30\ub85c \uc815\ud574\uc11c, \ubc31\uc5d4\ub4dc\ub294 \ub9d0\ub791\uc774 \uc77c\ub2e8 \ub2e4 \ub9cc\ub4e4\uace0 \uc788\ub2e4. \\n\ub9d0\ub791\uc774 \ud55c \ubd80\ubd84\uc774 \ub108\ubb34 \ub9ce\uc544\uc11c \ub0b4\uac00 \ubabb \ub530\ub77c\uac00\ub294 \uac83 \uac19\ub2e4. \\n\ub098\uc911\uc5d0 \ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc774\ud574\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### Http Request Header\\n\\n\uc544\uc9c1 \uc778\uc99d\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ud558\uc9c0 \uc54a\uc544\uc11c \uc694\uccad \ud5e4\ub354\uc5d0 \uc774\ub984\uc744 \ubcf4\ub0b4\uae30\ub85c \ud588\ub2e4. \\n\ub9d0\ub791\uc774 \ud55c\uae00\uc740 \uc548\ub41c\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c Base64\ub85c \uc778\ucf54\ub529\ud558\uace0, \ubc31\uc5d4\ub4dc\uc5d0\uc11c \ub514\ucf54\ub529 \ud558\uc5ec \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\n\uc544\ub798\ub294 pinia\uc5d0 \uc788\ub294 name \uac12\uc744 \uc778\ucf54\ub529 \ud558\ub294 \ucf54\ub4dc\ub2e4. deprecated \ub418\uc5c8\ub2e4\ub294\ub370, \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560 \uc904 \ubab0\ub77c\uc11c \uc77c\ub2e8 \uc774\uac78 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n```ts\\nconst encodedName = () => {\\n const uriComponent = unescape(encodeURIComponent(name.value));\\n return btoa(uriComponent);\\n};\\n```\\n\\n### Elastic Beanstalk\\n\\n\uac00\uc7a5 \ube60\ub974\uac8c \ubc31\uc5d4\ub4dc\ub97c \ubc30\ud3ec\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ubb58\uc9c0 \uace0\ubbfc\ud558\ub2e4\uac00 Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\nElastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uba74 \uc778\ud504\ub77c\uc5d0 \ub300\ud574 \uc798 \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube60\ub974\uac8c \ubc30\ud3ec\ud558\uace0 \uad00\ub9ac\ud560 \uc218 \uc788\ub2e4. \\n\ubaa8\ub2c8\ud130\ub9c1, \ub85c\uae45, \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4. \\n\\n### Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac\\n\\n\ucd08\uae30 \uc124\uc815 \uc2dc RDS\ub97c \uc5f0\uacb0\ud558\uace0 \uc124\uc815 \uc644\ub8cc \ud6c4 \ubd84\ub9ac\ud55c\ub2e4\uba74, Beanstalk \uc778\uc2a4\ud134\uc2a4 -> RDS \uc694\uccad \uc2dc \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc744 \uc548 \ud574\ub3c4 \ub41c\ub2e4. \\nRDS \ubd84\ub9ac \uc2dc Beanstalk\uc5d0 \uae30\ubcf8\uc801\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub294 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD\uc640 \uac19\uc740 \ud658\uacbd \ubcc0\uc218\uac00 \uac19\uc774 \uc81c\uac70\ub41c\ub2e4. \\n\ucd94\uac00\ub85c Elastic Beanstalk\ub85c RDS\ub97c \uc124\uc815\ud558\uba74 \uae30\ubcf8 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uba85\uc740 ebdb\ub2e4. \\n\\n### Elastic Beanstalk nginx \uc124\uc815\\n\\n\uc5c5\ub85c\ub4dc\ud558\ub294 zip \ud30c\uc77c \ub0b4\ubd80\uc5d0 `.platform/nginx/conf.d/` \uacbd\ub85c\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ucd94\uac00\ud558\uba74 nginx \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n### Jenkins\\n\\n\ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc77c\uc77c\ud788 \ubc30\ud3ec\ud558\uae30 \ubd88\ud3b8\ud574\uc11c Jenkins\ub97c \uc774\uc6a9\ud558\uc5ec Repository\uc5d0 \ucf54\ub4dc\ub97c push \ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ubc30\ud3ec\uac00 \ub418\uac8c \uc124\uc815\ud558\uae30\ub85c \ud588\ub2e4. \\n\uc791\ub144\uc5d0 \ud655\uc778\ud588\uc744 \ub550 2022\ub144 12\uc6d4 31\uc77c\uae4c\uc9c0 EC2 ARM \uae30\ubc18 t4g.small\uc774 \ubb34\ub8cc\uc600\ub294\ub370, \ub2e4\uc2dc \ub4e4\uc5b4\uac00 \ubcf4\ub2c8 2023\ub144\uae4c\uc9c0 12\uc6d4 31\uc77c\uae4c\uc9c0 t4g.small\uc744 \ubb34\ub8cc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\ub2e4. \\nt4g.small\uc740 \ub7a8\uc774 2G\uc778\ub370, \uc608\uc804\uc5d0\ub294 \ubd80\uc871\ud558\uc9c0 \uc54a\uc558\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370 Java 17\uc744 \uc368\uc11c \uadf8\ub7f0\uac00 \ube4c\ub4dc \ud560 \ub54c \ub7a8\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\uc544\uc11c Swap \uba54\ubaa8\ub9ac 2\uae30\uac00\ub97c \ucd94\uac00\ub85c \uc124\uc815\ud588\ub2e4. \\n\ucd94\uac00\ub85c build.gradle\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8 \uc2dc \uc0ac\uc6a9\ud558\ub294 \ub7a8\uc744 \ub298\ub9b4 \uc218 \uc788\ub2e4. \uae30\ubcf8\uac12\uc740 512MB\ub77c\uace0 \ud55c\ub2e4. \\n\\n```groovy\\ntest {\\n maxHeapSize = \\"1024m\\"\\n}\\n```\\n\\n### Jenkins Blue Ocean\\n\\nBlue Ocean\uc740 Jenkins Pipeline\uc744 \uad6c\uc131\ud558\ub294 \ub370\uc5d0 \uc788\uc5b4 \ud3b8\ub9ac\ud558\uac8c \ud574\uc8fc\ub294 \ub3c4\uad6c\ub2e4. \\n\uc2dc\uac01\ud654\ub3c4 \uc798 \ub418\uc5b4\uc788\uace0, \uc124\uc815\ub3c4 \ud3b8\ub9ac\ud55c \uac83 \uac19\ub2e4. \\n\uc624\ub298 \uc801\uc6a9\ud574 \ubcf4\ub2c8 \ub7a8\uc774 \ubd80\uc871\ud558\uc5ec \uc911\uac04\uc5d0 \uc798 \uc548\ub418\uae30\ub3c4 \ud558\uace0 \uadf8\ub798\uc11c \uadf8\ub0e5 \\"Pipeline\ub9cc \uc0ac\uc6a9\ud560 \uac78 \uadf8\ub7ac\ub098?\\" \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Elastic Beanstalk, AWS](https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/Welcome.html) \\n[EC2 AWS Graviton, AWS](https://aws.amazon.com/ko/ec2/graviton/) \\n[Default Memory Settings, AWS](https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings)"},{"id":"jenkins","metadata":{"permalink":"/jenkins","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx","source":"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx","title":"Jenkins\ub85c CI/CD \uc124\uc815","description":"\uc124\uc815 \ud658\uacbd","date":"2023-04-30T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 30\uc77c","tags":[{"label":"Jenkins","permalink":"/tags/jenkins"},{"label":"Elastic Beanstalk","permalink":"/tags/elastic-beanstalk"}],"readingTime":7.495,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","slug":"jenkins","tags":["Jenkins","Elastic Beanstalk"]},"unlisted":false,"prevItem":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","permalink":"/tecochat-retrospective-2"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","permalink":"/tecochat-retrospective-1"}},"content":"### \uc124\uc815 \ud658\uacbd\\n\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc774\ubbf8\uc9c0: Amazon Linux 2023 AMI \\n\uc544\ud0a4\ud14d\uccd0: ARM \\n\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small \\n\ud658\uacbd \uad6c\uc131\uc774 \uc644\ub8cc\ub41c Elastic Beanstalk \\n\ub2e8\uc77c Spring Boot \ud504\ub85c\uc81d\ud2b8\uac00 \uc874\uc7ac\ud558\ub294 Github Repository\\n\\n### \\\\[EC2 CLI\\\\] Swap \uba54\ubaa8\ub9ac \uc124\uc815\\n\\nt4g.small\uc774 \ub7a8\uc774 2G\uc778\ub370 \ub7a8\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \ub290\uaef4\uc838\uc11c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud588\ub2e4. \\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \ub530\ub77c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud558\uace0 free -h \uba85\ub839\uc5b4\ub97c \ud1b5\ud574 \uc798 \uc124\uc815\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n``` bash\\n# fallocate \uc774\uc6a9\ud558\uc5ec \uc2a4\uc651 \ud30c\uc77c \uc0dd\uc131\\nsudo fallocate -l 2G /swapfile\\n\\n# \uad8c\ud55c \uc124\uc815\\nsudo chmod 600 /swapfile\\n\\n# \ud30c\uc77c\uc744 Swap \ud3ec\ub9f7\uc73c\ub85c \ubcc0\uacbd \ud6c4 \uc2dc\uc2a4\ud15c\uc5d0 \ub4f1\ub85d\\nsudo mkswap /swapfile\\nsudo swapon /swapfile\\n\\n# Swap \uba54\ubaa8\ub9ac \ubd80\ud305\uc2dc \uc790\ub3d9\uc73c\ub85c \ub9c8\uc6b4\ud2b8\ud558\ub3c4\ub85d \uc801\uc6a9\\n# \ucd5c\ud558\ub2e8\uc5d0 \ub2e4\uc74c \uad6c\ubb38 \uc124\uc815 -> /swapfile swap swap defaults 0 0\\nsudo vim /etc/fstab\\n```\\n\\n\\n### \\\\[EC2 CLI\\\\] jenkins \uc124\uce58\\n\\n```bash\\nsudo wget -O /etc/yum.repos.d/jenkins.repo \\\\\\n https://pkg.jenkins.io/redhat-stable/jenkins.repo\\nsudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key\\nsudo yum upgrade\\nsudo yum install java-17-amazon-corretto-devel\\nsudo yum install jenkins\\nsudo systemctl daemon-reload\\n```\\n\\n[Jenkins \uacf5\uc2dd \ud648\ud398\uc774\uc9c0](https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos) \ub97c \ucc38\uace0\ud558\uc5ec \uc124\uce58\ud558\ub294 \uac8c \uc88b\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] Jenkins \uc2dc\uc791\\n\\n```bash\\nsudo systemctl enable jenkins\\nsudo systemctl start jenkins\\n```\\n\\nenable\ub85c \uc124\uc815\ud558\uc5ec \ubd80\ud305\uc2dc \uc790\ub3d9\uc2dc\uc791 \ub418\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] nginx & git \uc124\uce58\\n\\n```bash\\nsudo yum install nginx\\nsudo systemctl enable nginx\\nsudo systemctl start nginx\\n\\nsudo yum install git\\n```\\n\\nnginx\uc640 \ucf54\ub4dc\ub97c \ubd88\ub7ec\uc62c \ub54c \uc0ac\uc6a9\ud560 git\uc744 \uc124\uce58\ud55c\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815\\n\\n\uc544\ub798 \uc124\uc815 \ud30c\uc77c\uc740 \uacf5\uc2dd \ud648\ud398\uc774\uc9c0\uc5d0\uc11c \uc548\ub0b4\ud55c \uae30\ubcf8\uc801\uc778 \uc124\uc815 \ud30c\uc77c\uc774\ub2e4.\\n\\n```bash\\nupstream jenkins {\\n keepalive 32; # keepalive connections\\n server 127.0.0.1:8080; # jenkins ip and port\\n}\\n\\n# Required for Jenkins websocket agents\\nmap $http_upgrade $connection_upgrade {\\n default upgrade;\\n \'\' close;\\n}\\n\\nserver {\\n listen 80; # Listen on port 80 for IPv4 requests\\n\\n server_name jenkins.example.com; # replace \'jenkins.example.com\' with your server domain name\\n\\n # this is the jenkins web root directory\\n # (mentioned in the output of \\"systemctl cat jenkins\\")\\n root /var/run/jenkins/war/;\\n\\n access_log /var/log/nginx/jenkins.access.log;\\n error_log /var/log/nginx/jenkins.error.log;\\n\\n # pass through headers from Jenkins that Nginx considers invalid\\n ignore_invalid_headers off;\\n\\n location ~ \\"^/static/[0-9a-fA-F]{8}\\\\/(.*)$\\" {\\n # rewrite all static files into requests to the root\\n # E.g /static/12345678/css/something.css will become /css/something.css\\n rewrite \\"^/static/[0-9a-fA-F]{8}\\\\/(.*)\\" /$1 last;\\n }\\n\\n location /userContent {\\n # have nginx handle all the static requests to userContent folder\\n # note : This is the $JENKINS_HOME dir\\n root /var/lib/jenkins/;\\n if (!-f $request_filename){\\n # this file does not exist, might be a directory or a /**view** url\\n rewrite (.*) /$1 last;\\n break;\\n }\\n sendfile on;\\n }\\n\\n location / {\\n sendfile off;\\n proxy_pass http://jenkins;\\n proxy_redirect default;\\n proxy_http_version 1.1;\\n\\n # Required for Jenkins websocket agents\\n proxy_set_header Connection $connection_upgrade;\\n proxy_set_header Upgrade $http_upgrade;\\n\\n proxy_set_header Host $host;\\n proxy_set_header X-Real-IP $remote_addr;\\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\\n proxy_set_header X-Forwarded-Proto $scheme;\\n proxy_max_temp_file_size 0;\\n\\n #this is the maximum upload size\\n client_max_body_size 10m;\\n client_body_buffer_size 128k;\\n\\n proxy_connect_timeout 90;\\n proxy_send_timeout 90;\\n proxy_read_timeout 90;\\n proxy_buffering off;\\n proxy_request_buffering off; # Required for HTTP CLI commands\\n proxy_set_header Connection \\"\\"; # Clear for keepalive\\n }\\n\\n}\\n```\\n\\nJenkins\ub294 8080 \ud3ec\ud2b8\ub85c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc\ub97c \uc124\uc815\ud574\uc900\ub2e4. \\n`/etc/nginx/conf.d`\xa0\uc544\ub798\xa0`default.conf`\xa0\ud30c\uc77c\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uace0 \uc704\uc640 \uac19\uc774 \uc785\ub825\ud558\uace0 \uc800\uc7a5\ud55c\ub2e4. \\nnginx\uc758 \uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\uc5d0 \uc874\uc7ac\ud558\ub294\xa0`include /etc/nginx/conf.d/*.conf;`\xa0\uc124\uc815 \ub54c\ubb38\uc5d0\xa0`.conf`\xa0\ub85c \ub05d\ub09c\ub2e4\uba74 \uc124\uc815\uc774 \uc801\uc6a9\ub41c\ub2e4. \\n\uc124\uc815 \ud6c4\xa0`sudo nginx -t`\ub85c \uc124\uc815\ud30c\uc77c\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud558\uace0,\xa0`sudo systemctl restart nginx`\xa0\uba85\ub839\uc5b4\ub85c nginx\ub97c \uc7ac\uc2dc\uc791\ud55c\ub2e4. \\n\\n### \\\\[Jenkins\\\\] Jenkins \uc811\uc18d\\n\\nJenkins\ub97c \uc124\uce58\ud55c EC2 \uc778\uc2a4\ud134\uc2a4 \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc5d0 80\ubc88 \ud3ec\ud2b8\uac00 \uc5f4\ub824\uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\nEC2\uc758 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \ub4e4\uc5b4\uac00\uba74 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4.\\n\\n![jenkins-start](./jenkins-start.png)\\n\\n\ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud558\ub294\ub370 `sudo cat /var/lib/jenkins/secrets/initialAdminPasswor` \ub97c \uc785\ub825\ud574 \ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc5bb\uc744 \uc218 \uc788\ub2e4. \\n\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 \ud50c\ub7ec\uadf8\uc778 \uc124\uc815 \ucc3d\uc774 \ub098\uc62c\ud150\ub370 `install suggested plugins`\uc744 \ud074\ub9ad\ud558\uc5ec Jenkins\uac00 \ucd94\ucc9c\ud558\ub294 \uae30\ubcf8 \ud50c\ub7ec\uadf8\uc778\ub4e4\uc744 \uc124\uce58\ud558\uba74 \ub41c\ub2e4. \\n\ud50c\ub7ec\uadf8\uc778\uc744 \uc124\uce58\ud558\uba74 \uacc4\uc815 \ubc0f \uc8fc\uc18c \uc124\uc815\uc744 \ud574\uc57c\ud558\ub294\ub370 \uc774\uac74 \ud3b8\ud558\uac8c \uc124\uc815\ud558\uba74 \ub41c\ub2e4. \\n\\n### \\\\[Jenkins\\\\] Jenkins Blue Ocean \uc124\uce58\\n\\nJenkins \uad00\ub9ac \u2192 Plugin Manager\uc5d0\uc11c Blue Ocean\uc744 \uac80\uc0c9\ud574 \uc124\uce58\ud55c\ub2e4.\\n\\n### \\\\[AWS IAM & EC2\\\\] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30\\n\\nS3\uc640 Elastic Beanstalk\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub824\uba74 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk \ub450 \uac1c\uc758 \uc815\ucc45\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uc5ed\ud560\uc744 \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4. \\nIAM\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc774 \uc5ed\ud560\uc744 \ud558\ub098 \uc0c8\ub85c \uc0dd\uc131\ud55c\ub2e4.\\n\\n1. \uc5d4\ud130\ud2f0 \uc120\ud0dd\\n\\n![aws-iam1](./aws-iam1.png)\\n\\n2. \uad8c\ud55c \ucd94\uac00\\n\\n![aws-iam2](./aws-iam2.png)\\n\\n3. \uc774\ub984 \uc9c0\uc815, \uac80\ud1a0 \ubc0f \uc0dd\uc131\\n\\n![aws-iam3](./aws-iam3.png)\\n\\n4. \uc0dd\uc131\ud55c IAM EC2 Jenkins \uc778\uc2a4\ud134\uc2a4\ub97c \uc120\ud0dd\ud558\uace0, \uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc744 \ub20c\ub7ec Role \uc124\uc815\\n\\n![aws-iam4](./aws-iam4.png)\\n\\n### \\\\[AWS S3\\\\] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131\\n\\n\ubc84\ud0b7\uc744 \uc0dd\uc131\ud560 \ub54c \ub2e4\uc74c \uc124\uc815\uc744 \uc81c\uc678\ud558\uace0 \ubaa8\ub450 \ucc28\ub2e8 \ud65c\uc131\ud654\ub97c \ud574\uc900\ub2e4.\\n\\n- `\uc0c8 ACL(\uc561\uc138\uc2a4 \uc81c\uc5b4 \ubaa9\ub85d)\uc744 \ud1b5\ud574 \ubd80\uc5ec\ub41c \ubc84\ud0b7 \ubc0f \uac1d\uccb4\uc5d0 \ub300\ud55c \ud37c\ube14\ub9ad \uc561\uc138\uc2a4 \ucc28\ub2e8`\\n\\n![aws-s3](./aws-s3.png)\\n\\n### \\\\[Github\\\\] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131\\n\\nrepo, user:email \uad8c\ud55c\uc774 \uc788\ub294 \ud1a0\ud070\uc774 \ud544\uc694\ud558\ub2e4. \\n\\n### \\\\[Jenkins\\\\] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\\n\\n![jenkins-blue-ocean1](./jenkins-blue-ocean1.png)\\n\\n\ube14\ub8e8 \uc624\uc158 \uc5f4\uae30\ub85c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc0dd\uc131\ud55c\ub2e4. \\n\ud1a0\ud070 \uc785\ub825 \u2192 \uc870\uc9c1 \uc120\ud0dd \u2192 CI/CD \uc124\uc815\ud560 Repository \uc120\ud0dd\uc744 \ud558\uba74 \ud30c\uc774\ud504\ub77c\uc778 \ucc3d\uc73c\ub85c \ub118\uc5b4\uac04\ub2e4. \\nJenkinsfile\uc744 \uc9c1\uc811 \uc791\uc131\ud558\uc5ec \uc124\uc815\ud558\uae30 \uc704\ud574 \uac04\ub2e8\ud558\uac8c print \ud558\ub098 \ucd9c\ub825\ud558\ub294 \uac83\uc73c\ub85c \uc124\uc815\ud588\ub2e4. \\n\\n![jenkins-blue-ocean2](./jenkins-blue-ocean2.png)\\n\\n\ud30c\uc774\ud504\ub77c\uc778\uc774 \uc2e4\ud589\ub420 \ud150\ub370 pipeline status\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ucd08\ub85d\ubd88\uc774 \ub728\uba74 \ub41c\ub2e4.\\n\\n![jenkins-blue-ocean3](./jenkins-blue-ocean3.png)\\n\\n### \\\\[Github Repsoitory\\\\] Jenkinsfile \uc124\uc815\\n\\n\ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\uc744 \ud1b5\ud574 \uc124\uc815\ud558\uba74 Jenkinsfile\uc774 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc9c0\uace0, \uc544\ub798\uc640 \uac19\uc774 \uc6d0\ud558\ub294 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc124\uc815\ud55c\ub2e4.\\n\\n```bash\\npipeline {\\n agent any\\n stages {\\n stage(\'build and test\') {\\n steps {\\n sh \'/gradlew clean build\'\\n }\\n }\\n stage(\'zip\') {\\n steps {\\n sh \'mv ./build/libs/woowachat.jar .\'\\n sh \'zip -r woowachat.zip .platform delivery.jar Procfile\'\\n }\\n }\\n stage(\'upload\') {\\n steps {\\n sh \'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2\'\\n }\\n }\\n stage(\'deploy\') {\\n steps {\\n sh \'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket=\\"woowa-chat\\",S3Key=\\"woowachat.zip\\"\'\\n sh \'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}\'\\n }\\n }\\n }\\n}\\n```\\n\\n### \\\\[Github\\\\] Webhooks \uc124\uc815\\n\\n![github-hook](./github-hook.png)\\n\\npush \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud560 \ub54c `http://Jenkins\uc8fc\uc18c/github-webhook/` \ub85c post request\ub97c \ud558\ub3c4\ub85d \uc6f9\ud6c5\uc744 \uc124\uc815\ud55c\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Install Jenkins - CentOS, Jenkins](https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos) \\n[Nginx Reverse Proxy Configuration, Jenkins](https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/) \\n[Amazon Corretto 17 JDK Install, AWS](https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html) \\n[Amazon Linux 2023 packages, AWS](https://docs.aws.amazon.com/linux/al2023/release-notes/all-packages-al2023-20230419.html)"},{"id":"tecochat-retrospective-1","metadata":{"permalink":"/tecochat-retrospective-1","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx","source":"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx","title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","description":"4\uc6d4 21\uc77c \uae08\uc694\uc77c","date":"2023-04-22T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 22\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.68,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","slug":"tecochat-retrospective-1","tags":["TecoChat","Retrospective"]},"unlisted":false,"prevItem":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","permalink":"/jenkins"},"nextItem":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","permalink":"/book-leadership-and-self-deception"}},"content":"### 4\uc6d4 21\uc77c \uae08\uc694\uc77c\\n\\n\ub808\ubca8 2\ub97c \uc2dc\uc791\ud55c \ub4a4 \ub0b4\uac00 \ud559\uc2b5\uc5d0 \ub300\ud55c \ubc29\ud5a5\uc744 \uc783\uc5b4\ubc84\ub838\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub808\ubca8 3, 4\uc5d0\uc11c \ub098\ub9cc\uc758 \uac15\uc810\uc744 \uac00\uc9c0\uace0 \uc2f6\uc5b4 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\ub2e8\uc21c\ud788 \uc2a4\ud504\ub9c1\uc744 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ud6a8\uc728\uc774 \ub9ce\uc774 \ub5a8\uc5b4\uc9c4\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uae00\uc4f0\uae30 \uc218\uc0c1\uc73c\ub85c \ubc1b\uc740 \ucfe0\ud3f0\uc744 \uc0ac\uc6a9\ud574 \ube0c\ub77c\uc6b4\uc5d0\uac8c \ucee4\ud53c\ucc57\uc744 \uc2e0\uccad\ud588\uace0, \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud574\ubcf4\ub77c\ub294 \ub2f5\uc744 \ubc1b\uc558\ub2e4. \\n\\n\ub098\ub294 \uc544\uc774\ub514\uc5b4\ub97c \ubabb\ub0b4\ub294 \ud3b8\uc778\ub370 \ube0c\ub77c\uc6b4\uc774 \uc544\uc774\ub514\uc5b4\uae4c\uc9c0 \ub358\uc838\uc8fc\uc168\ub2e4. \\n`Chat-GPT \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uace0, \ud574\ub2f9 \ud06c\ub8e8\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc744 \uacf5\uc720\ud560 \uc218 \uc788\ub294 \uac74 \uc5b4\ub5a4\uc9c0?` \\n\\n\uae30\uc220\uc774 \ubaa9\uc801\uc778 \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4\ub294 \ub2f5\ubcc0\uc744 \ub4e4\uc5c8\uace0, \ud63c\uc790 \uc544\ub2c8\uba74 \ud398\uc5b4\ud560 \uc218 \uc788\uc744 \uc815\ub3c4\uc758 \uc778\uc6d0\uc73c\ub85c \uc9c4\ud589\ud558\uba74 \uc88b\uaca0\ub2e4\uace0 \ud558\uc168\ub2e4. \\n\ud504\ub860\ud2b8\ub791 \uac04\ub2e8\ud558\uac8c \ubc30\ud3ec\uae4c\uc9c0 \ud574\ubcf8 \uacbd\ud5d8\uc774 \uc788\uc5b4\uc11c \ud63c\uc790\ud574\ub3c4 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc744 \uac83 \uac19\uc544\uc11c \ud63c\uc790 \ud558\uae30\ub85c \ub9c8\uc74c\uc744 \uba39\uc5c8\ub2e4. \\n\\n\uc774\uac74 \ubabb\ucc38\uc9c0\\n\\n### \ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?\\n\\n\ucee4\ud53c\ucc57\uc774 \ub05d\ub098\uace0 \uc9d1\uc73c\ub85c \ub3cc\uc544\uac00\ub294 \uae38\uc5d0 \ubc14\ub85c \ub3c4\uba54\uc778\uc744 \uad6c\ub9e4\ud558\ub824\uace0 namecheap\uc5d0\uc11c \uc801\ub2f9\ud55c \ub3c4\uba54\uc778\uc774 \uc5c6\uc744\uae4c \uac80\uc0c9\uc744 \uacc4\uc18d\ud588\ub2e4. \\n\ub9c8\uce58 \uc5b4\ub9b4 \ub54c \ud588\ub358 \uac8c\uc784 \ub2c9\ub124\uc784 \uc815\ud558\ub294 \uac83\ucc98\ub7fc \uc2dc\uac04\uc774 \uc624\ub798 \uac78\ub838\ub2e4. \\ndev, io, chat \ub3c4\uba54\uc778\uc774 \ud6c4\ubcf4\uc600\uace0 \uc9d1 \uac00\ub294 \uae38\uc5d0 \uacb0\uc815\ub9cc \ud558\ub2e4\uac00 \uad6c\ub9e4\ud558\uc9c0 \ubabb\ud588\ub2e4.\\n\\n### \ub9d0\ub791\uc758 DM\\n\\n\uc9d1\uc5d0 \uac00\uc11c \ubc25\uc744 \uba39\uace0 \ub9d0\ub791\uc774\ub791 DM \ud558\ub2e4 \ud504\ub85c\uc81d\ud2b8\ub97c \uac19\uc774 \ud558\uc790\ub294 \uc774\uc57c\uae30\uac00 \ub098\uc654\ub2e4. \\n\uc6b0\ud14c\ucf54 \ucd5c\uace0 \uace0\uc218 \ub9d0\ub791\uc758 \uc694\uad6c\ub77c \uc218\ub77d\ud558\uc9c0 \uc54a\uc73c\uba74 \ud6c4\ud3ed\ud48d\uc744 \uac10\ub2f9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\\n\uc774\ub7f0\uc800\ub7f0 \ub300\ud654\ub97c \ub098\ub204\ub2e4\uac00 \ub09c \ube60\ub974\uac8c \ud504\ub85c\ud1a0\ud0c0\uc785\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uace0 \uc2f6\uc5b4\uc11c \ud504\ub860\ud2b8\ub97c \uad6c\ud604\ud55c\ub2e4\uace0 \ud588\uace0, \ub9d0\ub791\uc740 GPT api\ub97c \uc870\uc0ac\ud558\uae30\ub85c \ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub3c4\uba54\uc778\uc5d0 \uad00\ud55c \uc774\uc57c\uae30\ub97c \ud558\ub2e4\uac00 woowachat\uc774 \uc5b8\uae09\ub418\uc5c8\uace0, namecheap\uc5d0\uc11c chat \ub3c4\uba54\uc778\uc744 \uc0ac\uc6a9\ud55c woowa.chat\uc73c\ub85c \uad6c\ub9e4\ud588\ub2e4. \\n\uc774\ud6c4\uc5d0 teco.chat\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4!\\n\\n### \ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec\\n\\n\ud1a0\uc694\uc77c\uc5d0 \uad6c\ub9e4\ud55c \ub3c4\uba54\uc778\uc744 CDN, \ubcf4\uc548 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 Cloudflare\uc5d0 \ub3c4\uba54\uc778 \ub4f1\ub85d\uc744 \ud588\ub2e4. \\n\ub098\uc5d0\uac8c \uc775\uc219\ud55c Nuxt3\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\uace0, Cloudflare Pages\ub97c \uc774\uc6a9\ud558\uc5ec \ubc30\ud3ec\ud588\ub2e4. \\n\\n### GPT\\n\\n\ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud558\ub2c8 api limit\uc774 \uc788\uc5b4 \ubd84\ub2f9 3\ubc88\ubc16\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uc77c\ub2e8 \ubc31\uc5d4\ub4dc\ub97c \uad6c\ucd95\ud558\uae30 \uc804\uc5d0\ub294 \ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud560 \uc0dd\uac01\uc774\ub2e4. \\n\\n### Sonarcloud\\n\\n\uc815\uc801 \ucf54\ub4dc \ubd84\uc11d \ub3c4\uad6c\ub85c Sonarcloud\ub97c \uc801\uc6a9\ud588\ub2e4. \\nSonarcloud\ub294 SonarQube\uc758 SaaS \ubc84\uc804\uc774\uace0 \uc0ac\uc6a9\uc774 \ub9e4\uc6b0 \ud3b8\ud558\ub2e4. \\n\uc608\uc804\uc5d0 Sonarcloud\ub97c \uc0ac\uc6a9\ud560 \ub550 \ubc84\ud2bc \uba87 \ubc88 \ub204\ub974\uba74 \uc801\uc6a9\ud560 \uc218 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \ubc14\ub85c github action\uc744 \uc0ac\uc6a9\ud558\ub77c\ub294 \uc548\ub0b4 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud588\ub2e4. \\nSonarcloud\uac00 \uc790\uccb4\uc801\uc73c\ub85c github repository\uc5d0 push \ud558\uba74 \uc815\uc801 \ubd84\uc11d\uc744 \ud574\uc8fc\ub294 \uae30\ub2a5\uc744 \uc6d0\ud588\uace0, Administration -> Analysis Method\uc5d0 Automatic Analysis\ub97c \uc124\uc815\ud558\ub2c8 \ub418\uc5c8\ub2e4. \\n\ub108\ubb34 \uaf41\uaf41 \uc228\uaca8\uc838\uc788\ub124\\n\\n### Tiptap\\n\\n\ucf54\ub4dc \ud558\uc774\ub77c\uc774\ud305 \uae30\ub2a5\uc744 \ub123\uace0 \uc2f6\uc5b4\uc11c Tiptap\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\nTiptap\uc740 Headless WYSIWYG \uc5d0\ub514\ud130\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uae30\ub2a5\uc5d0 \ud2b9\ud654\ub418\uc5b4\uc788\ub294 \uc5d0\ub514\ud130\ub2e4. \\n\uc544\uc9c1 Tiptap\uc774 \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uae30\ub2a5\uc744 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc0ac\uc6a9\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc CodeBlockLowlight \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucf54\ub4dc \ube14\ub85d\uc744 \uc608\uc058\uac8c \ucd9c\ub825\ud560 \uc218 \uc788\uc5c8\ub2e4. \\napi \ubc18\ud658\uac12 \uadf8\ub300\ub85c tiptap\uc758 content\uc5d0 \uc124\uc815\ud588\ub354\ub2c8 \ucf54\ub4dc \ube14\ub85d\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc544\uc11c \ubc31 \ud2f1 3\uac1c\ub97c `
`\ub85c \ubcc0\ud658\ud588\ub2e4.  \\n\ucd94\uac00\ub85c \ub744\uc5b4\uc4f0\uae30\ub3c4 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc544\uc11c `\\\\n`\ub97c `
`\ud0dc\uadf8\ub85c \ubcc0\ud658\ud588\ub2e4. \\n\ubcc0\ud658\ud558\ub294 \ub85c\uc9c1\uc740 GPT\uc758 \ub3c4\uc6c0\uc744 \ub9ce\uc774 \ubc1b\uc558\ub2e4. \\n\\n```ts\\nconst replaceCodeFences = (input: String) => {\\n const codeFencesRegex = /```([\\\\w-]*)\\\\n([\\\\s\\\\S]*?)\\\\n```/g;\\n return input\\n .replace(codeFencesRegex, (match, p1, p2) => {\\n const languageClass = p1 ? ` class=\\"language-${p1}\\"` : \\"\\";\\n return `
${p2}
`;\\n })\\n .replace(/\\\\n/g, \\"
\\");\\n};\\n```\\n\\nTiptap\uc744 \uc801\uc6a9\ud558\ub2c8 \ub2e4\uc74c\uacfc \uac19\uc774 \uae54\ub054\ud55c \ucf54\ub4dc \ube14\ub85d\uc744 \ubcfc \uc218 \uc788\uc5c8\ub2e4. \\n\\n![tecochat](./teco-chat.png)\\n\\n### \ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9\\n\\n\ud0c0\uc774\ud2c0\uc740 \ubc30\ub2ec\uc758\ubbfc\uc871 \ub3c4\ud604\uccb4, \ub0b4\uc6a9\uc740 IBM Plex Sans\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\ucd94\uac00\ub85c favicon\ub3c4 \uac04\ub2e8\ud558\uac8c \uc801\uc6a9\ud574\uc11c \ub9cc\uc871\uc2a4\ub7ec\uc6e0\ub2e4."},{"id":"book-leadership-and-self-deception","metadata":{"permalink":"/book-leadership-and-self-deception","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx","source":"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx","title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","description":"\ucc45 \uc815\ubcf4","date":"2023-04-08T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 8\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":5.16,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","slug":"book-leadership-and-self-deception","tags":["Book"]},"unlisted":false,"prevItem":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","permalink":"/tecochat-retrospective-1"},"nextItem":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/innodb-lock"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c \\n> \uc544\ube48\uc800\uc5f0\uad6c\uc18c\\n> \\n\\n### \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\\n\\n\ucc45\uc5d0\uc11c\ub294 \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc744 \ub2e4\ub8ec\ub2e4. \\n- \uc790\uae30\uae30\ub9cc: \uc790\uc2e0\uc758 \ubb38\uc81c\ub97c \uc778\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \\n- \uc790\uae30\ubc30\ubc18: \ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ubb34\uc5b8\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uc744 \ubc18\ud558\ub294 \ud589\uc704\\n\\n\uc790\uae30\ubc30\ubc18\uc744 \ud55c\ub2e4\uba74 \uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uac00 \ub41c\ub2e4. \\n\uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uc5d0 \ube60\uc9c0\ub294 \uac83\uc744 \ucc45\uc5d0\uc11c\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac04\ub2e4\uace0 \ud45c\ud604\ud55c\ub2e4. \\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\ucd5c\uadfc\uc5d0 \uc77d\uc740 \ucc45 \uc911 \uac00\uc7a5 \ub9c8\uc74c\uc774 \ubd88\ud3b8\ud588\ub2e4. \\n\uadf8\ub807\uae30\uc5d0 \ub354\ub354\uc6b1 \ub098\uc5d0\uac8c \ud544\uc694\ud55c \ub0b4\uc6a9\uc774 \ub2f4\uaca8\uc788\uc5c8\ub2e4. \\n\\n\uc0b4\uba74\uc11c \ub9ce\uc740 \uc120\ud0dd\uc758 \uc21c\uac04\uc774 \uc874\uc7ac\ud588\uace0, \uadf8 \uc21c\uac04\ub9c8\ub2e4 \uc790\uae30\ubc30\ubc18\uc744 \ud0dd\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4. \\n\uc791\uac8c\ub294 \uc9d1\uc548\uc77c\uc744 \ud574\uc57c \ud558\ub294\ub370 \ubab8\uc774 \uc870\uae08 \ud798\ub4e4\ub2e4\uace0 \ud558\uc9c0 \uc54a\uac70\ub098 \\n\ud06c\uac8c\ub294 \uc798\ubabb\uc744 \uc778\uc815\ud574\uc57c \ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uadf8\ub7ec\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uac00 \uc788\uc5c8\ub2e4. \\n\uc774\ub7f0 \uc0c1\ud669\uc774 \ubc18\ubcf5\ub418\uc5b4 \uacb0\uad6d \uc0c1\uc790 \uc548\uc5d0 \ub098 \uc790\uc2e0\uc744 \uac00\ub450\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4. \\n\\n\ub354 \ub098\uc740 \uc0b6\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \uc9c0\uc18d\uc801\uc73c\ub85c \ud655\uc778\ud558\uace0, \uc0c1\uc790 \ubc16\uc73c\ub85c \ub098\uac00\ub824\ub294 \uc5f0\uc2b5\uc744 \ud574\uc57c\uaca0\ub2e4. \\n\ub113\uc740 \uc2dc\uc120\uc744 \uac00\uc9c0\uace0, \ud56d\uc0c1 \ub0b4\uac00 \ud2c0\ub9b4 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc0dd\uac01\ud558\uace0 \uc0b4\uc544\uac00\uc790. \\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \uc6b0\ub9ac\uc758 \uc0dd\uac01\uc740 \uc9c0\uc2dd\ubcf4\ub2e4 \uc791\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc9c0\uc2dd\uc740 \uc0ac\ub791\ubcf4\ub2e4 \uc791\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc0ac\ub791\uc740 \uc874\uc7ac\ubcf4\ub2e4 \uc791\ub2e4. \\n\uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc0dd\uac01\ud558\ub294 \ub098\ub294 \uc2e4\uc81c\uc758 \ub098\ubcf4\ub2e4 \uadf8\ub9cc\ud07c \uc791\ub2e4. \\nR. D. \ub7ad \\np.19\\n>\\n\\n> \uc6b0\ub9ac\uac00 \uc678\uc801\uc73c\ub85c \uc5b4\ub5a4 \ud589\ub3d9\uc744 \ud558\ub4e0\uc9c0 \uac04\uc5d0, \uc0ac\ub78c\ub4e4\uc740 \uc6b0\ub9ac \ub9c8\uc74c\uc5d0\uc11c \uadf8\ub4e4\uc744 \uc5b4\ub5bb\uac8c \ub300\ud558\uace0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \uc8fc\ub85c \ubc18\uc751\ud569\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uac00 \uc0ac\ub78c\ub4e4\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \ub290\ub07c\uac8c \ub418\ub294\uc9c0\ub294 \uc6b0\ub9ac\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \ud639\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c0\uac8c \ub429\ub2c8\ub2e4. \\np.66\\n>\\n\\n> \ube44\ub09c\uc740 \uac10\uc815\uc5d0 \uc18d\ud558\uace0 \ub099\uad00\uc740 \uc758\uc9c0\uc5d0 \uc18d\ud55c\ub2e4. \\n\uc778\uac04\uc740 \uac10\uc815\ubcf4\ub2e4 \ub354 \ud070 \uc874\uc7ac\uc774\ub2e4. \\n\uc54c\ub7ad, \ud0c1\ub2db\ud55c \\np.103\\n>\\n\\n> \uc6b0\ub9ac\uac00 \uc790\uc2e0\uc5d0\uac8c\ub9cc \uc9d1\uc911\ud558\uace0 \uc788\ub294 \ud55c, \ud63c\uc790\uc11c \uc77c\ud558\ub294 \uac83 \uc774\uc0c1\uc758 \ucc3d\uc870\uc801\uc778 \uacb0\uacfc\ub098 \ud611\ub825\uc744 \uc774\ub04c\uc5b4 \ub0b8\ub2e4\ub294 \uac83\uc740 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4. \\n\uc624\ub298\ub0a0 \uacbd\uc81c \ud658\uacbd\uc5d0\uc11c\ub294 \ud63c\uc790\uc11c\ub294 \uc77c\uc758 \uacb0\uacfc\ub97c \ud0c1\uc6d4\ud558\uac8c \ub9cc\ub4e4\uc5b4 \ub0b4\uae30\uac00 \uc5b4\ub835\uc2b5\ub2c8\ub2e4. \\n\ub0b4\uac00 \uc911\uc2ec\uc774\uc5b4\uc57c \ub41c\ub2e4\ub294 \ud3d0\uc1c4\uc801\uc778 \uc0ac\uace0\ub294 \ud568\uaed8 \uc77c\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uc5f4\uc815\uc744 \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud569\ub2c8\ub2e4. \\np.175\\n> \\n\\n> \uc194\uc9c1\ud568\uc740 \uc6b0\ub9ac\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\ub294 \uc5f4\uc1e0\uc785\ub2c8\ub2e4. \\n\uadf8\uac83\uc740 \uc790\uc2e0\uc758 \ud589\ub3d9\uacfc \uad00\ub828\ub41c \uc0ac\ub78c\uc5d0 \ub300\ud574 \uae30\uaebc\uc774 \uc0ac\uacfc\ub97c \ud558\ub294 \uac83\uc785\ub2c8\ub2e4. \\n\uadf8\uac83\ub9cc\uc774 \uc2e4\ud0c0\ub798\ucc98\ub7fc \uc5c9\ud0a8 \uad00\uacc4\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\uc8e0. \\np.188\\n> \\n\\n> \ub204\uad70\uac00\ub97c \ub098\uc640 \uac19\uc774 \ub3d9\uc77c\ud55c \uac00\uce58\ub97c \uc9c0\ub2cc \ud55c \uc778\uac04\uc73c\ub85c \uc0dd\uac01\ud574\uc11c \uadf8 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \ubc16\uc5d0 \uacc4\uc18d \uba38\ubb34\ub974\uace0 \uc2f6\uc740 \uc5f4\ub9dd\uc774 \uc0dd\uae38 \ub54c, \ub098\ub294 \uc774\ubbf8 \uadf8 \uc0ac\ub78c\uc5d0 \ub300\ud574 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub2e4. \\np.214\\n> \\n\\n> \ub300\ubd80\ubd84\uc758 \uc0ac\ub78c\ub4e4\uc774 \uad00\uacc4 \uae30\uc220\uc744 \uac00\uc9c0\uace0 \uadf8\ub4e4\uc774 \uacaa\uace0 \uc788\ub294 \ubb38\uc81c\ub97c \ubc14\ub85c\uc7a1\uc73c\ub824\uace0 \ud558\ub294 \ub178\ub825\uc774 \uacb0\uc2e4\uc744 \uc5bb\uc9c0 \ubabb\ud558\ub294 \uac83\uc740 \uacb0\ucf54 \uadf8\ub7ec\ud55c \uae30\uc220 \ubd80\uc871 \ub54c\ubb38\uc5d0 \uc0dd\uae30\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4. \\n\uadf8\uac83\ub4e4\uc740 \uc790\uae30\ubc30\ubc18 \ub54c\ubb38\uc5d0 \uc0dd\uaca8\ub0a9\ub2c8\ub2e4. \\np.224\\n>\\n\\n> \uc6b0\ub9ac\ub294 \ud568\uaed8 \uc77c\ud558\uace0 \uc6b0\ub9ac\uc640 \ud568\uaed8 \uc0b4\uc544\uac00\ub294 \uc0ac\ub78c\uc774 \uc9c4\uc815\uc73c\ub85c \ub204\uad6c\uc778\uc9c0 \uc54c\uc9c0 \ubabb\ud569\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uac00 \uadf8\ub4e4\uacfc \uc9c4\uc815\uc73c\ub85c \ud568\uaed8 \uc18c\ud1b5\ud558\uae30 \uc804\uae4c\uc9c0\ub294 \uc6b0\ub9ac\ub294 \uadf8\ub4e4\uc758 \uac00\uce58\ub97c \uc798 \ubaa8\ub985\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc704\ub300\ud568\uc774\ub780 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc704\ub300\ud55c \uc810\uc744 \ubc1c\uacac\ud574 \uc8fc\ub294 \uac83\uc5d0 \uc788\uc2b5\ub2c8\ub2e4. \\np.280\\n>"},{"id":"innodb-lock","metadata":{"permalink":"/innodb-lock","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","source":"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","description":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","date":"2023-04-07T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 7\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Lock","permalink":"/tags/lock"},{"label":"InnoDB","permalink":"/tags/inno-db"}],"readingTime":5.805,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","slug":"innodb-lock","tags":["DataBase","Lock","InnoDB"]},"unlisted":false,"prevItem":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","permalink":"/book-leadership-and-self-deception"},"nextItem":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/mysql-lock"}},"content":"## InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08\\n\\nMySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08\uacfc \ubcc4\uac1c\ub85c \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub0b4\ubd80\uc5d0\uc11c \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \\n\ubcf4\ud1b5 \uba85\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\ub294 \ub4dc\ubb3c\uace0, \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ubb35\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc774 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n\ub3d9\uc2dc\uc131 \uc81c\uc5b4 \ubc29\uc2dd\uc5d0\ub294 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uacfc \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc774 \uc788\ub2e4. \\nInnoDB\ub294 \uae30\ubcf8\uc801\uc73c\ub85c MVCC(\ub2e4\uc911 \ubc84\uc804 \ub3d9\uc2dc\uc131 \uc81c\uc5b4)\ub97c \ud1b5\ud574 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uace0 \ub77d\uc744 \ud1b5\ud574 \ud2b9\uc815 \uc0c1\ud669\uc5d0\uc11c \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n:::note \ub099\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(OCC, Optimistic concurrency control)\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \uc11c\ub85c \ucda9\ub3cc\ud558\uc9c0 \uc54a\ub294\ub2e4\uace0 \uac00\uc815\ud558\ub294 \ubc29\uc2dd \\n\\n:::\\n\\n:::note \ube44\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(PCC, Pessimistic Concurrency Control)\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ucda9\ub3cc\ud558\ub294 \uac00\uc815\ud558\uc5d0 \uc7a0\uae08\uc744 \uac70\ub294 \ubc29\uc2dd \\n\uc77c\ubc18\uc801\uc73c\ub85c\xa0Shared Lock, Exclusive Lock\uc744 \ud1b5\ud574 \uc774\ub97c \uad6c\ud604\ud55c\ub2e4.\\n\\n:::\\n\\n### Shared & Exclusive Locks\\n\\nInnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc218\ud589\ud560 \ub54c \uacf5\uc720 \uc7a0\uae08\uacfc \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n**\uacf5\uc720 \uc7a0\uae08(S, shared lock)**\\n\\n\ub370\uc774\ud130 \uc870\ud68c\ub97c \uc704\ud55c \ub77d, \uc77d\uae30 \uc7a0\uae08(read lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uae30\uac00 \uac00\ub2a5\ud558\uc9c0\ub9cc, \uc4f0\uae30\ub294 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc608) `SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;`\\n\\n**\ubc30\ud0c0\uc801 \uc7a0\uae08(X, exclusive lock)** \\n\\n\ub370\uc774\ud130 \ubcc0\uacbd\uc744 \uc704\ud55c \ub77d, \uc4f0\uae30 \uc7a0\uae08(write lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\ub77d\uc744 \uac74 \ud2b8\ub79c\uc7ad\uc158\ub9cc\uc774 \ud574\ub2f9 \ub370\uc774\ud130\uc5d0 \uc811\uadfc \uac00\ub2a5\ud558\ub2e4. \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \uc77d\uae30, \uc4f0\uae30\uac00 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc608) `SELECT * FROM table_name WHERE id = 1 FOR UPDATE;`\\n\\n### Intention Locks\\n\\nInnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uacfc \ud14c\uc774\ube14 \uc7a0\uae08\uc758 \uacf5\uc874\uc744 \uc704\ud574 \uc778\ud14d\uc158 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \\n\ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ub85c\uc6b0\uc5d0 \ub300\ud574\uc11c \ub098\uc911\uc5d0 \uc694\uccad\ub418\ub294 \uac83\uc774 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uc7a0\uae08\uc778\uc9c0 \uac00\ub9ac\ud0a4\uae30 \uc704\ud574 \uc0ac\uc6a9\ub41c\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 \uc778\ud150\uc158 \uc7a0\uae08\uc744 \uba3c\uc800 \ud68d\ub4dd\ud55c\ub2e4. \\n\uc778\ud150\uc158 \ub77d\uc740 \uae30\ubcf8\uc801\uc73c\ub85c \ucda9\ub3cc\uc744 \ubc29\uc9c0\ud558\uace0 \ub370\ub4dc\ub77d\uc744 \ubc29\uc9c0\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4. \\n\\n**\uc778\ud150\uc158 \uacf5\uc720 \uc7a0\uae08(IS, intention shared lock)**\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \uacf5\uc720 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.\\n\\n**\uc778\ud150\uc158 \ubc30\ud0c0\uc801 \uc7a0\uae08(IX, intention exclusive lock)** \\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.\\n\\n** \uc7a0\uae08\uac04\uc758 \ud638\ud658\uc131 **\\n\\n| | X | IX | S | IS |\\n| --- | --- | --- | --- | --- |\\n| X | Conflict | Conflict | Conflict | Conflict |\\n| IX | Conflict | Compatible | Conflict | Compatible |\\n| S | Conflict | Conflict | Compatible | Compatible |\\n| IS | Conflict | Compatible | Compatible | Compatible |\\n\\n### Record Locks\\n\\n\ub808\ucf54\ub4dc \uc790\uccb4\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\nInnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc740 \ub808\ucf54\ub4dc \uc790\uccb4\uac00 \uc544\ub2c8\ub77c \uc778\ub371\uc2a4\uc758 \ub808\ucf54\ub4dc\ub97c \uc7a0\uadfc\ub2e4. \\n\\n### Gap Locks\\n\\n\ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\n\ub808\ucf54\ub4dc\uc640 \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\uc5d0 \uc0c8\ub85c\uc6b4 \ub808\ucf54\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \uc81c\uc5b4\ud558\uace0, \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc758 \uc77c\ubd80\ub85c \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### Next-Key Locks\\n\\n\ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4. \\n`REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ud32c\ud140 \ub9ac\ub4dc\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uc7a0\uae08\uc774\ub2e4. \\n\\n### AUTO-INC Locks\\n\\n`AUTO_INCREMENT` \uce7c\ub9bc\uc774 \uc0ac\uc6a9\ub41c \ud14c\uc774\ube14\uc5d0 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \ub808\ucf54\ub4dc\uac00 `INSERT`\ub418\ub294 \uacbd\uc6b0, \uac01 \ub808\ucf54\ub4dc\ub294 \uc911\ubcf5\ub418\uc9c0 \uc54a\uace0 \uc800\uc7a5\ub41c \uc21c\uc11c\ub300\ub85c \uc99d\uac00\ud558\ub294 \uc77c\ub828\ubc88\ud638 \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4. \\nInnoDB \ub294 \ub0b4\ubd80\uc801\uc73c\ub85c AUTO-INC \ub77d\uc774\ub77c\uace0 \ud558\ub294 \ud14c\uc774\ube14 \uc218\uc900\uc758 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uacfc \uad00\uacc4 \uc5c6\uc774 `INSERT`\ub098 `REPLACE` \ubb38\uc7a5\uc5d0\uc11c `AUTO_INCREMENT` \uac12\uc744 \uac00\uc838\uc624\ub294 \uc21c\uac04\ub9cc \ub77d\uc774 \uac78\ub838\ub2e4\uac00 \ud574\uc81c\ub41c\ub2e4.\\n\\n### \uc7a0\uae08 \uc608\uc2dc\\n\\n```sql\\n-- \ub808\ucf54\ub4dc\ub294 id \uae30\uc900 10, 20, 30, 40, 50\uc774 \uc788\ub2e4\uace0 \uac00\uc815\\n-- Record Locks: 10\uc5d0 \ub300\ud574 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id = 10 for update;\\n\\n-- Gap Locks: 51\ubd80\ud130 PositiveInfinity\uae4c\uc9c0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id > 100 for update;\\n\\n-- Next-Key Locks: 21\ubd80\ud130 30, 31\ubd80\ud130 40\uc5d0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id BETWEEN 25 AND 35 for update;\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Optimistic and Pessimistic record locking, IBM](https://www.ibm.com/docs/en/rational-clearquest/9.0.0?topic=clearquest-optimistic-pessimistic-record-locking) \\n[MySQL Innodb Locks, cecil1018](https://cecil1018.wordpress.com/2016/06/18/mysql-innodb-locks/) \\n[MySQL 8.0 InnoDB Locks, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html) \\n[Locks Set by Different SQL Statements in InnoDB, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html)"},{"id":"mysql-lock","metadata":{"permalink":"/mysql-lock","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","source":"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","description":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","date":"2023-04-06T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 6\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Lock","permalink":"/tags/lock"},{"label":"MySQL","permalink":"/tags/my-sql"}],"readingTime":4.405,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","slug":"mysql-lock","tags":["DataBase","Lock","MySQL"]},"unlisted":false,"prevItem":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/innodb-lock"},"nextItem":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","permalink":"/transaction-and-isolation"}},"content":"## MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08\\n\\nMySQL\uc5d0\uc11c\uc758 \ub77d\uc740 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub808\ubca8\uacfc, MySQL \uc5d4\uc9c4 \ub808\ubca8\ub85c \ub098\ub20c \uc218 \uc788\ub2e4. \\nMySQL \uc5d4\uc9c4 \ub808\ubca8\uc758 \uc7a0\uae08\uc740 \ubaa8\ub4e0 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce5c\ub2e4. \\n\\n### \uae00\ub85c\ubc8c \ub77d(Global lock)\\n\\nMySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08 \uc911 \uac00\uc7a5 \ub113\uc740 \ubc94\uc704\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc7a0\uae08\uc774\ub2e4. \\n - \uc601\ud5a5\uc744 \ubbf8\uce58\ub294 \ubc94\uc704\ub294 \ud574\ub2f9 \uc11c\ubc84 \uc804\uccb4\uc774\ub2e4.\\n - \uc791\uc5c5 \ub300\uc0c1 \ud14c\uc774\ube14, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0c1\uad00 \uc5c6\uc774 \ub3d9\uc77c\ud558\uac8c \uc601\ud5a5\uc744 \ubc1b\ub294\ub2e4.\\n\\n\ud55c \uc138\uc158\uc5d0\uc11c \uae00\ub85c\ubc8c \ub77d\uc744 \ud68d\ub4dd\ud558\uba74 \ud574\uc81c \ub420 \ub54c \uae4c\uc9c0 \uc870\ud68c\ub97c \uc81c\uc678\ud55c \ub300\ubd80\ubd84\uc758 \uba85\ub839\uc774 \ub300\uae30 \uc0c1\ud0dc\uac00 \ub41c\ub2e4. \\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc874\uc7ac\ud558\ub294 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \ubc31\uc5c5\uc744 \ubc1b\uc544\uc57c\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\nInnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c\ub294 \ubc31\uc5c5 \uc2dc \uc870\uae08 \ub354 \uac00\ubcbc\uc6b4 \ubc31\uc5c5 \ub77d\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\n-- GLOBAL LOCK\\nFLUSH TABLES WITH READ LOCK;\\n-- UNLOCK\\nUNLOCK TABLES;\\n\\n-- BACKUP LOCK\\nLOCK INSTANCE FOR BACKUP;\\n-- UNLOCK\\nUNLOCK INSTANCE;\\n```\\n\\n:::note MyISAM\\n\\nMySQL 5.5 \ubc84\uc804 \uc774\uc804\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, SELECT \uc791\uc5c5 \uc18d\ub3c4\uac00 \ube60\ub974\ub2e4.\\n\\n:::\\n\\n### \ud14c\uc774\ube14 \ub77d(Table lock)\\n\\n\uac1c\ubcc4 \ud14c\uc774\ube14 \ub2e8\uc704\ub85c \uc124\uc815\ub418\ub294 \uc7a0\uae08\uc774\ub2e4. \\n\uba85\uc2dc\uc801 \ub610\ub294 \ubb35\uc2dc\uc801\uc73c\ub85c \ud2b9\uc815 \ud14c\uc774\ube14\uc758 \ub77d\uc744 \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4. \\n\ubb35\uc2dc\uc801 \ub77d\uc740 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub294 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uba74 \ubc1c\uc0dd\ud55c\ub2e4. \\nInnoDB \ud14c\uc774\ube14\uc5d0\ub294 DML \ucffc\ub9ac\ub294 \ubb34\uc2dc\ub418\uace0 DDL \uc77c \uacbd\uc6b0\uc5d0\ub9cc \ubb35\uc2dc\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud55c\ub2e4.\\n\\n```sql\\n-- TABLE LOCK\\nLOCK TABLES table_name [ READ | WRITE ]\\n\\n-- UNLOCK\\nUNLOCK TABLES;\\n```\\n\\n### \ub124\uc784\ub4dc \ub77d(Named lock)\\n\\n\uc784\uc758\uc758 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc7a0\uae08\uc73c\ub85c \uc720\uc800 \ub808\ubca8 \ub77d\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\uc5ec\ub7ec \uc2a4\ub808\ub4dc\ub098 \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc77c\ud55c \ub370\uc774\ud130\ub97c \uc218\uc815\ud558\ub824\ub294 \uacbd\uc6b0, \ub3d9\uc2dc\uc5d0 \uc218\uc815\ud558\uc9c0 \ubabb\ud558\ub3c4\ub85d \ubcf4\ud638\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\n-- aGVyYg== \ub77c\ub294 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08 \ud68d\ub4dd, \uc774\ubbf8 \uc7a0\uae08\uc744 \uc0ac\uc6a9\uc911\uc778 \uacbd\uc6b0 1\ucd08 \ub3d9\uc548\ub9cc \ub300\uae30\\nSELECT GET_LOCK(\'aGVyYg==\', 1);\\n\\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc774 \uc124\uc815\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.\\nSELECT IS_FREE_LOCK(\'aGVyYg==\');\\n\\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4.\\nSELECT RELEASE_LOCK(\'aGVyYg==\');\\n\\n-- \uc704 3\uac1c \ud568\uc218 \ubaa8\ub450 \uc815\uc0c1\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud558\uac70\ub098 \ud574\uc81c\ud55c \uacbd\uc6b0\uc5d0 1\uc744, \uc544\ub2c8\uba74 0\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n-- \ubaa8\ub4e0 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4. \ud574\uc81c\ub41c \uc7a0\uae08\uc758 \uac1c\uc218\ub97c \ubc18\ud658\ud55c\ub2e4.\\nSELECT RELEASE_ALL_LOCKS();\\n```\\n\\n### \uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac1d\uccb4\uc758 \uc774\ub984\uc774\ub098 \uad6c\uc870\ub97c \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \ud68d\ub4dd\ud558\ub294 \uc7a0\uae08\uc774\ub2e4. \\n\uba85\uc2dc\uc801\uc73c\ub85c \ud68d\ub4dd \ub610\ub294 \ud574\uc81c \ud560 \uc218 \uc5c6\uc9c0\ub9cc \ud14c\uc774\ube14\uc758 \uc774\ub984\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4. \\n\ubcf4\ud1b5 \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ud14c\uc774\ube14\uc744 \ubc14\uafd4\uc57c\ud558\ub294 \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ub41c\ub2e4.\\n\\n```sql\\n-- \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ubcc4\ub3c4\uc758 \uc784\uc2dc \ud14c\uc774\ube14\uc5d0 \uc11c\ube44\uc2a4\uc6a9 \ub7ad\ud0b9 \ub370\uc774\ud130 \uc0dd\uc131 \ud6c4 \uae30\uc874 \ud14c\uc774\ube14\uc744 \ubc31\uc5c5\ud558\ub294 \uacbd\uc6b0\\n-- \uc544\ub798 \uad6c\ubb38 \uc2e4\ud589 \uc2dc \uba54\ud0c0\ub370\uc774\ud130 \ub77d\uc744 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.\\nRENAME TABLE rank TO rank_backup, rank_new TO rank;\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[MySQL\uc758 User Level Lock\ub97c \ud65c\uc6a9\ud55c\ub2e4\uba74?, gywndi](https://gywn.net/2013/12/mysql-user-level-lock/) \\n[Locking Functions, MySQL 5.7 Reference](https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html#function_release-all-locks) \\n[Locking Functions, MySQL 8.0 Reference](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks)"},{"id":"transaction-and-isolation","metadata":{"permalink":"/transaction-and-isolation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx","source":"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx","title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","description":"\ud2b8\ub79c\uc7ad\uc158(Transaction)","date":"2023-04-05T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 5\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Transaction","permalink":"/tags/transaction"},{"label":"Isolation","permalink":"/tags/isolation"}],"readingTime":9.57,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","slug":"transaction-and-isolation","tags":["DataBase","Transaction","Isolation"]},"unlisted":false,"prevItem":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/mysql-lock"},"nextItem":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","permalink":"/test-double"}},"content":"## \ud2b8\ub79c\uc7ad\uc158(Transaction)\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub17c\ub9ac\uc801 \uae30\ub2a5\uc744 \uc218\ud589\ud558\uae30 \uc704\ud55c \uc791\uc5c5\uc758 \ub2e8\uc704\ub97c \ub9d0\ud55c\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc740 \uc791\uc5c5\uc758 \uc644\uc804\uc131\uacfc \ub370\uc774\ud130\uc758 \uc815\ud569\uc131\uc744 \ubcf4\uc7a5\ud574 \uc900\ub2e4. \\n\ub17c\ub9ac\uc801\uc778 \uc791\uc5c5 \uc14b\uc744 \uc644\ubcbd\ud558\uac8c \ucc98\ub9ac\ud558\uac70\ub098, \uc624\ub958 \uc2dc \uc791\uc5c5\uc758 \uc77c\ubd80\ub9cc \uc801\uc6a9\ub418\ub294 \ud604\uc0c1\uc744 \ub9c9\uc544\uc900\ub2e4. \\n\\n### \ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)\\n\\n\uc6d0\uc790\uc131(Atomicity): \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \uc2e4\ud589\ub41c \uc791\uc5c5\ub4e4\uc740 \ubaa8\ub450 \uc131\uacf5\ud558\uac70\ub098, \uc2e4\ud328\ud574\uc57c \ud55c\ub2e4. \\n\uc77c\uad00\uc131(Consistency): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc218\ud589\ub418\uae30 \uc804\uacfc \ud6c4\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc77c\uad00\ub41c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud574\uc57c \ud55c\ub2e4. \\n\uaca9\ub9ac\uc131(Isolation): \uac01\uac01\uc758 \ud2b8\ub79c\uc7ad\uc158\uc740 \ub3c5\ub9bd\uc801\uc774\ub77c \uc11c\ub85c\uc5d0\uac8c \uc601\ud5a5\uc744 \uc8fc\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4. \\n\uc9c0\uc18d\uc131(Durability): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c\ub2e4\uba74 \uc601\uad6c\uc801\uc73c\ub85c \uacb0\uacfc\uc5d0 \ubc18\uc601\ub418\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### \ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc740 \uaf2d \ud544\uc694\ud55c \ucd5c\uc18c\uc758 \ucf54\ub4dc\uc5d0\ub9cc \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.(\ud2b8\ub79c\uc7ad\uc158\uc758 \ubc94\uc704\ub97c \ucd5c\uc18c\ud654\ud558\ub77c) \\n\uad6c\ud604\ud574\uc57c \ud558\ub294 \uc5c5\ubb34\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158\uc744 \ubb36\uac70\ub098 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\ub294 \uacbd\uc6b0 \ubc18\ub4dc\uc2dc \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4. \\n\\n:::info \uc65c \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\uc744 \ub54c \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud560\uae4c? \ud83e\udd14\\n\\n\ub370\uc774\ud130\uc758 \uc77c\uad00\uc131\uacfc \uc548\uc804\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4. \\n\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc744 \ud2b8\ub79c\uc7ad\uc158 \ub0b4\ubd80\uc5d0 \ud3ec\ud568\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \\n- \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc911\uac04\uc5d0 \uc2e4\ud328\ud560 \uac00\ub2a5\uc131(\uc548\uc804\uc131 X)\\n- \ud1b5\uc2e0\uc73c\ub85c \uc778\ud574 \ub370\uc774\ud130\uac00 \ubcc0\uacbd\ub420 \uc218 \uc788\ub294 \ubd80\ubd84(\uc77c\uad00\uc131 X)\\n\\n:::\\n\\n## \uaca9\ub9ac \uc218\uc900(Isolation level)\\n\\n\uc5ec\ub7ec \ud2b8\ub79c\uc7ad\uc158\uc774 \ub3d9\uc2dc\uc5d0 \ucc98\ub9ac\ub420 \ub54c \ud2b9\uc815 \ud2b8\ub79c\uc7ad\uc158\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\uc758 \uc870\ud68c \ubc0f \ubcc0\uacbd\uc744 \ud5c8\uc6a9\ud560\uc9c0 \uacb0\uc815\ud558\ub294 \uac83\uc744 \ub9d0\ud55c\ub2e4. \\n\uaca9\ub9ac \uc218\uc900\uc774 \ub192\uc544\uc9c8 \uc218\ub85d \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\uc774 \ub5a8\uc5b4\uc9c0\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\uc9c0\ub9cc, `SERIALIZABLE`\uc774 \uc544\ub2c8\ub77c\uba74 \ud06c\uac8c \uc131\ub2a5\uc758 \uc800\ud558\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\n### READ UNCOMMITTED\\n\\n\uac01 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\uc758 \ubcc0\uacbd \ub0b4\uc6a9\uc774 `COMMIT`\uc774\ub098 `ROLLBACK` \uc5ec\ubd80\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcf4\uc778\ub2e4. \\n\ub354\ud2f0 \ub9ac\ub4dc \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud558\uae30 \ub54c\ubb38\uc5d0 \uc815\ud569\uc131\uc758 \ubb38\uc81c\uac00 \ub9ce\uc740 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\nMySQL \uc0ac\uc6a9\uc2dc \ucd5c\uc18c `READ COMMITTED` \uc774\uc0c1\uc758 \uaca9\ub9ac \uc218\uc900 \uc0ac\uc6a9\uc744 \uad8c\uc7a5\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: READ UNCOMMITTED\\n---\\nsequenceDiagram\\n Alice->>Database: BEGIN\\n Alice->>Database: INSERT(Alice)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: COMMIT(Alice)\\n```\\n\\n### READ COMMITTED\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 `COMMIT`\uc774 \uc644\ub8cc\ub41c \ub370\uc774\ud130\ub9cc \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc870\ud68c\ud560 \uc218 \uc788\ub2e4. \\n\uc624\ub77c\ud074 DBMS\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\n`REPEATABLE READ`\uac00 \ubcf4\uc7a5\ub418\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 `NON-REPEATABLE READ` \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: READ COMMITTED\\n---\\nsequenceDiagram\\n Alice->>Database: BEGIN\\n Alice->>Database: UPDATE(Alice to Bob)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice(Undo log)\\n Alice->>Database: COMMIT\\n```\\n\\n### REPEATABLE READ\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \uc2dc\uc791\ub418\uae30 \uc804\uc5d0 `COMMIT`\uc774 \uc644\ub8cc\ub41c \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub9cc \uc870\ud68c\ud560 \uc218 \uc788\ub2e4. \\nMySQL\uc758 InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\nMVCC\ub97c \uc774\uc6a9\ud574 \uc5b8\ub450(Undo) \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \uc774\uc804 \ub370\uc774\ud130\ub97c \uc774\uc6a9\ud574 \ub3d9\uc77c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc5ec\uc904 \uc218 \uc788\uac8c \ubcf4\uc7a5\ud55c\ub2e4. \\n\ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc7a5\ud558\ub294 \ubc29\ubc95\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n - \ubaa8\ub4e0 InnoDB \ud2b8\ub79c\uc7ad\uc158\uc740 \uc21c\ucc28\uc801\uc73c\ub85c \uc99d\uac00\ud558\ub294 \uace0\uc720\ud55c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ub97c \uac00\uc9c4\ub2e4.\\n - Undo \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \ub808\ucf54\ub4dc\uc5d0\ub294 \ubcc0\uacbd\uc744 \ubc1c\uc0dd\uc2dc\ud0a8 \ud2b8\ub79c\uc7ad\uc158\uc758 \ubc88\ud638\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\ub2e4.\\n - Undo \uc601\uc5ed\uc758 \ubc31\uc5c5\ub41c \ub370\uc774\ud130\ub294 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774 \ubd88\ud544\uc694\ud558\ub2e4\uace0 \ud310\ub2e8\ud558\ub294 \uacbd\uc6b0 \uc0ad\uc81c\ub41c\ub2e4.\\n - `REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c\ub294 MVCC\ub97c \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \uac00\uc7a5 \uc624\ub798\ub41c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ubcf4\ub2e4 \uc55e\uc120 Undo \uc601\uc5ed\uc758 \ub370\uc774\ud130\ub294 \uc0ad\uc81c\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\nInnoDB\uc5d0\uc11c\ub294 \uac2d \ub77d\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc744 \uc774\uc6a9\ud558\uc5ec \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc744 \ubc29\uc9c0\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: REPEATABLE READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN(TRX-ID: 1)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: BEGIN(TRX-ID: 2)\\n Alice->>Database: UPDATE(Alice to Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice(Undo log)\\n```\\n\\n:::note \uac2d \ub78d(Gap lock)\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d(Next-key lock)\\n\\n\uac2d \ub77d: \ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\n\ub125\uc2a4\ud2b8 \ud0a4 \ub77d: \ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4.\\n\\n:::\\n\\n:::note MVCC(Multi Version Concurrency Control)\\n\\n\ub3d9\uc2dc\uc131\uc744 \uc81c\uc5b4\ud558\ub294 \ubc29\ubc95 \uc911 \ud558\ub098\ub85c \ud558\ub098\uc758 \ub808\ucf54\ub4dc\uc5d0 \ub300\ud574 \uc5ec\ub7ec \uac1c\uc758 \ubc84\uc804\uc774 \ub3d9\uc2dc\uc5d0 \uad00\ub9ac\ub418\ub294 \uac83\uc774\ub2e4.\\n - PostgreSQL\uc740 \ub2e4\uc911 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uac83\uc73c\ub85c MVCC\ub97c \uad6c\ud604\ud55c\ub2e4.\\n - Oracle, InnoDB\ub294 `Undo log`\ub97c \uc774\uc6a9\ud574 \uc774 \uae30\ub2a5\uc744 \uad6c\ud604\ud55c\ub2e4.(\ucd5c\uc2e0 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub9cc DB\uc5d0 \uc800\uc7a5)\\n\\n\uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc77d\uad00\ub41c \uc77d\uae30\ub97c \uc81c\uacf5\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4.\\n\\n:::\\n\\n### SERIALIZABLE\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc9c4\ud589\uc2dc\ud0a4\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uace0 \ub530\ub77c\uc11c \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\ub3c4 \ub2e4\ub978 \uaca9\ub9ac \uc218\uc900\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c4\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uace0 \uc4f0\ub294 \ub808\ucf54\ub4dc\ub97c \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\ub294 \uc811\uadfc\ud560 \uc218 \uc5c6\uace0 \ub2e8\uc21c\ud55c \uc77d\uae30 \uc791\uc5c5\ub3c4 \uacf5\uc720 \uc7a0\uae08(\uc77d\uae30 \uc7a0\uae08)\uc744 \ud68d\ub4dd\ud574\uc57c\ub9cc \ud55c\ub2e4. \\nInnoDB\uc5d0\uc11c\ub294 \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc774 `REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uad73\uc774 \uc0ac\uc6a9\ud560 \ud544\uc694\ub294 \uc5c6\ub2e4. \\n\\n## \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c\\n\\n\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ub354\ud2f0 \ub9ac\ub4dc, \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c, \ud32c\ud140 \ub9ac\ub4dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n| \uaca9\ub9ac \uc218\uc900 / \ubd80\uc815\ud569 \ubb38\uc81c | \ub354\ud2f0 \ub9ac\ub4dc | \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c | \ud32c\ud140 \ub9ac\ub4dc |\\n| --- | --- | --- | --- |\\n| READ UNCOMMITTED | O | O | O |\\n| READ COMMITTED | X | O | O |\\n| REPEATABLE READ | X | X | O(InnoDB\ub294 X) |\\n| SERIALIZABLE | X | X | X |\\n\\n### \ub354\ud2f0 \ub9ac\ub4dc(Dirty read)\\n\\n\uc5b4\ub5a4 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c \uc791\uc5c5\uc774 \uc644\ub8cc\ub418\uc9c0 \uc54a\uc558\uc5b4\ub3c4 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcfc \uc218 \uc788\ub294 \ud604\uc0c1 \\n\ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \uc218\uc900\uc774 READ UNCOMMITTED\uc77c \ub54c \ubc1c\uc0dd\ud55c\ub2e4. \\n\uc608) B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uace0 \ucee4\ubc0b\uc744 \ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, A\uac00 \ud574\ub2f9 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud560 \uc218 \uc788\ub294 \uacbd\uc6b0\\n\\n### \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)\\n\\n\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc758 \uac19\uc740 \ud589\uc5d0 \ub450 \ubc88 \uc774\uc0c1 \uc870\ud68c\uac00 \ubc1c\uc0dd\ud588\ub294\ub370, \uadf8 \uac12\uc774 \ub2e4\ub978 \ud604\uc0c1 \\n\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc5ec\ub7ec \ubc88 \uc870\ud68c\ud558\ub358 \uc911 B\uac00 \ub808\ucf54\ub4dc\ub97c \ubcc0\uacbd\ud558\uc5ec A\uac00 \uc870\ud68c\ud55c \uac12\uc774 \ub2ec\ub77c\uc9c0\ub294 \uacbd\uc6b0 \\n\\n```mermaid\\n---\\ntitle: NON REPEATABLE READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: BEGIN\\n Alice->>Database: UPDATE(Alice to Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT\\n Database->>+Bob: Bob\\n```\\n\\n### \ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)\\n\\n\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ucffc\ub9ac \uc218\ud589\uc2dc, \uc218\ud589 \uacb0\uacfc\uac00 \ub2e4\ub978 \ud604\uc0c1 \\n\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud558\uace0 B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uc5ec A\uac00 \ub2e4\uc2dc \uc870\ud68c\ud560 \ub54c \uc874\uc7ac\ud558\uc9c0 \uc54a\uc740 \ub808\ucf54\ub4dc\uac00 \uc870\ud68c\ub418\ub294 \uacbd\uc6b0 \\n\\n```mermaid\\n---\\ntitle: PHANTOM READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN(TRX-ID: 1)\\n Bob->>Database: SELECT COUNT\\n Database->>+Bob: 1\\n Alice->>Database: BEGIN(TRX-ID: 2)\\n Alice->>Database: INSERT(Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT COUNT\\n Database->>+Bob: 2\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Isolation Level, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html)"},{"id":"test-double","metadata":{"permalink":"/test-double","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx","source":"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx","title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","description":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?","date":"2023-04-04T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 4\uc77c","tags":[{"label":"Test","permalink":"/tags/test"},{"label":"Mock","permalink":"/tags/mock"}],"readingTime":4.52,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","slug":"test-double","tags":["Test","Mock"]},"unlisted":false,"prevItem":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","permalink":"/transaction-and-isolation"},"nextItem":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","permalink":"/java-class-file"}},"content":"### \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?\\n\\n\ubaa8\ub4e0 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \uac00\uc9dc \uc758\uc874\uc131\uc744 \uc758\ubbf8\ud558\uace0, \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud589\ub420 \ub54c \ub2e4\ub978 \uac1d\uccb4\ub97c \ub300\uc2e0\ud55c\ub2e4. \\nGerard Meszaros\uc758 xUnit Test Patterns\ub77c\ub294 \ucc45\uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ub2e4\uc12f \uac00\uc9c0(\ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774, \ubaa9, \ud398\uc774\ud06c)\ub85c \uad6c\ubd84\ud55c\ub2e4.\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \uae30\ubcf8 \uba54\ucee4\ub2c8\uc998\uc740 \ub2e4\ud615\uc131\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774\ub2e4. \\n\uc678\ubd80 \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uacbd\uc6b0, \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uace0 \uc678\ubd80 \uc11c\ube44\uc2a4 \ub300\uc2e0 \ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\uc758 \uad6c\ud604\uccb4\ub97c \uc0dd\uc131\ud558\ub294 \uac83\uc774\ub2e4.\\n\\n**\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \ud0c0\uc785 \uacc4\uce35 \uad6c\uc870**\\n\\n```mermaid\\nflowchart LR\\n Mock --\x3e Spy --\x3e Stub --\x3e Dummy --\x3e TestDouble\\n Fake --\x3e TestDouble\\n```\\n\\n### \ub354\ubbf8(Dummy)\\n\\n\uac00\uc7a5 \ub2e8\uc21c\ud558\uace0, \uc6d0\uc2dc\uc801\uc778 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c \uc544\ubb34 \uc77c\ub3c4 \ud558\uc9c0 \uc54a\ub294 \uad6c\ud604\uccb4\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\uac00 \ud544\uc694\ud55c \uacbd\uc6b0 \uc0ac\uc6a9\ud55c\ub2e4. \\n\ub9cc\uc57d \uba54\uc11c\ub4dc\uac00 \ubb34\uc5b8\uac00 \ubc18\ud658\uc744 \ud574\uc57c\ud558\ub294 \uacbd\uc6b0 0, null\uacfc \uac19\uc740 \uac12\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\\n### \uc2a4\ud141(Stub)\\n\\n\uc2dc\ub098\ub9ac\uc624\ub9c8\ub2e4 \ub2e4\ub978 \uac12(\ubbf8\ub9ac \uc900\ube44 \ub41c \uacb0\uacfc)\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\uc774\ub97c \ud1b5\ud574 \ud2b9\uc815 \uc870\uac74\uc5d0\uc11c \uba54\uc11c\ub4dc\uac00 \uc608\uc0c1\ud55c\ub300\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n### \uc2a4\ud30c\uc774(Spy)\\n\\n\uc2a4\ud141\uacfc \uc720\uc0ac\ud558\uc9c0\ub9cc \ud638\ucd9c \uc5ec\ubd80\ub97c \uae30\ub85d\ud558\uac70\ub098 \ud638\ucd9c\ud560 \ub54c \uc804\ub2ec\ud55c \uc778\uc790\uac12\uc744 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4. \\n\uc608) \uba54\uc77c \uc804\uc1a1 \uae30\ub2a5\uc744 \uac00\uc9c4 \uac1d\uccb4\ub97c \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc73c\ub85c \uad6c\ud604\ud588\uc744 \ub54c \uba54\uc77c \uc804\uc1a1 \ud69f\uc218\ub97c \uae30\ub85d\ud55c\ub2e4. \\n\\n### \ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)\\n\\n\ubaa9\uc740 \ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774\ub97c \ud3ec\ud568\ud55c\ub2e4. \\n\ud638\ucd9c \uc2dc \uc0ac\uc804\uc5d0 \uc815\uc758\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud558\uace0, \uc608\uc0c1\uce58 \ubabb\ud55c \ud638\ucd9c\uc774 \uc788\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4. \\n\ub610\ud55c \ud638\ucd9c\uc5d0 \ub300\ud55c \uac80\uc99d\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n### \uac00\uc9dc(Fake)\\n\\nDOC\uc640 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc9c0\ub9cc, \ub354\uc6b1 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ub41c \uac83\uc774\ub2e4. \\n\uc608) \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \ub3d9\uc791\ud558\ub294 \uac00\uc9dc \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note DOC(depended-on component)\\n\\n\uc758\uc874 \uad6c\uc131 \uc694\uc18c, DOC\ub97c \ud14c\uc2a4\ud2b8 \ub354\ube14\ub85c \ub300\uccb4\ud560 \uc218 \uc788\ub2e4. \\n\ud14c\uc2a4\ud2b8 \ub354\ube14\uc740 DOC\uc640 \ub3d9\uc77c\ud55c API\ub97c \uc81c\uacf5\ud574\uc57c \ud55c\ub2e4. \\n\\n:::\\n\\n### \uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84\\n\\n\ub2e8\uc704 \ud14c\uc2a4\ud2b8 p.149 \uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ud06c\uac8c \ubaa9\uacfc \uc2a4\ud141\uc73c\ub85c \uad6c\ubd84\ud55c\ub2e4. \\n\ubaa9\uc740 SUT\uc640 \uad00\ub828\ub41c \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ubc18\uba74, \uc2a4\ud141\uc740 \ub2e8\uc21c \ubaa8\ubc29\ub9cc \ud55c\ub2e4. \\n\\n| TestDouble | Mock | Stub |\\n| --- | --- | --- |\\n| \ud3ec\ud568 \uc720\ud615 | \ubaa9, \uc2a4\ud30c\uc774 | \uc2a4\ud141, \ub354\ubbf8, \ud398\uc774\ud06c |\\n| \uc6a9\ub3c4 | \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ub370 \uc0ac\uc6a9 | \ub0b4\ubd80\ub85c \ub4e4\uc5b4\uc624\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\ub294 \ub370 \uc0ac\uc6a9 |\\n| \uc124\uba85 | SUT\uac00 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9 | SUT\uac00 \uc785\ub825 \ub370\uc774\ud130\ub97c \uc5bb\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9\\n| \uc608\uc2dc | \uc774\uba54\uc77c \ubc1c\uc1a1 | \ub370\uc774\ud130 \uac80\uc0c9 |\\n\\n:::note SUT(system under test)\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc0c1 \uc2dc\uc2a4\ud15c \\n\ud14c\uc2a4\ud2b8\ub97c \ud558\ub824\ub294 \ub300\uc0c1\\n\\n:::\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30 - 3\uc7a5 \uace0\uae09 \ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 \\n\ub2e8\uc704 \ud14c\uc2a4\ud2b8 - 5\uc7a5 \ubaa9\uacfc \ud14c\uc2a4\ud2b8 \ucde8\uc57d\uc131, \ube14\ub77c\ub514\ubbf8\ub974 \ucf54\ub9ac\ucf54\ud504 \\n\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uc2dc\uc791\ud558\uae30 - 7\uc7a5 \ub300\uc5ed, \ucd5c\ubc94\uade0 \\n[\ud14c\uc2a4\ud2b8 \ub354\ube14, Martin Fowler](https://www.martinfowler.com/bliki/TestDouble.html) \\n[\ud14c\uc2a4\ud2b8 \uad00\ub828 \uc6a9\uc5b4 \uc815\ub9ac, Johngrib](https://johngrib.github.io/wiki/test-terms/) \\n[Test Double, Gerard Meszaros](http://xunitpatterns.com/Test%20Double.html)"},{"id":"java-class-file","metadata":{"permalink":"/java-class-file","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx","source":"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx","title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","description":"\ud074\ub798\uc2a4 \ud30c\uc77c","date":"2023-04-03T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 3\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Class","permalink":"/tags/class"}],"readingTime":5.63,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","slug":"java-class-file","tags":["Java","Class"]},"unlisted":false,"prevItem":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","permalink":"/test-double"},"nextItem":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","permalink":"/custom-jdbc-template"}},"content":"### \ud074\ub798\uc2a4 \ud30c\uc77c\\n\\n\uc790\ubc14 \uc18c\uc2a4\ucf54\ub4dc\uac00 \uc2e4\ud589\uc774 \ub418\ub824\uba74 \uc790\ubc14 \ucef4\ud30c\uc77c\ub7ec(javac)\ub97c \ud1b5\ud574 \uc18c\uc2a4\ucf54\ub4dc\ub97c \ud074\ub798\uc2a4\ud30c\uc77c\ub85c \ubcc0\ud658\ud574\uc57c \ud55c\ub2e4. \\n\ucef4\ud30c\uc77c\ub41c \ud074\ub798\uc2a4\ud30c\uc77c\uc740 \uc5b4\ub5a4 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744\uae4c?\\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd\\n\\n8\ube44\ud2b8 \ubc14\uc774\ud2b8\uc758 \uc2a4\ud2b8\ub9bc\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4. \\n16\ube44\ud2b8 \ubc0f 32\ube44\ud2b8\uc758 \ub370\uc774\ud130\ub294 \uac01\uac01 2\uac1c, 4\uac1c\uc758 \uc5f0\uc18d\ub41c 8\ube44\ud2b8\ub97c \uc77d\uc5b4\uc11c \uad6c\uc131\ub41c\ub2e4. \\n\uba40\ud2f0\ubc14\uc774\ud2b8\uc758 \uacbd\uc6b0 \ud56d\uc0c1 big endian \uc21c\uc11c\ub85c \uc800\uc7a5\ub41c\ub2e4. \\n\\nu1 \u2192 unsigned 1byte \\nu2 \u2192 unsigned 2byte \\nu4 \u2192 unsigned 4byte \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870\\n\\n```\\nClassFile {\\n u4 magic;\\n u2 minor_version;\\n u2 major_version;\\n u2 constant_pool_count;\\n cp_info constant_pool[constant_pool_count-1];\\n u2 access_flags;\\n u2 this_class;\\n u2 super_class;\\n u2 interfaces_count;\\n u2 interfaces[interfaces_count];\\n u2 fields_count;\\n field_info fields[fields_count];\\n u2 methods_count;\\n method_info methods[methods_count];\\n u2 attributes_count;\\n attribute_info attributes[attributes_count];\\n}\\n```\\n\\n### \ub9e4\uc9c1\ub118\ubc84\\n\\n\ubaa8\ub4e0 \ud074\ub798\uc2a4 \ud30c\uc77c\uc740 0xCAFEBABE\ub77c\ub294 \ub9e4\uc9c1\ub118\ubc84\ub85c \uc2dc\uc791\ud55c\ub2e4. \\n\ubcf4\ud1b5 \ub9e4\uc9c1\ub118\ubc84\ub294 \ud30c\uc77c \uc885\ub958\ub97c \uc2dd\ubcc4\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804\\n\\n\ud074\ub798\uc2a4 \ud30c\uc77c \ubc84\uc804 \uac12\uc740 \ud074\ub798\uc2a4\ub85c\ub354\uc758 \ud638\ud658\uc131 \ubcf4\uc7a5\uc744 \uc704\ud574 \uaf2d \ud544\uc694\ud55c \uac12\uc774\ub2e4. \\n- Java 17 \ubc84\uc804\uc73c\ub85c \ube4c\ub4dc\ud55c\ub2e4\uba74 class version 61 ex) 00 00 00 3D\\n\\n\ud638\ud658\ub418\uc9c0 \uc54a\ub294 \ubc84\uc804\uc758 \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \ub85c\ub529\ud558\ub824\uace0 \ud558\ub294 \uacbd\uc6b0 \ub7f0\ud0c0\uc784\uc5d0 `UnsupportedClassVersionError` \uc608\uc678\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n**class\xa0file format major versions**\\n\\n| Java SE | Released | Major | Supported majors |\\n| --- | --- | --- | --- |\\n| 8 | March 2014 | 52 | 45 .. 52 |\\n| 9 | September 2017 | 53 | 45 .. 53 |\\n| 10 | March 2018 | 54 | 45 .. 54 |\\n| 11 | September 2018 | 55 | 45 .. 55 |\\n| 12 | March 2019 | 56 | 45 .. 56 |\\n| 13 | September 2019 | 57 | 45 .. 57 |\\n| 14 | March 2020 | 58 | 45 .. 58 |\\n| 15 | September 2020 | 59 | 45 .. 59 |\\n| 16 | March 2021 | 60 | 45 .. 60 |\\n| 17 | September 2021 | 61 | 45 .. 61 |\\n\\n### \uc0c1\uc218 \ud480\\n\\n2\ubc14\uc774\ud2b8\uc758 \uc0c1\uc218\uc758 \uac1c\uc218\uac12\uc774 \uba3c\uc800\uc624\uace0 \uadf8 \ub4a4\ub85c \ucf54\ub4dc\uc5d0 \ub4f1\uc7a5\ud558\ub294 \uc0c1\uc218\uac12\uc774 \ubaa8\uc5ec\uc788\ub2e4. \\n\ud074\ub798\uc2a4\uba85, \uc0c1\uc218\uba85, \uc0c1\uc218 \uac12, \ud544\ub4dc\uba85, \uba54\uc11c\ub4dc\uba85\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4. \\nJVM\uc740 \ucf54\ub4dc \uc2e4\ud589 \uc2dc \ub7f0\ud0c0\uc784\uc5d0 \ubc30\uce58\ub41c \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c, \ud574\ub2f9 \uc0c1\uc218 \ud480 \ud14c\uc774\ube14\uc744 \ucc3e\uc544\ubcf4\uace0 \ud544\uc694\ud55c \uac12\uc744 \ucc38\uc870\ud55c\ub2e4.\\n\\n### \uc561\uc138\uc2a4 \ud50c\ub798\uadf8\\n\\n\ud074\ub798\uc2a4, \uc778\ud130\ud398\uc774\uc2a4\uc640 \uac19\uc740 \ud30c\uc77c\uc758 \uc18d\uc131\uc744 \ud45c\uc2dc\ud55c\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 public interface\ub85c \uc815\uc758\ub41c \uc778\ud130\ud398\uc774\uc2a4\uc758 \ud50c\ub798\uadf8\ub294 0x0601\uc774\ub2e4. \\n- \uacc4\uc0b0\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. `ACC_PUBLIC` xor `ACC_INTERFACE` xor `ACC_ABSTRACT`\\n\\n\uacf5\uc2dd\ubb38\uc11c\uc5d0 \ub4e4\uc5b4\uac00\uba74 \uac01 \ud50c\ub798\uadf8\uc5d0 \ub300\ud55c \uc124\uba85 + \ud50c\ub798\uadf8 \uc124\uc815\uc2dc \ub3d9\uc2dc\uc5d0 \uc124\uc815\ub418\uba74 \uc548\ub418\ub294 \ud50c\ub798\uadf8\uc640 \uac19\uc740 \uc124\uba85\uc774 \uc790\uc138\ud558\uac8c \ub098\uc640\uc788\ub2e4.\\n\\n**Class access and property modifiers**\\n\\n| Flag Name | Value | Interpretation |\\n| --- | --- | --- |\\n| ACC_PUBLIC | 0x0001 | Declared\xa0public; may be accessed from outside its package. |\\n| ACC_FINAL | 0x0010 | Declared\xa0final; no subclasses allowed. |\\n| ACC_SUPER | 0x0020 | Treat superclass methods specially when invoked by the\xa0invokespecial\xa0instruction. |\\n| ACC_INTERFACE | 0x0200 | Is an interface, not a class. |\\n| ACC_ABSTRACT | 0x0400 | Declared\xa0abstract; must not be instantiated. |\\n| ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |\\n| ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |\\n| ACC_ENUM | 0x4000 | Declared as an\xa0enum\xa0type. |\\n| ACC_MODULE | 0x8000 | Is a module, not a class or interface. |\\n\\n### this_class\\n\\n\ud074\ub798\uc2a4\uba85\uacfc \uac19\uc740 \uc774\ub984\uc744 \ud45c\ud604\ud558\ub294 \uac12\uc73c\ub85c, \uc0c1\uc218 \ud480\uc5d0\uc11c \ud074\ub798\uc2a4\uba85\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4. \\n\ud574\ub2f9 \uc778\ub371\uc2a4\uc758 \ud56d\ubaa9\uc740 `CONSTANT_Class_infoclass` \ud615\uc2dd\uc758 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### super_class\\n\\n\uc0c1\uc218 \ud480\uc5d0\uc11c \uc288\ud37c \ud074\ub798\uc2a4\uc758 \uc774\ub984\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4. \\n\uc544\ubb34\uac83\ub3c4 \uc0c1\uc18d\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\uc758 \uacbd\uc6b0 `java.lang.Object`\uc758 \uc778\ub371\uc2a4 \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4.\\n\\n### interface, field, method\\n\\n\uac01\uac01\uc758 \uac1c\uc218\uc640, \uc815\ubcf4\uc5d0 \ub300\ud55c \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4. \\ninterface, field, method\ub97c \ud45c\uc2dc\ud558\ub294 \ubc29\ubc95\uc774 \uac01\uac01 \ub2e4\ub974\uace0, \uc811\uadfc\uc790\uc5d0 \ub300\ud55c \ud50c\ub798\uadf8\ub3c4 \uac01\uac01 \ub2e4\ub974\ub2e4.\\n\\n### attributes\\n\\n\ud574\ub2f9 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucd94\uac00 \uc815\ubcf4\uc758 \ubaa8\uc74c\uc774\ub2e4. \uc608) \uc18c\uc2a4\ud30c\uc77c\uba85 \\n\uc815\ud574\uc9c4 \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \uad6c\uc870\ub97c \ud655\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4. \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234\\n\\nIntelliJ plugin - BinEd \\nIntelliJ plugin - jclasslib Bytecode Viewer\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n2\uc7a5 JVM \uc774\uc57c\uae30, \uc790\ubc14 \ucd5c\uc801\ud654 \\n[Class file in Java, File Format](https://docs.fileformat.com/ko/programming/class/) \\n[java se11 Class \ud30c\uc77c \ud615\uc2dd, Oracle](https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html) \\n[java se17 Class \ud30c\uc77c \ud615\uc2dd, Oracle](https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html)"},{"id":"custom-jdbc-template","metadata":{"permalink":"/custom-jdbc-template","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx","source":"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx","title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","description":"\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.","date":"2023-04-02T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 2\uc77c","tags":[{"label":"JDBC","permalink":"/tags/jdbc"},{"label":"Java","permalink":"/tags/java"}],"readingTime":9.025,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","slug":"custom-jdbc-template","tags":["JDBC","Java"]},"unlisted":false,"prevItem":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","permalink":"/java-class-file"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","permalink":"/woowacourse-level1-retrospective"}},"content":"import Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\uc774 \ub54c JDBC\ub97c \uc0ac\uc6a9\ud560 \ub54c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ucee4\ub125\uc158\uc744 \uc5bb\uace0, try-with-resource\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc774 \ubc18\ubcf5\ub418\uc5c8\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc774\uc6a9\ud558\uc5ec \ub098\ub9cc\uc758 JdbcTemplate\uc744 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4. \\n\\n### \uae30\uc874 \ucf54\ub4dc\\n\\n\\n\\n\\n```java\\npublic class User {\\n private final int id;\\n private final String name;\\n\\n public User(final int id, final String name) {\\n this.id = id;\\n this.name = name;\\n }\\n\\n public int getId() {\\n return id;\\n }\\n\\n public String getName() {\\n return name;\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic class UserDao {\\n private final ConnectionPool connectionPool;\\n\\n public UserDao(final ConnectionPool connectionPool) {\\n this.connectionPool = connectionPool;\\n }\\n\\n public void insert(final String name) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setString(1, name);\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public void delete(final int userId) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"DELETE FROM user WHERE id = ?\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setInt(1, userId);\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public User findById(final int userId) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setInt(1, userId);\\n final ResultSet resultSet = preparedStatement.executeQuery();\\n if (resultSet.next()) {\\n return new User(\\n resultSet.getInt(\\"id\\"),\\n resultSet.getString(\\"name\\")\\n );\\n }\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n return null;\\n }\\n\\n public List findAll() {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"SELECT * FROM user\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n final ResultSet resultSet = preparedStatement.executeQuery();\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(new User(\\n resultSet.getInt(\\"id\\"),\\n resultSet.getString(\\"name\\")\\n ));\\n }\\n return result;\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic class ConnectionPool {\\n private static final String SERVER = \\"localhost:13306\\";\\n private static final String DATABASE = \\"chess\\";\\n private static final String OPTION = \\"?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true\\";\\n private static final String URL = \\"jdbc:mysql://\\" + SERVER + \\"/\\" + DATABASE + OPTION;\\n private static final String USERNAME = \\"root\\";\\n private static final String PASSWORD = \\"root\\";\\n\\n private final AtomicInteger index = new AtomicInteger();\\n private final List connections;\\n\\n public ConnectionPool(final int connectionCount) {\\n connections = generateConnections(connectionCount);\\n }\\n\\n private List generateConnections(final int connectionCount) {\\n return Stream.generate(this::generateConnection)\\n .limit(connectionCount)\\n .collect(toList());\\n }\\n\\n private Connection generateConnection() {\\n try {\\n return DriverManager.getConnection(URL, USERNAME, PASSWORD);\\n } catch (SQLException e) {\\n throw new IllegalStateException(\\"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\");\\n }\\n }\\n\\n public Connection getConnection() {\\n int currentIndex = index.getAndIncrement();\\n return connections.get(currentIndex % connections.size());\\n }\\n}\\n```\\n\\n\\n\\n\\n### SELECT, DELETE \uc911\ubcf5 \uc81c\uac70\\n\\n\ubcc0\ud558\uc9c0 \uc54a\ub294 \ubd80\ubd84: try-with-resource, preparedStatement\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84, executeUpdate\ub85c \uc2e4\ud589 \ub4f1\ub4f1 \\n\ubcc0\ud558\ub294 \ubd80\ubd84: SQL Query, \ub9e4\uac1c\ubcc0\uc218 \\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\ub294 \ubd80\ubd84\uc744 \ubd84\ub9ac\ud558\uace0 \uac00\ubcc0\uc778\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 SELECT\uc640 DELETE\uc758 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\\n```java\\npublic void insert(final String name) {\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n executeUpdate(query, name);\\n}\\n\\npublic void delete(final int userId) {\\n final String query = \\"DELETE FROM user WHERE user_id = ?\\";\\n executeUpdate(query, userId);\\n}\\n\\nprivate void executeUpdate(final String query, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758\\n\\n\uc870\ud68c\ub294 INSERT, DELETE\uc640 \ub2ec\ub9ac \uac12\uc744 \ubc18\ud658\ubc1b\uc544\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0 \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. \\n\uc774 \ub54c \ucf5c\ubc31\uc774\ub77c\ub294 \uac83\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \ucf5c\ubc31(Callback)\\n\\n\ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \ucf5c\ubc31\uc740 \ub2e4\ub978 \ucf54\ub4dc\uc758 \uc778\uc218\ub85c \ub118\uaca8\uc8fc\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ucf54\ub4dc\ub97c \ub73b\ud55c\ub2e4. \\n\uc790\ubc14\uc5d0\uc11c\ub294 \ub78c\ub2e4\ub098 \uc775\uba85 \ud074\ub798\uc2a4\ub97c \ub118\uaca8\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n```mermaid\\nflowchart LR\\n \ud074\ub77c\uc774\uc5b8\ud2b8 -- \ucf5c\ubc31\uc804\ub2ec --\x3e \uba54\uc11c\ub4dc\\n \uba54\uc11c\ub4dc -- \ub0b4\ubd80\ud638\ucd9c --\x3e \uc804\ub2ec\ubc1b\uc740\ucf5c\ubc31\\n```\\n\\n:::\\n\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uc870\ud68c\ud558\uace0, \ud574\ub2f9 \uac12\uc744 \uac1d\uccb4\ub85c \ub9e4\ud551\ud558\uc5ec \uac12\uc744 \ubc18\ud658\ud574\uc57c \ud55c\ub2e4. \\nexecuteQuery\ub85c \uc870\ud68c\ud55c \uac12\uc740 ResultSet \uc548\uc5d0 \ub4e4\uc5b4\uac00\uc788\ub2e4. \\n\uc774\ub97c \uc6d0\ud558\ub294 \ud0c0\uc785\uc758 \uac12\uc73c\ub85c \ubcc0\ud658\ud574\uc57c\ud558\ub2c8 \uc77c\ub2e8 \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4. \\n\\n```java\\n@FunctionalInterface\\npublic interface RowMapper {\\n User mapRow(final ResultSet resultSet) throws SQLException;\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c\\n\\n\uc704\uc5d0\uc11c \uc815\uc758\ud55c RowMapper\ub97c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c? \\n\uc544\ub798\uc640 \uac19\uc774 SQL \ucffc\ub9ac, RowMapper, \ud30c\ub77c\ubbf8\ud130\ub97c \ubd84\ub9ac\ud55c \uba54\uc11c\ub4dc\uc5d0 \ub118\uaca8\uc8fc\uace0 \ucffc\ub9ac \uc2e4\ud589 \ud6c4 \ub9e4\ud551\ud55c \uac12\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \\n\\n```java\\npublic User findById(final int userId) {\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n return queryForSingleResult(query, resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n }, userId);\\n}\\n\\nprivate User queryForSingleResult(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n if (resultSet.next()) {\\n return rowMapper.mapRow(resultSet);\\n }\\n return null;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n\\nprivate ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c\\n\\n\ub2e8\uac74 \uc870\ud68c\uc640 \uc720\uc0ac\ud558\ub2e4.\\n\\n```java\\npublic List findAll() {\\n final String query = \\"SELECT * FROM user\\";\\n return query(query, resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n });\\n}\\n\\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(rowMapper.mapRow(resultSet));\\n }\\n return result;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n\\nprivate ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n}\\n```\\n\\n### \uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30\\n\\n\uc704\uc758 \ucf54\ub4dc\ub294 User\ub97c \uc870\ud68c\ud560 \ub54c\ub9cc \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\n\uc544\ub798\uc640 \uac19\uc774 \uc81c\ub124\ub9ad\uc744 \uc801\uc6a9\ud558\uc5ec \ub2e4\ub978 Dao\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n@FunctionalInterface\\npublic interface RowMapper {\\n T mapRow(final ResultSet resultSet) throws SQLException;\\n}\\n\\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {...}\\nprivate T queryForSingleResult(final String query, final RowMapper rowMapper, final Object... parameters) {...}\\n```\\n\\n### \uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30\\n\\n\uba54\uc11c\ub4dc\ub85c \ubd84\ub9ac\ud55c \ubd80\ubd84\uc744 JdbcTemplate\uc774\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc62e\uae34\ub2e4. \\n\ub610\ud55c null\uc744 \ubc18\ud658\ud558\uae30 \ubcf4\ub2e8 Optional\ub85c \uac10\uc2f8\uc11c \ubc18\ud658\ud558\ub3c4\ub85d \ubcc0\uacbd\ud55c\ub2e4. \\n\ucd5c\uc885\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uac00 \uc644\uc131\ub41c\ub2e4.\\n\\n\\n\\n\\n```java\\npublic class UserDao {\\n private final RowMapper rowMapper = resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n };\\n private final JdbcTemplate jdbcTemplate;\\n\\n public UserDao(final JdbcTemplate jdbcTemplate) {\\n this.jdbcTemplate = jdbcTemplate;\\n }\\n\\n public void insert(final String name) {\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n jdbcTemplate.executeUpdate(query, name);\\n }\\n\\n public void delete(final int userId) {\\n final String query = \\"DELETE FROM user WHERE user_id = ?\\";\\n jdbcTemplate.executeUpdate(query, userId);\\n }\\n\\n public Optional findById(final int userId) {\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);\\n }\\n\\n public List findAll() {\\n final String query = \\"SELECT * FROM user\\";\\n return jdbcTemplate.query(query, rowMapper);\\n }\\n}\\n```\\n\\n\\n\\n\\n```java\\npublic class JdbcTemplate {\\n private final ConnectionPool connectionPool;\\n\\n public JdbcTemplate(final ConnectionPool connectionPool) {\\n this.connectionPool = connectionPool;\\n }\\n\\n public void executeUpdate(final String query, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public Optional queryForSingleResult(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n ) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n if (resultSet.next()) {\\n return Optional.of(rowMapper.mapRow(resultSet));\\n }\\n return Optional.empty();\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n private ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters\\n ) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n }\\n\\n public List query(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n ) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(rowMapper.mapRow(resultSet));\\n }\\n return result;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n}\\n```\\n\\n\\n"},{"id":"woowacourse-level1-retrospective","metadata":{"permalink":"/woowacourse-level1-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","description":"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.","date":"2023-04-01T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 1\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.48,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","slug":"woowacourse-level1-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","permalink":"/custom-jdbc-template"},"nextItem":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","permalink":"/chess-retrospective"}},"content":"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4. \\n\uc6b0\ud14c\ucf54\ub97c \uc2dc\uc791\ud558\uae30 \uc804 \ub0b4\uac00 \uc815\ud574\ub450\uc5c8\ub358 \ubaa9\ud45c \uc774\uc0c1\uc73c\ub85c \ub2ec\uc131\ud588\uae30 \ub54c\ubb38\uc5d0 \ub9e4\uc6b0 \ub9cc\uc871\uc2a4\ub7fd\ub2e4. \\n\ud63c\uc790 \ub3c5\ud559\uc744 \ud560 \ub550 \uc774 \ubc29\ud5a5\uc73c\ub85c \uacf5\ubd80\ud558\ub294 \uac8c \ub9de\ub294\uc9c0 \uacc4\uc18d \ubc18\ucd94\ud558\ub2e4 \uacb0\uad6d \ubb34\uae30\ub825\ud568\uc5d0 \ube60\uc838\ub4e4\uc5c8\ub2e4. \\n\ud558\uc9c0\ub9cc \uc774\uc81c\ub294 \uac19\uc774 \uacf5\ubd80\ud560 \uc0ac\ub78c\ub3c4 \uc788\uace0, \uc774\uc57c\uae30\ud560 \uc0ac\ub78c\ub3c4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc990\uae30\ub294 \uc77c\ub9cc \ub0a8\uc740 \uac83 \uac19\ub2e4. \\n\\n### Keep\\n\\n**\ub098\ub9cc\uc758 \ub8e8\ud2f4 \ub9cc\ub4e4\uae30** \\n\\n\uc2a4\uc2a4\ub85c\uac00 \uc678\ubd80\uc758 \uc601\ud5a5\uc744 \ub9ce\uc774 \ubc1b\ub294\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ucd5c\ub300\ud55c \uafb8\uc900\ud788 \ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n\ub9e4\uc77c 8\uc2dc\uc5d0 \ub3c4\ucc29\ud558\uc5ec \uc544\uce68\uc5d0 \ud574\uc57c \ud560 \uc77c\uc744 \uc815\ub9ac\ud558\uac70\ub098, \uc6b0\uc120\uc21c\uc704\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud558\uace0 \\n\uc18c\ud654\ub2a5\ub825\uc774 \ubd80\uc871\ud558\uae30 \ub54c\ubb38\uc5d0 \uc810\uc2ec\uc740 \ub3c4\uc2dc\ub77d(\uadf8\ub798\ubd24\uc790 \uacc4\ub7802\uac1c)\uc744 \uc900\ube44\ud558\uace0 \\n\ud56d\uc0c1 \ub611\uac19\uc740 \ucee8\ub514\uc158\uc744 \uc720\uc9c0\ud558\uae30 \uc704\ud574 \ud56d\uc0c1 6\uc2dc\uc5d0 \uc9d1\uc5d0 \uac04\ub2e4. \\n\uc774\uc81c \ubc14\ube60\uc9c8 \ud14c\ub2c8 \uc77c\ucc0d \uc9d1\uc5d0 \uac00\ub294 \uc77c\uc740 \uc5b4\uca54 \uc218 \uc5c6\uc774 \uc904\uc5b4\ub4e4\uaca0\uc9c0\ub9cc\ud83d\ude22 \\n\\n\uc120\ud0dd\ub3c4 \ube44\uc6a9\uc774\ub2e4. \uc55e\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\uc774 \ud544\uc694 \uc5c6\ub294 \ubd80\ubd84\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\ub4e4\uc5b4\uc57c\uaca0\ub2e4. \\n\\n**\ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uae30** \\n\\n10\uba85 \uc815\ub3c4\uc758 \ud06c\ub8e8\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b0\uace0 \uce5c\ud558\uac8c \uc9c0\ub0b8\ub2e4\uba74 \uc131\uacf5\uc801\uc774\ub77c\uace0 \uc0dd\uac01\ud588\uc5c8\ub2e4. \\n\ud558\ub2e4 \ubcf4\ub2c8 \ub354 \ub9ce\uc740 \ud06c\ub8e8\ub4e4\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b4 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c\ub3c4 \ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uace0 \uc544\ubb34 \ub54c\ub098 \ub9d0\uc744 \uac78 \uc218 \uc788\ub294 \ud06c\ub8e8\uac00 \ub298\uc5b4\ub098\uae38 :) \\n\\n**\uae00\uc4f0\uae30** \\n\\n\uae00\uc744 \uc798 \uc4f0\ub294 \ud3b8\uc740 \uc544\ub2c8\uc9c0\ub9cc \uafb8\uc900\ud788 \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ub9e4 \ubbf8\uc158\ub9c8\ub2e4 \ud68c\uace0\ub97c \uc791\uc131\ud558\ub2c8 \uc0dd\uac01\ub3c4 \uc815\ub9ac\ub418\uace0 \uac1c\uc120\uc810\ub3c4 \ucc3e\uc744 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\ub2e4. \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc5d0\ub294 \ub808\ubca8\ub9c8\ub2e4 \uae00\uc4f0\uae30\ub97c \uc9c4\ud589\ud558\ub294\ub370, \uc6b4\uc774 \uc88b\uac8c \uae00\uc4f0\uae30 \uc0c1\uc744 \ubc1b\uc558\ub2e4. \\n\uc0ac\uc2e4 \uac89\uc73c\ub85c \ub4dc\ub7ec\ub0b4\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uaf2d \ubc1b\uc544\ubcf4\uace0 \uc2f6\uc5c8\ub2e4. \\n\uae00\uc4f0\uae30 \uc870\uc6d0, \ud22c\ud45c\ud574 \uc900 \ud06c\ub8e8\ub4e4\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4. \\n\\n**\ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514** \\n\\n\ub204\ub204, \uc8fc\ub178, \ub2e4\uc990, \ub9d0\ub791, \ubc15\uc2a4\ud130, \uc624\uc789, \uae43\uc9f1\uc640 \ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\uacfc\uc5f0 \ub3c4\uc6c0\uc774 \ub420\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud558\uba74\uc11c \uc131\uc7a5\uc744 \ub9ce\uc774 \ud55c \uac83 \uac19\ub2e4. \\n\ud22c\uc790\ud55c \uc2dc\uac04 \ub300\ube44 \uac00\uc131\ube44\uac00 \uc88b\uc740 \ud65c\ub3d9\uc774\uc5c8\ub2e4. \\n\ub204\ub204\uac00 \uc2a4\ud130\ub514\uc7a5\uc778\ub370 \uacfc\uc5f0 \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00\ub824\ub098? \\n\\n**\ub808\ubca8 \uc778\ud130\ubdf0**\\n\\n\uc778\ud130\ubdf0\ud560 \ub54c \ub9ce\uc774 \ub5a8\uc9c0 \uc54a\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ub0a8\ub4e4 \uc55e\uc5d0\uc11c \uc774\uc57c\uae30\ub97c \ud558\uac70\ub098, \uba74\uc811\uc744 \ubcf4\uba74 \ud56d\uc0c1 \uc5c4\uccad \ub5a8\uc5b4\uc11c \uac71\uc815\ud588\ub294\ub370 \\n\uae30\uc220\uc801\uc778 \uc9c8\ubb38\uc744 \ubc1b\uc558\uc744 \ub54c \ub5a8\uc9c0 \uc54a\uace0 \uc798 \ub300\ub2f5\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \ub2e4\ub978 \ud06c\ub8e8\uac00 \uc9c8\ubb38\ud588\uc744 \ub54c, \ucd5c\ub300\ud55c \uc774\ud574\ud558\uae30 \uc27d\uac8c \uc124\uba85\ud558\ub824\uace0 \ud588\ub358 \uacbd\ud5d8\uc774 \ub3c4\uc6c0\uc774 \ub41c \uac83 \uac19\ub2e4. \\n\uc774\ud6c4 \ub808\ubca8 \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\ub2e4. \\n- \ub300\ub2f5\ud558\uba74\uc11c \uc9c8\ubb38\uc744 \uacc4\uc18d \uc0dd\uac01\ud558\uba70 \uc78a\uc5b4\ubc84\ub9ac\uc9c0 \ub9d0\uae30 \\n- \ub450\uad04\uc2dd \ud45c\ud604\\n- \uc124\uba85\ud558\ub2e4\uac00 \uc798\ubabb \uc124\uba85\ud55c \uac83 \uac19\uc73c\uba74 \ub2e4 \ub04a\uace0 \ub2e4\uc2dc \uc774\uc57c\uae30\ud574\ub3c4 \ub420\uc9c0 \ubb3c\uc5b4\ubcf4\uae30 \\n- \uc124\uba85\ud560 \uc218 \uc788\uc744\ub9cc\ud07c \uc2dc\uac04 \ucda9\ubd84\ud788 \uac00\uc9c0\uae30\\n- \uc778\ud130\ubdf0\uc5b4\uc758 \uc9c8\ubb38 \uc758\ub3c4\ub97c \uba85\ud655\ud788 \uc774\ud574\ud558\uc9c0 \ubabb\ud588\ub2e4\uba74 \uc758\ub3c4 \ub2e4\uc2dc \ubb3c\uc5b4\ubcf4\uae30\\n- \ub05d\ub9fa\ub294 \ubd80\ubd84 \uc5f0\uc2b5\ud558\uae30(\uc790\uc2e0\uac10 \uc788\uac8c)\\n- \uae30\uc220\uc801\uc778 \uc9d1\ucc29\uac00\uc9c0\uae30\\n- \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud788 \uc900\ube44\ud588\uc73c\uba74 \ud611\uc5c5 \uad00\ub828 \uc9c8\ubb38\ub3c4 \uc900\ube44\ud558\uae30\\n\\n### Problem\\n\\n**\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d** \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ud65c\ub3d9 \uc911 \ud558\ub098\ub77c\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ud398\uc5b4\ub294 \ub9e4\ubc88 \ubc14\ub00c\uace0, \ubbf8\uc158\uc758 \ubcf5\uc7a1\ub3c4\ub3c4 \uc99d\uac00\ud558\uae30 \ub54c\ubb38\uc778 \uac83 \uac19\ub2e4. \\n\uc18c\ud1b5 \ub2a5\ub825, \uc2dc\uac04\uad00\ub9ac\uac00 \ubd80\uc871\ud588\uace0, \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\uc558\ub2e4. \\n\ud558\uc9c0\ub9cc \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uace0, \ud68c\uace0\ub97c \ud558\ub2e4 \ubcf4\ub2c8 \ub098\ub9cc\uc758 \ub178\ud558\uc6b0\uac00 \uc313\uc774\ub294 \ub290\ub08c\uc774\ub2e4. \\n\ub808\ubca8 2\uc5d0\uc11c\ub294 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc120\ud558\uc5ec \ud568\uaed8\ud558\uace0 \uc2f6\uc740 \ud398\uc5b4\uac00 \ub418\uace0 \uc2f6\ub2e4. \\n\\n**\uc9d1\uc911\ud558\ub294 \uc2dc\uac04\u23f1\ufe0f \ubd80\uc871** \\n\\n\ub808\ubca8 1\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc9d1\uc911\ud558\ub294 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4. \\n\uc774\ub978 \uc544\uce68\uacfc \uc624\ud6c4\uc5d0 \uac1c\uc778\uc801\uc73c\ub85c \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \uacf5\uac04\uc744 \uc608\uc57d\ud574\uc11c \uc628\uc804\ud788 \ub098\ub9cc\uc758 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### Try\\n\\n**\ud5c8\ube0c\ud83c\udf3f\uc640\uc758 \ud2f0\ud0c0\uc784?** \\n\\n\uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc744 \ub298\ub9b4 \ubc29\ubc95\uc744 \uc0dd\uac01\ud558\ub2e4\uac00 \ub300\ud654\ub97c \ub098\ub204\uc9c0 \ubabb\ud55c \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \uae5c\uc9dd \ucee4\ud53c\ucc57\uc744 \ud558\uba74 \uc5b4\ub5a8\uae4c \uc0dd\uac01\ud588\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 \uc7a1\ub2f4\ubc29\uc5d0 `\uc800\uc640 \ucee4\ud53c\ucc57 \ud558\uc2e4 \ubd84 :)` \ud558\uba74\uc11c \uc62c\ub9b4 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ucc38\uc5ec\ud558\ub294 \uc0ac\ub78c\uc774 \uc788\uc744\uc9c0, \uc548 \uc88b\uac8c \ubcf4\ub294 \uac8c \uc544\ub2d0\uc9c0 \uac71\uc815\ub418\uc9c0\ub9cc \uadf8\ub798\ub3c4 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4. \\n\uc800\ub791 \ud5c8\ube0c\ud2f0 \ud55c\uc794 \ud558\uc2e4\ub798\uc694? \\n\\n**\uae30\uc220\uc801\uc778 \ubd80\ubd84** \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0 \uc870\uae08 \ub354 \ubb34\uac8c\ub97c \ub450\ub2e4 \ubcf4\ub2c8 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc774 \ubd80\uc871\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc2dc\uac04\uc758 \uc5ec\uc720\uac00 \ub420 \ub54c \ucc45\uc744 \uc870\uae08\uc529 \uc77d\uc5b4\uc57c\uaca0\ub2e4. \\n\ube14\ub85c\uadf8\uc5d0 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \ub9ce\uc774 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\ub294 \uc2dc\uac04\ub3c4 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### \ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70 \\n\\n\uc2dc\uac04\uc774 \ube60\ub974\uac8c \ud758\ub7ec\uac14\ub2e4. \\n\ud0c0\uc778\uc5d0\uac8c \uc88b\uc740 \uc601\ud5a5\uc744 \uc8fc\uae30\uc704\ud574, \ubc29\ud559\ub3d9\uc548 \ub098\ub97c \ucc59\uae30\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\ub610\ud55c \ud568\uaed8 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc744 \ubaa9\ud45c\ub85c \uc55e\uc73c\ub85c\ub3c4 \uafb8\uc900\ud788 \uc758\uc2dd\uc801 \ub178\ub825\uc744 \ud574\uc57c\uaca0\ub2e4."},{"id":"chess-retrospective","metadata":{"permalink":"/chess-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","description":"1, 2\ub2e8\uacc4//github.com/woowacourse/java-chess/pull/441","date":"2023-03-31T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 31\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.705,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","slug":"chess-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","permalink":"/woowacourse-level1-retrospective"},"nextItem":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","permalink":"/grasp"}},"content":":::note PR \ub9c1\ud06c \\n1, 2\ub2e8\uacc4: https://github.com/woowacourse/java-chess/pull/441 \\n3, 4\ub2e8\uacc4: https://github.com/woowacourse/java-chess/pull/529 \\n:::\\n\\n### \uccb4\uc2a4\\n\uccb4\uc2a4 \ubbf8\uc158\uc5d0\ub294 \uac00\ube44\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4! \\n\uccb4\uc2a4\ub294 \uc774\uc804 \ubbf8\uc158\ub4e4\ubcf4\ub2e4 \ud6e8\uc52c \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778\uc774\uc5c8\ub2e4. \\n\ud558\uc9c0\ub9cc \uac00\ube44\uc640 \ub098\ub294 \uccb4\uc2a4 \ub3c4\uba54\uc778\uc774 \uc775\uc219\ud574\uc11c \ub354 \ud3b8\ud55c \ub9c8\uc74c\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc5b4\ub824\uc6e0\ub358 \ubd80\ubd84\uc740 \uae30\ubb3c\uc758 \uc774\ub3d9, \uc774\ub3d9\uc2dc \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4. \\n \\n\uac00\ube44\uac00 \uc9d1\uc5d0\uac00\uc11c\ub3c4 \uae30\ubb3c\uc758 \uc774\ub3d9 \uad00\ub828\ud574 \uc0dd\uac01 \uc815\ub9ac\ud55c \uae00\uc744 \ubcf4\ub0b4\uc918\uc11c \ub354\uc6b1 \ube68\ub9ac \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ucd5c\uc885\uc801\uc73c\ub85c \uacb0\uc815\ud55c \ubd80\ubd84\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n**\uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5\uc5ec\ubd80** \\nRank\uc640 File\uc740 \uac01\uac01 \uc704\uce58\uac12\uc744 \uac00\uc9c0\uace0 \uc788\uace0, \uac12\uc758 \ucc28\uc774\ub97c \uc774\uc6a9\ud574\uc11c \uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uacc4\uc0b0\ud588\ub2e4. \\n\uc9c1\uc120 \u2192 Rank\uc640 File \ucc28\uc774 \uc911 \ud558\ub098\uac00 0\uc774\uc5b4\uc57c \ud55c\ub2e4. \\n\ub300\uac01\uc120 \u2192 Rank\uc640 File \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \uac19\uc544\uc57c \ud55c\ub2e4. ex) abs(-2) == abs(2) \\n\ub098\uc774\ud2b8 \u2192 \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \ud558\ub098\ub294 2 \ub098\uba38\uc9c0 \ud558\ub098\ub294 1\uc774\uc5b4\uc57c \ud55c\ub2e4.\\n\\n**\ub3c4\ucc29 \uce78\uc758 \uae30\ubb3c \uc5ec\ubd80** \\n\uc544\uad70 \u2192 \uc774\ub3d9\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc801\uad70 \u2192 \uc774\ub3d9\uc774 \uac00\ub2a5\ud558\ub2e4. \uc801\uad70\uc744 \uc7a1\ub294\ub2e4. \\n\\n**\uc911\uac04\uc5d0 \uae30\ubb3c \uc874\uc7ac \uc5ec\ubd80** \\n\uc774\ub3d9 \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\uba74 \uc548\ub41c\ub2e4. \\n\\n**\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9** \\n\uccb4\uc2a4 \ubbf8\uc158\uc740 \ud2b9\ubcc4\ud558\uac8c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc5f0\uacb0\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5c8\ub2e4. \\n\uccb4\uc2a4 \uac8c\uc784\uc758 \uc0c1\ud0dc\ub97c \ub2e4\uc74c\uc758 \ub450\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uc815\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n- \uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95 \\n- \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\uace0 \uac8c\uc784\uc744 \ubd88\ub7ec\uc640 \uae30\ubcf4\ub300\ub85c \uc774\ub3d9\uc2dc\ud0a4\ub294 \ubc29\ubc95 \\n\\n\uae30\ubb3c\uc774 \uc774\ub3d9\ud560 \ub54c\ub9c8\ub2e4 \uac12\uc744 \uc800\uc7a5\ud558\uace0 \uc2f6\uc5c8\uace0, \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud588\ub2e4. \\n\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc774\uc720\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n- \ud134\uacfc \uac19\uc740 \ubd80\uac00\uc801\uc778 \uc694\uc18c\ub97c \uc800\uc7a5\ud574\uc57c \ud55c\ub2e4. \\n- \uc774\ub3d9\uc744 \ud560 \ub54c \uae30\ubb3c\uc774 \uc7a1\ud788\ub294 \uacbd\uc6b0 update \ucffc\ub9ac(\uc774\ub3d9 \uae30\ubb3c)\uc640 delete(\uc7a1\ud78c \uae30\ubb3c) 2\uac1c\uc758 \ucffc\ub9ac\ub97c \ub0a0\ub824\uc57c \ud55c\ub2e4. \\n- \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ub3c4\uba54\uc778\uc758 \ubcc0\uacbd\uc774 \ud06c\uac8c(\ucd08\uae30 \uc0c1\ud0dc\ub97c \uad6c\uc131\ud558\ub294 \ubd80\ubd84) \uc77c\uc5b4\ub098\uc57c \ud55c\ub2e4. \\n\\n\uc815\ub9ac\ud558\uc790\uba74 \uae30\ubb3c \uc804\uccb4 \uc800\uc7a5\uacfc \uae30\ubcf4 \uc800\uc7a5\uc740 \ub2e4\uc74c\uacfc \ucc28\uc774\uac00 \uc788\ub2e4. \\n\ubcf4\ub4dc\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc\uc5d0\uc11c 32\uac1c\uc758 Insert \ucffc\ub9ac(\uae30\ubb3c\uc758 \uc704\uce58) + \uae30\ubb3c \uc774\ub3d9 \uc2dc \uc6c0\uc9c1\uc784 \ubcc0\uacbd(\uc7a1\ud788\ub294 \uacbd\uc6b0 2\uac1c\uc758 \ucffc\ub9ac) \\n\uae30\ubcf4\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uad6c\uc131 + \uc800\uc7a5\ub41c \uae30\ubcf4\ub97c select \ucffc\ub9ac\ub85c \uc870\ud68c\ud574\uc11c \uc0ac\uc6a9(1\ud68c) + insert \ucffc\ub9ac(\uc774\ub3d9 \ub2f9 1\ud68c)\\n\\n\ucd94\uac00\ub85c \uae30\ubcf4\uc800\uc7a5\uc774 \uad6c\ud604\ub3c4 \ub354\uc6b1 \uac04\ub2e8\ud558\ub2e4. \ud83d\udc4d \\n\\n**\ubd80\uac00\uc801\uc778 \ubd80\ubd84**\\n\\n\ub9ac\ubdf0\uc5b4\uc778 \ucc30\ub9ac\ud83c\udf6b\uac00 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uac8c\uc784\uc774 \uc9c4\ud589\ub41c\ub2e4\uba74 \uc5b4\ub5a8\uc9c0? \uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ub2e4\uc591\ud55c \uc2dc\ub3c4\ub97c \ud574\ubd24\ub2e4. \\n- \ub204\ub204\uc758 \ub3c4\uc6c0\uc73c\ub85c ConnectionPool \uad6c\ud604 \\n- ThreadLocal \uc0ac\uc6a9\ud574\uc11c \uc4f0\ub808\ub4dc \ubcc4 \uc138\uc158 \uad00\ub9ac \\n- \uc2e4\uc81c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub0b4\uc5d0\uc11c \uccb4\uc2a4 \uac8c\uc784\uc774 \uc9c4\ud589\ub418\ub294 Board\ub97c ConcurrentHashMap\uc73c\ub85c \uc800\uc7a5(\uc0ac\uc2e4 \uc774 \ubd80\ubd84\uc740 \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ud544\uc694\uc5c6\uc9c0\ub9cc 2\uba85\uc774 \uc11c\ub85c \uac8c\uc784\ud558\ub294 \uacbd\uc6b0\ub97c \uc0dd\uac01\ud574\uc11c \ub123\uc5b4\ubcf4\uc558\ub2e4.) \\n\\n\ub450 \uba85\uc774 \uc11c\ub85c \uac19\uc740 \ubc29\uc5d0 \uc785\uc7a5\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4\uba74 \ucd9c\ub825\ud558\ub294 \ubd80\ubd84\uc774 \uae4c\ub2e4\ub85c\uc6cc\uc9c8 \uac83 \uac19\ub2e4\uace0 \uc608\uc0c1\ub418\uc5b4(Board\uc5d0 \uc635\uc800\ubc84 \ud328\ud134\uc744 \uc0ac\uc6a9\ud574\uc57c\ub418\ub098?) \ud574\ubcfc \uc5c4\ub450\uac00 \ub098\uc9c0 \uc54a\uc558\ub2e4. \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc9c0 \ubabb\ud55c \ubd80\ubd84** \\nDB \uad00\ub828 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0\ub9cc \uc9d1\uc911\ud558\ub2e4\ubcf4\ub2c8 \uc815\uc801 \uc911\uc694\ud55c DB\uc758 \ucf54\ub4dc\uc758 \uc608\uc678\ucc98\ub9ac, \ube48 \uac12\uc744 \ubc18\ud658 \ud558\ub294 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucc98\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \ucc30\ub9ac\uc758 \uaf3c\uaf3c\ud55c \ub9ac\ubdf0\ub85c DB\ubd80\ubd84\uacfc \ub098\ub9cc\uc758 JdbcTemplate\uc744 \uae54\ub054\ud558\uac8c \uad6c\ud604\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n**\uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ub2f4\uac10** \\n\ucd08\ubc18\uc5d0\ub294 \uc5ec\uc720\ub86d\uc9c0\ub9cc \uc81c\ucd9c \ub9c8\uac10\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \uc218\ub85d \uc0ac\ub78c\uc774 \uae09\ud574\uc9c0\ub294 \uac83 \uac19\ub2e4. \\n\ub2e4\uc74c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\ud560 \ub550 \uc18d\ub3c4\ub97c \uc870\uc808\ud558\uace0, \ub9c8\uc74c\uc5d0 \uc5ec\uc720\ub97c \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**DAO \uc911\ubcf5 \uc81c\uac70**\\n\\n\ud504\ub864\ub85c\uadf8\uc5d0 [\uae00](https://prolog.techcourse.co.kr/studylogs/2947)\uc744 \uc791\uc131\ud588\ub2e4. \\nDAO\ub97c \uc791\uc131\ud558\ub294\ub370 try-catch-resources\uc640 \uc5ec\ub7ec \ucf54\ub4dc\uac00 \uc911\ubcf5\ub418\uc11c \uc81c\uac70\ud558\uace0\uc2f6\uc5c8\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc73c\ub85c \uae54\ub054\ud558\uac8c \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\udc4d\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\ud398\uc5b4 \uc0dd\uac01\ud558\uae30** \\n\uac00\ube44\ub294 \ub204\uad6c\ubcf4\ub2e4 \ud398\uc5b4\ub97c \uc0dd\uac01\ud558\uace0, \ubc30\ub824\ud574\uc8fc\ub294 \ud398\uc5b4\uc600\ub2e4. \\n\uc911\uac04 \uc911\uac04 \ub2f9 \ub5a8\uc5b4\uc9c8\uae4c\ubd10 \uac71\uc815\ub3c4 \ud574\uc8fc\uace0, \ub098\uc758 \ucee8\ub514\uc158\ub3c4 \ud655\uc778\ud574\uc92c\ub2e4! \\n\\n**\ubbf8\uc158 \ubab0\uc785\ud558\uae30** \\n\ucd5c\uadfc\uc5d0 \ubbf8\uc158\uc5d0 \uc798 \ubab0\uc785\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\uac00\ube44\ub294 \ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \ubbf8\uc158\uc5d0 \ub300\ud55c \ubab0\uc785\ub3c4\uac00 \ub9e4\uc6b0 \uc88b\uc558\ub2e4. \\n\uc9d1\uc5d0\uac00\uc11c\ub3c4 \uccb4\uc2a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ub85c\uc9c1\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560 \uc9c0 \uc0dd\uac01\ud55c \ub4a4 \uaf3c\uaf3c\ud574\uc11c \uc815\ub9ac\ud574\uc11c \ub098\uc5d0\uac8c \ubcf4\ub0b4\uc8fc\uc5c8\ub2e4. \\n\ub355\ubd84\uc5d0 \ub098\ub3c4 \uac00\ube44\uc758 \uc0dd\uac01\uc744 \uc54c \uc218 \uc788\uc5b4\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294\ub370 \uac00\uc18d\ub3c4\uac00 \ubd99\uc740 \uac83 \uac19\ub2e4. \\n\ub610\ud55c \ubbf8\uc158\uc744 \uc798 \ub9c8\ubb34\ub9ac\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\uc774 \uc804\ub2ec\ub418\uc11c \uadf8\ub7f0\uc9c0 \ub098\ub3c4 \ub369\ub2ec\uc544 \uc5f4\uc2ec\ud788 \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\ude04 \\n\\n**\uc194\uc9c1\ud568** \\n\uba3c\uc800 \ud68c\uace0\ud558\uc790\uace0 \ub9d0 \uac78\uc5b4\uc918\uc11c \uc815\ub9d0 \uace0\ub9c8\uc6e0\ub2e4\uace0 \ud45c\ud604\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\ubaa8\ub974\ub294\uac8c \uc788\uc73c\uba74 \uc194\uc9c1\ud558\uac8c \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\ub098\uc758 \uc758\uacac\uc744 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud55c \uc0c1\ud0dc\ub85c \uc804\ub2ec\ud560 \ub54c \uc774\ud574\uac00 \uc548\ub418\uc5c8\ub2e4\uace0 \uc815\ud655\ud788 \uc804\ub2ec\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\uc194\uc9c1\ud568\uc740 \ud398\uc5b4\ud560 \ub54c \uc911\uc694\ud55c \ubd80\ubd84\uc778 \uac83 \uac19\ub2e4. \\n\\n\ub9c8\uc9c0\ub9c9\uc73c\ub85c \ucc30\ub9ac\ud83c\udf6b \uccb4\uc2a4 \ubbf8\uc158\ub54c \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0 \ub0a8\uaca8\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4!"},{"id":"grasp","metadata":{"permalink":"/grasp","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-30-GRASP.mdx","source":"@site/blog/2023-1/2023-03-30-GRASP.mdx","title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","description":"GRASP(General Responsibility Assignment Software Pattern)","date":"2023-03-30T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 30\uc77c","tags":[{"label":"GRASP","permalink":"/tags/grasp"},{"label":"OOP","permalink":"/tags/oop"}],"readingTime":8.085,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","slug":"grasp","tags":["GRASP","OOP"]},"unlisted":false,"prevItem":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","permalink":"/chess-retrospective"},"nextItem":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","permalink":"/blackjack-retrospective"}},"content":"### GRASP(General Responsibility Assignment Software Pattern)\\n\\n\ud06c\ub808\uc774\uadf8 \ub77c\ub9cc\uc758 Applying UML and Patterns\uc774\ub77c\ub294 \ucc45\uc5d0\uc11c \ub098\uc628 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134\\n\\n\uac01 \ud328\ud134\ub9c8\ub2e4 Solution\uacfc Problem\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub2e4.\\n\\n### \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)\\n\\nQ: \uac1d\uccb4\uc5d0 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uae30\ubcf8 \uc6d0\uce59\uc740 \ubb34\uc5c7\uc778\uac00?\\n\\nA: \ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub370 \ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \ud074\ub798\uc2a4(\uc815\ubcf4 \uc804\ubb38\uac00)\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4.\\n\\n\uc815\ubcf4\uc640 \ud589\ub3d9\uc744 \uac00\uae4c\uc6b4 \uacf3\uc5d0 \uc704\uce58\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \ucea1\uc290\ud654\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4.\\n\\n\ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \uac1d\uccb4\ub4e4\ub85c \ucc45\uc784\uc774 \ubd84\uc0b0\ub41c\ub2e4.\\n\\n### \ucc3d\uc870\uc790 \ud328\ud134(Creator)\\n\\nQ: \ub204\uac00 \uac1d\uccb4 A\ub97c \uc0dd\uc131\ud558\ub294\uac00?\\n\\nA: \ub2e4\uc74c\uc758 \uc870\uac74\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\uc871\ud558\ub294 \uac1d\uccb4\uc5d0\uac8c \uac1d\uccb4 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n- B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\uc758 \ucd08\uae30\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4.\\n\\n\uc0dd\uc131 \uc608\uc815\uc778 \uac1d\uccb4\uc640 \uc5f0\uad00\ub418\uc5b4 \uc788\ub294 \uac1d\uccb4\uac00 \uc0dd\uc131 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac8c \ub41c\ub2e4\uba74, \uc774\ubbf8 \ud574\ub2f9 \uac1d\uccb4\uc640 \uacb0\ud569\ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\uac8c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)\\n\\nQ: \uc758\uc874\uc131\uc744 \ub0ae\ucd94\uace0 \ubcc0\ud654\uc758 \uc601\ud5a5\uc744 \uc904\uc774\uba70 \uc7ac\uc0ac\uc6a9\uc131\uc744 \uc99d\uac00\uc2dc\ud0a4\ub294 \ubc29\ubc95\uc740?\\n\\nA: \uc804\uccb4\uc801\uc778 \uacb0\ud569\uc774 \ub0ae\uac8c \uc720\uc9c0\ub418\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n> \uacb0\ud569\ub3c4(Coupling)\\n\uac1d\uccb4 \uc0ac\uc774\uc758 \uc758\uc874\uc131\uc774 \uacfc\ud55c \uacbd\uc6b0 \uacb0\ud569\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4.\\n- \uc624\ube0c\uc81d\ud2b8 p.17\\n> \\n\\n\uacb0\ud569\ub3c4\ub97c \ub0ae\ucd98\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4.\\n\\n- \ub2e4\ub978 \uad6c\uc131 \uc694\uc18c\uc758 \ubcc0\ud654\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294\ub2e4.\\n- \uc7ac\uc0ac\uc6a9\uc774 \ud3b8\ub9ac\ud574\uc9c4\ub2e4.\\n- \ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\uc758\uc874\ud558\ub294 \ud074\ub798\uc2a4\uac00 \uc801\uae30 \ub54c\ubb38\uc5d0)\\n\\n### \ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)\\n\\nQ. \uac1d\uccb4\ub97c \uad00\ub9ac\ud558\uae30 \uc27d\uac8c \ud558\ub824\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub192\uc740 \uc751\uc9d1\ub3c4\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n> \uc751\uc9d1\ub3c4(Cohesion)\\n\uc5f0\uad00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc5f0\uad00\uc131 \uc5c6\ub294 \uc791\uc5c5\uc740 \ub2e4\ub978 \uac1d\uccb4\uc5d0\uac8c \uc704\uc784\ud558\ub294 \uac1d\uccb4\ub97c \uac00\ub9ac\ucf1c \uc751\uc9d1\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4.\\n- \uc624\ube0c\uc81d\ud2b8 p.26\\n> \\n\\n\ubcc0\uacbd\uc758 \uc774\uc720\uc5d0 \ub530\ub77c \ud074\ub798\uc2a4\ub97c \ubd84\ub9ac\ud55c\ub2e4\uba74 \uc751\uc9d1\ub3c4\ub97c \ub192\uc77c \uc218 \uc788\uace0, \uc751\uc9d1\ub3c4\uac00 \ub192\uc544\uc9c4\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4.\\n\\n- \ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\ud560\ub2f9\ub41c \ucc45\uc784\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0)\\n- \uc720\uc9c0\ubcf4\uc218\uac00 \uc26c\uc6cc\uc9c4\ub2e4.\\n- \ub0ae\uc740 \uacb0\ud569\ub3c4 \ub610\ud55c \uc9c0\uc6d0\ud55c\ub2e4.\\n- \uc751\uc9d1\ub3c4\uac00 \ub192\uc740 \ud074\ub798\uc2a4\ub294 \ud2b9\uc815\ud55c \ubaa9\uc801\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc7ac\uc0ac\uc6a9\ud558\uae30 \uc88b\ub2e4.\\n\\n### \ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)\\n\\nQ. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uac83\uc740 \ub204\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294\uac00?\\n\\nA. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 Controller \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n\\n\uc5b4\ub5a4 \uc11c\ube0c\uc2dc\uc2a4\ud15c\uc774 \uc874\uc7ac\ud55c\ub2e4\uace0 \uac00\uc815\ud560 \ub54c\\n\\n- \uc9c1\uc811\uc801\uc73c\ub85c \uac1d\uccb4\uc5d0 \uc811\uadfc\ud558\uc5ec \ud504\ub85c\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uacb0\ud569\ub3c4\uac00 \uc0c1\uc2b9\ud55c\ub2e4.\\n- \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc5d0 \ub4e4\uc5b4\uc624\ub294 \uc694\uccad\uc744 \ucc98\ub9ac\ud574\uc8fc\ub294 \ucee8\ud2b8\ub864\ub7ec\uac00 \uc788\ub2e4\uba74 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 \ud574\ub2f9 \ucee8\ud2b8\ub864\ub7ec\ub9cc \uc54c\uba74 \ub41c\ub2e4.\\n- \ub9cc\uc57d \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc758 \ubcc0\uacbd\uc774 \uc0dd\uacbc\uc744 \ub54c \uc678\ubd80\uc5d0 \ubbf8\uce58\ub294 \uc601\ud5a5\ub3c4 \uc904\uc5b4\ub4e0\ub2e4.\\n\\n### \ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)\\n\\nQ. \uac1d\uccb4\uc758 \ud0c0\uc785\uc5d0 \ub530\ub77c \ud589\ub3d9\uc774 \ubc14\ub010\ub2e4\uba74 \ucc45\uc784\uc744 \uc5b4\ub5bb\uac8c \ud560\ub2f9\ud574\uc57c \ud560\uae4c?\\n\\nA. OOP\uac00 \uc9c0\uc6d0\ud558\ub294 \ub2e4\ud615\uc131\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ud65c\uc6a9\ud55c\ub2e4. (\uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0 \ud589\ub3d9\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uad6c\ud604)\\n\\n\uac1d\uccb4\uc758 \uc885\ub958\uc5d0 \ub530\ub77c \ubd84\uae30\ud558\ub294 \uc870\uac74\ubb38\uc774 \uc544\ub2cc \ub2e4\ud615\uc131\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4.\\n\\n\uc0c8\ub85c\uc6b4 \ud0c0\uc785\uc774 \ucd94\uac00\ub418\uc5c8\uc744 \ub54c \uc870\uac74\ubb38\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uae30\uc874\uc758 \uc870\uac74\ubb38\uc744 \uc218\uc815\ud574\uc57c \ud558\uc9c0\ub9cc \ub2e4\ud615\uc131\uc744 \ud65c\uc6a9\ud558\uba74 \uc27d\uac8c \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\\n\\nQ. \uc5b4\ub5bb\uac8c \ud558\uba74 \ubcc0\uacbd\uc774 \ub2e4\ub978 \uc694\uc18c\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud560 \uc218 \uc788\uc744\uae4c?\\n\\nA. \ubcc0\ud654\uac00 \uc608\uc0c1\ub418\ub294 \uc9c0\uc810\uc744 \uc2dd\ubcc4\ud558\uace0, \uc8fc\uc704\uc5d0 \uc548\uc815\ub41c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud615\uc131\ud558\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n### \uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)\\n\\nQ. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud558\uace0 \uc2f6\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ub2e4\ub978 \uac1d\uccb4\ub97c \ub450\uc5b4 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc911\uc7ac\uc790 \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ud558\ub098\uc758 \uac1d\uccb4\ub97c \ucd94\uac00\ud558\uc5ec \ubcf5\uc7a1\ud55c \uad00\uacc4\ub97c \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc911\uac04\uc5d0 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub454\ub2e4\uba74 \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\uc5d0 \ud574\ub2f9\ub41c\ub2e4.\\n\\n### \uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)\\n\\nQ. \ucc45\uc784\uc744 \ud560\ub2f9\ud55c \ub3c4\uba54\uc778 \uac1d\uccb4\uac00 Low Coupling, High Cohesion, \uc7ac\uc0ac\uc6a9\uc131 \ub4f1\uc758 \ubaa9\uc801\uc744 \uc704\ubc18\ud55c\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub3c4\uba54\uc778 \uac1c\ub150\uc744 \ud3ec\ud568\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uace0 \ub9e4\uc6b0 \uc751\uc9d1\ub41c \ucc45\uc784\uc744 \ud560\ub2f9\ud560 \uc218 \uc788\ub2e4.\\n\\n\ud589\ub3d9\uc744 \ucd94\uac00\ud560 \ub54c, \ud574\ub2f9 \ucc45\uc784\uc744 \uc218\ud589\ud560 \ub3c4\uba54\uc778 \uac1c\ub150\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \ub3c4\uba54\uc778\uacfc \ubb34\uad00\ud55c \uc778\uacf5\uc801\uc778 \uac1d\uccb4\ub97c \ub9cc\ub4e0\ub2e4\uc74c \ud574\ub2f9 \uac1d\uccb4\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4.\\n\\n\uac1d\uccb4\uac00 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud574\uc57c \ud560 \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4\uace0, \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134\uc744 \uc801\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud558\ub77c\ub294 \ucc45\uc784\uc744 \uac00\uc9c0\ub77c\uace0 \ud558\uc9c0 \uc54a\ub294\ub2e4.\\n\\n\uc608) \uc0c1\uc810\uacfc \uace0\uac1d \ud074\ub798\uc2a4\uac00 \uc788\uace0 \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uace0 \uac00\uc815\\n\\n- \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 \uac70\ub798\ub97c \ud558\ub824\uba74 \ud658\uc804\uc744 \ud574\uc57c\ud55c\ub2e4.\\n- \ub450 \ud074\ub798\uc2a4 \ub2e4 \ud658\uc804\uc5d0 \ub300\ud55c \ucc45\uc784\uc744 \ubd80\uc5ec\ud558\uae30 \uc560\ub9e4\ud558\ub2e4\uba74 \ud658\uc804\uc744 \ucc45\uc784\ud558\ub294 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud558\uace0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc624\ube0c\uc81d\ud2b8 5\uc7a5. \ucc45\uc784 \ud560\ub2f9\ud558\uae30, [\uc870\uc601\ud638](http://aeternum.egloos.com/)\\n\\nApplying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman\\n\\n[GRASP, \ud55c\ube5b \ub124\ud2b8\uc6cc\ud06c](https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS8586826397)"},{"id":"blackjack-retrospective","metadata":{"permalink":"/blackjack-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/java-blackjack/pull/427","date":"2023-03-14T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 14\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.17,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","slug":"blackjack-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","permalink":"/grasp"},"nextItem":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","permalink":"/ladder-retrospective"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/java-blackjack/pull/427 \\n2\ub2e8\uacc4: https://github.com/woowacourse/java-blackjack/pull/537 \\n:::\\n\\n### \ube14\ub799\uc7ad\\n\\n\ube14\ub799\uc7ad \ubbf8\uc158\uc5d0\uc11c\ub294 \ud6c4\ucd94\uc640 \ud398\uc5b4(\uc870\ubbf8\ub8cc \ub4c0\uc624?)\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \uc2e4\uc218\ud558\uc9c0 \uc54a\uace0, \ubc14\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uc9c0 \uc54a\uace0 \uce5c\ud574\uc9c0\uae30 \ubd80\ud130 \uc2dc\uc791\ud588\ub2e4. \\n\\n\ube14\ub799\uc7ad\uc740 \uad6c\ud604\ud574\uc57c \ub420 \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud560 \uac83 \uac19\uc558\uc9c0\ub9cc \\n\ud6c4\ucd94\uc640 \ud568\uaed8 \uc804\ub7b5\uc801(\uc0bc\uc77c\uc808\uc5d0 \ubbf8\uc158 \uc774\uc57c\uae30 \ub098\ub204\uae30)\uc73c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud574 \uc2dc\uac04 \ub0b4\uc5d0 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\ubbf8\uc158\uc744 \ub05d\ub098\uace0 \ud68c\uace0\ub97c \ud588\uc744 \ub54c \ud6c4\ucd94\uac00 \uace0\ubbfc\uac70\ub9ac\ub97c \ud558\ub098 \ub0b4\uc92c\ub2e4. \\n\\"\ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \uc555\ubc15\uac10\uc744 \ub290\ub07c\ub294 \ud398\uc5b4\uac00 \uc788\ub2e4\uba74 \ud5c8\ube0c\uac00 \ud574\uc904 \uc218 \uc788\ub294\uac8c \ubb50\uac00 \uc788\uc744\uae4c?\\" \\n\\n\uacf0\uacf0\ud788 \uc0dd\uac01\ud574\ubd24\uc9c0\ub9cc \uc27d\uac8c \ub2f5\uc744 \ub0b4\ub9b4 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uc911\uac04 \uc911\uac04 \ud68c\uace0\ub97c \ud558\uace0, \ub098\uc758 \uc18c\ud504\ud2b8\uc2a4\ud0ac\uc744 \ub192\ud788\ub294\uac8c \ub2f5\uc77c\uae4c? \\n\ubd80\ub2f4\uac10\uc744 \ub290\ub07c\uc9c0 \uc54a\uace0 \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub420 \uc218 \uc788\ub3c4\ub85d \uacc4\uc18d \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4. \\n\\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc0dd\uac01\uc774 \ub9ce\uc544\uc838\uc11c \uc804 \ub9ac\ubdf0\uc5b4\uc778 \ud130\ud2c0\ud83d\udc22\uacfc\ub3c4 \ub300\ud654\ub97c \ub098\ub204\uc5c8\ub2e4. \\n\ud130\ud2c0\uc740 \uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84(\uad81\uadf9\uc801\uc778 \ubaa9\ud45c\uc778 \uc88b\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uac83)\uc5d0 \uc9d1\uc911\ud574\ubcf4\ub77c\uace0 \ud558\uc168\ub2e4. \\n\\n\uc88b\uc740 \ucf54\ub4dc, \uc88b\uc740 \ud398\uc5b4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc77c\ub2e8 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\ud398\uc5b4 \uc2e0\uacbd\uc4f0\uae30** \\n\uc774\ubc88 \ud398\uc5b4\ud560 \ub54c \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub0b4\ubcf4\ub3c4\ub85d \ud588\ub2e4. \uadf8\ub807\uae30\uc5d0 \ub108\ubb34 \uc758\uacac\uc744 \uac15\ud558\uac8c \ubc00\uc5b4\ubd99\uc778 \ub290\ub08c\uc774 \ub4e4\uc5b4\uc11c \ubbf8\uc548\ud588\ub2e4. \\n\ud6c4\ucd94\uac00 \uc555\ubc15\uc744 \ub290\uaf08\uc744 \uc218\ub3c4 \uc788\uc744 \uac83 \uac19\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\uc911\uac04 \uc911\uac04 \uc791\uc740 \ud68c\uace0\ub97c \uc9c4\ud589\ud574\ubcf4\ub294 \uac83\uc774 \uc88b\uc744\uae4c?\\n\\n**\uccb4\ub825 \uad00\ub9ac** \\n\uc694\uc998 \uc798 \ubabb\uba39\ub294 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c \uc0b4 \ub0a0\uc774 \ub9ce\uc740\ub370 \uc798 \ucc59\uaca8\uba39\uace0, \ud798\ub0b4\uc57c\uaca0\ub2e4.\\n\\n**\uc911\uac04 \uc911\uac04 \ub3cc\uc544\ubcf4\uae30** \\n\uc774\ubc88 \ubbf8\uc158\uacfc \uad00\ub828\ub41c \ub0b4\uc6a9\uc740 \uc544\ub2c8\uc9c0\ub9cc \uc6b0\ud14c\ucf54\ub97c \uc798 \ud65c\uc6a9 \ud558\uace0 \uc788\ub294\uc9c0 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4. \\n\ub0b4\uac00 \uc6b0\ud14c\ucf54\uc5d0 \uc9c0\uc6d0\ud55c \uc774\uc720\ub97c \ud56d\uc0c1 \uc78a\uc9c0 \uc54a\uc544\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uc0c1\ud0dc \ud328\ud134** \\n\uac1d\uccb4\uc758 \ub0b4\ubd80 \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc2a4\uc2a4\ub85c \ud589\ub3d9\uc744 \ubcc0\uacbd\ud558\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc73c\ub85c if/else/switch\uc640 \uac19\uc740 \uc870\uac74\ubb38\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\ube14\ub799\uc7ad \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc0c1\ud0dc \ud328\ud134\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ucc98\uc74c \uc801\uc6a9\ud574\ubcf4\uc558\ub2e4. \\n\ucc98\uc74c \uc801\uc6a9\ud558\uae30 \uc804\uc5d0\ub294 \ubcc4\ub85c\ub77c\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc0dd\uac01\ubcf4\ub2e4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4. \\n\\n**\uc77c\uad00\uc131, \uac00\ub3c5\uc131, \ucd94\uc0c1\ud654** \\n\uc774\ubc88 \ub9ac\ubdf0\uc5b4\ub294 \uac80\ud504\ud83c\udf6b \uc600\ub2e4! \\n\uac80\ud504\uc758 \ub9ac\ubdf0\ub294 \uac04\uacb0\ud568\uc5d0 \uad00\ub828\ub41c \ub0b4\uc6a9\uc774 \ub9ce\uc558\ub2e4. \\n\uc77c\uad00\uc131\uc774 \uc788\ub294 \ucf54\ub4dc, \uac00\ub3c5\uc131\uc774 \uc88b\uc740 \ucf54\ub4dc, \ucd94\uc0c1\ud654\uac00 \uc798 \ub418\uc5b4\uc788\ub294 \ucf54\ub4dc \\n\uc77d\uae30 \uc88b\uace0, \uac04\uacb0\ud55c \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b4 \uac83 \uac19\ub2e4. \\n\ucf54\ub4dc\ub97c \ubc14\ub77c\ubcf4\ub294 \uc2dc\uc810\uc774 \ud558\ub098 \ub298\uc5b4\ub09c \uae30\ubd84\uc774\ub2e4!(\uc55e\uc73c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc740 \ub098\uc758 \ubaab\uc774\uc9c0\ub9cc) \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uc0dd\uac01 \uc815\ub9ac** \\n\uc911\uac04 \uc911\uac04 \ud604\uc7ac \uc0c1\ud669\uc5d0 \ub300\ud574 \uadf8\ub9bc\uc744 \uadf8\ub9ac\uac70\ub098, \uae00\uc744 \uc801\uc73c\uba74\uc11c \uc815\ub9ac\ud55c\ub2e4. \\n\ud398\uc5b4\uc640 \ub3d9\uc77c\ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\n\uc9c4\ud589\ud558\ub294\ub370 \ub9e4\uc6b0 \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ub098\ub3c4 \ub2e4\uc74c \ud398\uc5b4\ub54c\ubd80\ud130 \ud39c\uc774\ub791 \uc885\uc774\ub97c \uc900\ube44\ud574\uc57c\uaca0\ub2e4.\\n\\n**\uac00\uac10\uc5c6\uc774 \uc758\uacac\uc744 \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84** \\n\uc9c4\ud589 \uc0c1\ud669\uc5d0 \ub300\ud55c \ubd80\ubd84, \uc9c4\ud589 \uc18d\ub3c4, \uc9c0\uae08 \uc790\uc2e0\uc774 \uc774\ud574\ud558\uace0 \uc788\ub294 \ubd80\ubd84\uc744 \ub9d0\ud574\uc918\uc11c \ud3b8\ud588\ub2e4. \\n\ud68c\uace0\ub54c\ub3c4 \uc11c\ub85c \uc194\uc9c1\ud558\uac8c \uc758\uacac\uc744 \uc8fc\uace0 \ubc1b\uc544\uc11c \uc88b\uc558\ub2e4. \\n\\n**\ub3c4\uba54\uc778 \uc5b8\uc5b4\uc5d0 \uc2e0\uacbd\uc4f0\ub294 \ubd80\ubd84** \\n\ud074\ub798\uc2a4\uba85, \ubcc0\uc218\uba85\uacfc \uac19\uc740 \uc5b8\uc5b4\ub97c \uc138\uc2ec\ud558\uac8c \uc2e0\uacbd\uc4f4\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d \uc815\ub9ac\ub3c4 \uae54\ub054\ud558\uac8c \uc798\ud558\ub294 \uac83 \uac19\ub2e4. \\n\\n\ud6c4\ucd94 \ucd5c\uace0 \ud83d\udc4d"},{"id":"ladder-retrospective","metadata":{"permalink":"/ladder-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/java-ladder/pull/97","date":"2023-02-26T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 26\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":10.285,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","slug":"ladder-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","permalink":"/blackjack-retrospective"},"nextItem":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","permalink":"/racing-car-retrospective"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/java-ladder/pull/97 \\n2\ub2e8\uacc4: https://github.com/woowacourse/java-ladder/pull/234 \\n:::\\n\\n### \uc0ac\ub2e4\ub9ac \ud0c0\uae30\\n\\n\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc6b0\uac00\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc774\uc804 \ubbf8\uc158\uacfc \ub2ec\ub9ac TDD\ub85c \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ud544\uc218\uc600\uae30 \ub54c\ubb38\uc5d0 \uc775\uc219\ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, \uc6b0\uac00\uc640 \ubbf8\uc158\uc5d0 \uad00\ud55c \uc18c\ud1b5\uc774 \uc798 \ub418\uc5b4\uc11c \ud070 \ubb38\uc81c \uc5c6\uc774 \ubbf8\uc158\uc744 \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\uc6b0\uac00\uc640 \uc774\uc57c\uae30\uac00 \uc798 \ud1b5\ud574\uc11c \uadf8\ub7f0\uc9c0 1\ub2e8\uacc4\ub294 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub294\ub370, 2\ub2e8\uacc4\uc5d0\uc11c \ub9ce\uc774 \uace0\uc804\ud55c \uac83 \uac19\ub2e4.\\n\\n2\ub2e8\uacc4\uc5d0\uc11c\ub294 2\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ud574\ubd24\ub2e4.\\n\\n1. LadderGame\uc5d0\uc11c Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n2. Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c Ladder\uc5d0\uac8c Position\uc744 \ub118\uaca8\uc8fc\uba70 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95\\n\\n### Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n\\n\uc0ac\uc2e4\uc0c1 index\ub97c Ladder\uc5d0\uac8c \ub118\uaca8\uc8fc\uace0, \ud574\ub2f9 index\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc1b\ub294 \ubc29\ubc95\uacfc \uc720\uc0ac\ud588\ub2e4. \\n\uad6c\ud604\ud558\uace0 \ub098\ub2c8 \ub2e4\ub978 \ud074\ub798\uc2a4\ub4e4\uc774 Position\uc5d0 \ub300\ud55c \uc758\uc874\ub3c4\uac00 \ub108\ubb34 \ub192\uc740 \uac83 \uac19\uc558\ub2e4. \\n\ub610\ud55c Players\uac00 \ubcc4\ub2e4\ub978 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\ub2e4\uace0 \ub290\uaf08\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\n LadderGameController --\x3e LadderGame\\n LadderGame --\x3e Ladder\\n LadderGame --\x3e Players\\n LadderGame --\x3e Items\\n\\n Ladder --\x3e Line\\n Line --\x3e LineStatus\\n\\n LadderGame --\x3e Position\\n Ladder --\x3e Position\\n Items --\x3e Position\\n Line --\x3e Position\\n Players --\x3e Position\\n\\n LadderGame --\x3e LadderGameResult\\n\\n Items --\x3e Item\\n Players --\x3e Player\\n\\n LadderGameController --\x3e InputView\\n LadderGameController --\x3e OutputView\\n\\n```\\n\\n```java\\npublic LadderGameResult play() {\\n final Map result = new LinkedHashMap<>();\\n // \uc0ac\uc6a9\uc790 \uc218\ub9cc\ud07c Position\uc744 \uac00\uc838\uc640\uc11c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4.\\n for (Position position : Position.range(players.count())) {\\n final Position resultPosition = ladder.play(position);\\n result.put(players.get(position), items.get(resultPosition));\\n }\\n return new LadderGameResult(result);\\n}\\n```\\n\\n### Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n\\nPosition\uc5d0 \ub300\ud55c \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub294 Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c, Player\uac00 Ladder\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4. \\n\uc774 \ubc29\ubc95\uc774 \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc704\ud574\uc11c \uac1d\uccb4\ub4e4\uc774 \uae34\ubc00\ud558\uac8c \ud611\ub825\ud558\uace0, \uc870\uae08 \ub354 \ucc45\uc784\uc758 \ubd84\ubc30\uac00 \uc798 \ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\uc774 \ub418\uc5c8\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\n LadderGameController --\x3e LadderGame\\n LadderGame --\x3e Ladder\\n LadderGame --\x3e Players\\n LadderGame --\x3e Items\\n\\n Ladder --\x3e Line\\n Line --\x3e LineStatus\\n Line --\x3e Position\\n\\n Players --\x3e Ladder\\n Player --\x3e Ladder\\n\\n Item --\x3e Position\\n Player --\x3e Position\\n\\n\\n LadderGame --\x3e LadderGameResult\\n\\n Items --\x3e Item --\x3e ItemName\\n Players --\x3e Player --\x3e PlayerName\\n\\n LadderGameController --\x3e InputView\\n LadderGameController --\x3e OutputView\\n\\n OutputView --\x3e LadderMessageGenerator\\n```\\n\\n```java\\npublic LadderGameResult play() {\\n // \ucc38\uac00\uc790\ub4e4\uc5d0\uac8c \uc0ac\ub2e4\ub9ac\ub97c \uc804\ub2ec\ud574\uc11c \uc0ac\ub2e4\ub9ac\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud55c\ub2e4.\\n final Map playResult = players.play(ladder);\\n\\n final Map result = new LinkedHashMap<>();\\n for (Player player : playResult.keySet()) {\\n result.put(player, toItem(playResult.get(player)));\\n }\\n return new LadderGameResult(result);\\n}\\n```\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\uc5d0 \uc2dc\uac04\uc744 \ub4e4\uc774\uae30** \\n\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc815\ud558\ub294\ub370 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ub4e4\uc5ec\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc0ac\ub2e4\ub9ac \ud0c0\uae30\uc758 \uc2e4\ud589 \uacb0\uacfc\ub97c Item\uc73c\ub85c \uc9d3\ub2e4\ub2c8.. \ubb54\uac00 \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\ub2e4. \\n\uc774\uc804 \ubbf8\uc158\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c, \uba85\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \ubd80\uc871\ud568\uc744 \ub9ce\uc774 \ub290\uaf08\ub2e4. \\n\\n**\ud398\uc5b4\uc640 \uc870\uae08 \ub354 \uce5c\ud574\uc9c0\uae30** \\n\uccab\ub0a0\uc740 \ud398\uc5b4\uc640 \uce5c\ud574\uc9c0\ub294 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \uac00\uc838\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc6b0\uac00\ub791 \ud68c\uace0\ud560 \ub54c \ub0b4\uac00 \uc2dc\uc791\ud558\uc790\ub9c8\uc790 \ucee8\ubca4\uc158 \uc815\ud558\uc790\uace0 \ud574\uc11c \ub9ce\uc774 \ub2f9\ud669\uc2a4\ub7ec\uc6e0\ub2e4\uace0 \ud55c\ub2e4. \uc6b0\uac00 \ubbf8\uc548.. \ud83e\udd72\\n\\n**README\ub97c \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c** \\n\uc774\uc0c1\ud558\uac8c \ucf54\ub529\uc5d0 \uc9d1\uc911\ud558\uba74 README\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uba74\uc11c \uac19\uc774 \ucee4\ubc0b \ud558\ub294 \uac78 \ud56d\uc0c1 \uae4c\uba39\ub294\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\uc5d0\ub294 \uc870\uae08 \ub354 \uc2e0\uacbd \uc368\uc57c\uaca0\ub2e4.\\n\\n**\uc88b\uc740 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud558\uae30** \\n\uccab PR\ub54c \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \uc9c8\ubb38\uc744 \ub0a8\uae30\uc9c0 \ubabb\ud588\ub2e4. \\n\ub9ac\ubdf0\uc5b4\uc640\uc758 \uc2dc\uac04\uc774 \uc18c\uc911\ud55c \uc2dc\uac04\uc774\ub77c\ub294 \uac83\uc744 \uae4c\uba39\uc9c0 \ub9d0\uace0, \ub098\uc758 \uc131\uc7a5\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud574\uc57c\uaca0\ub2e4. \\n\\n**PR \ud6c4\uc5d0\ub3c4 \uaf3c\uaf3c\ud558\uac8c \ud655\uc778\ud558\uae30** \\n\ubd84\uba85 \uc54c\uace0 \uc788\ub294 \ubd80\ubd84\uc774\uc9c0\ub9cc, \ub193\uce5c \ubd80\ubd84\uc774 \ub9ce\uc740 \uac83 \uac19\uc558\ub2e4. \\nPR \ud558\uae30 \uc804\uc5d0\ub3c4 \uacc4\uc18d \ud655\uc778\uc744 \ud588\uc9c0\ub9cc, \uc544\ubb34\ub798\ub3c4 IntelliJ\uc5d0\uc11c \ubcf4\ub2c8 \ucf54\ub4dc\uc5d0 \uc775\uc219\ud574\uc838\uc11c \uadf8\ub7f0\uc9c0 \ubcc0\uacbd\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc798 \uc548\ubcf4\uc600\ub2e4. \\ngithub pr\uc5d0\uc11c\ub294 \uc804\uccb4 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\ub2c8 PR \ud6c4\uc5d0\ub3c4 \uaf2d \ud655\uc778\ud574\uc57c\uaca0\ub2e4.\\n\\n**\uc801\uadf9\uc801\uc73c\ub85c \ub098\uc758 \uc758\uacac\uc744 \ub9d0\ud558\uae30** \\n\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ud398\uc5b4\uc758 \uc758\uacac\uc774 \uad1c\ucc2e\ub2e4\uace0 \uc0dd\uac01\ud558\uba74 \uc218\uc6a9 \ud6c4 \uac1c\uc120\uc744 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\uc5c8\ub294\ub370, \uc870\uae08 \ub354 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ud5a5\uc774 \uc788\ub2e4\uba74 \ub098\ub3c4 \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub9d0\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\ub098\ub3c4 \uc124\ub4dd\ud558\ub294 \ud798\uc744 \uae30\ub974\uace0, \ud398\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc744 \uc54c \uc218 \uc788\uace0, \uacb0\uacfc\ubb3c\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub098\uc624\uc9c0 \uc54a\uc744\uae4c? (\uace0\ubbfc \ub4e4\uc5b4\uc8fc\uc2e0 \ub9ac\ubdf0\uc5b4 \ud130\ud2c0\ud83d\udc22 \uac10\uc0ac\ud569\ub2c8\ub2e4.)\\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784** \\nPlayers\uac00 Position\uc744 \uc0dd\uc131\ud558\uace0 Player\uc758 \uc0dd\uc131\uc790\uc5d0 \ub123\uc5b4\uc8fc\uc5c8\ub2e4. \ud558\uc9c0\ub9cc \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ub828\ub41c \ucf54\uba58\ud2b8\uac00 \ub2ec\ub838\ub2e4.\\n\uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uc0dd\uac01\ud574 \ubcf4\ub2c8 Position\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uac74 Player\uae30 \ub54c\ubb38\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 Player\uac00 \ub2f4\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4. \\n\\n\uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud55c \ud328\ud134\uc73c\ub85c GRASP\uc758 Creator \ud328\ud134\uc774 \uc788\ub294\ub370 \ub2e4\uc74c\uc758 \uc694\uc18c\ub97c \ucd5c\ub300\ud55c \ub9cc\uc871\ud558\ub294 \ud074\ub798\uc2a4\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n- B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4.\\n- B\uac00 A\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4.\\n- B\uac00 A\uc758 \ucd08\uae43\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4. \\n\\n\uc2e4\uc81c\ub85c \uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud574\uc11c \uae4a\uc774 \uc0dd\uac01\ud558\uba74\uc11c \ucf54\ub529\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc2dc\uc57c\uac00 \ub113\uc5b4\uc9c4 \uac83 \uac19\ub2e4.\\n\\n**\ud328\ud0a4\uc9c0 \ubd84\ub9ac \uae30\uc900** \\n\ud328\ud0a4\uc9c0 \ubd84\ub9ac\uc5d0 \ub300\ud55c \ub098\ub9cc\uc758 \uae30\uc900\uc774 \uc544\uc9c1 \uba85\ud655\ud558\uc9c0 \uc54a\uc544 \uc9c8\ubb38\uc774 \ub4e4\uc5b4\uc640\ub3c4 \uba85\ud655\ud558\uac8c \ub2f5\ubcc0\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ub9c8\uc9c0\ub9c9 \uc81c\ucd9c \uc804\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub97c \ubd84\ub9ac\ud574 \ubd24\ub294\ub370, \uae30\uc900\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \uc88b\uc9c0 \uc54a\uc740 \uc120\ud0dd\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.\\n\ud604\uc7ac \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ud06c\uae30\uac00 \uadf8\ub807\uac8c \ud06c\uc9c0 \uc54a\uc73c\ub2c8, domain \ud328\ud0a4\uc9c0\uc5d0\uc11c \uc138\ubd80 \ud328\ud0a4\uc9c0\ub85c \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub420 \uac83 \uac19\ub2e4. \\n\\n**\uc0ac\uc6a9\ud558\ub294 \ucabd\uc5d0\uc11c \uc0dd\uac01\ud558\uae30 & \uc608\uce21\uac00\ub2a5\ud55c \ucf54\ub4dc \uc791\uc131\ud558\uae30** \\nPosition\uc5d0\uc11c \ub2e4\uc74c \uc704\uce58\ub098 \uc774\uc804 \uc704\uce58\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud5c8\uc6a9 \ubc94\uc704(0~19)\uac00 \ubc97\uc5b4\ub09c\ub2e4\uba74, \uc758\ubbf8 \uc5c6\ub294 \uac12\uc774 \ub4e4\uc5b4\uac04 Position\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\uc774\uac74 Position\uc744 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc744 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \ucf54\ub529\uc774\uc5c8\ub294\ub370, \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 0~19\uc758 \uac12\uc774 \ubcf4\uc7a5\ub418\uc5b4 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uac83\uc774\uae30 \ub54c\ubb38\uc774\ub2e4. \\n\ub530\ub77c\uc11c hasNext, hasPrevious\ub77c\ub294 \uc774\uc804 \uac12, \uc774\ud6c4 \uac12\uc774 \ubc94\uc704 \ub0b4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud558\uace0, \uae30\uc874\uc758 \uac12\uc744 \uac00\uc838\uc624\ub294 \uba54\uc11c\ub4dc\ub294 \ubc94\uc704\uac00 \ubc97\uc5b4\ub098\uba74 \uc608\uc678\ub97c \ub358\uc9c0\ub294 \ubc29\ud5a5\uc73c\ub85c \ud574\uacb0\ud558\uc600\ub2e4. \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n\ubc1d\uc740 \uae30\uc6b4\uc744 \uac00\uc9c0\uace0 \uc788\uace0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \uce5c\ud654\ub825\uc774 \uc88b\uc740 \uac83 \uac19\uc558\ub2e4. \\n\uc774\ubc88\uc5d0 \ud398\uc5b4 \ud560 \ub54c \ucee8\ub514\uc158 \uad00\ub9ac\ub97c \uc81c\ub300\ub85c \ubabb\ud574\uc11c \ub9ce\uc774 \ubbf8\uc548\ud588\ub2e4. \ub2e4\uc74c\uc5d0\ub294 \ucd5c\uc0c1\uc758 \ucee8\ub514\uc158\uc73c\ub85c \ud398\uc5b4\ub97c \uc900\ube44\ud574 \ubd10\uc57c\uaca0\ub2e4. \\n\uadf8\ub9ac\uace0 \uc6b0\uac00\ub791 \ud398\uc5b4\ub97c \ud558\uace0 \ub098\uc11c, \ub098\ub3c4 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \ub354 \uc798 \uc9c0\ub0b4\ubd10\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5b4 \uc870\uae08 \ub354 \uc6a9\uae30\ub97c \ub0b4 \uc7a1\ub2f4 \uc911\uc774\ub2e4! \\n\\n\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589\uc774 \uc798 \ub418\uc5c8\ub2e4. \\n\ub610\ud55c \ud398\uc5b4 \uc9c4\ud589\uc774 \ub290\ub9b0 \uac83 \uac19\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c \uc548\uc815\uc801\uc73c\ub85c \uc2dc\uac04 \uc548\uc5d0 \ubbf8\uc158\uc744 \uc644\ub8cc\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589 \uc18d\ub3c4\uc5d0 \ub300\ud574 \uc870\uae08 \ub354 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4!\\n\\n\ud56d\uc0c1 \uc9c0\ub098\uac08 \ub54c\ub9c8\ub2e4 \uc6c3\uc5b4\uc8fc\ub294\ub370, \ub098\ub3c4 \uc790\uc8fc \uc6c3\uc5b4\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc6c3\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uc0ac\ub78c\uc774 \ubc1d\uc544 \ubcf4\uc5ec\uc11c \ub108\ubb34 \uc88b\uc740 \uac83 \uac19\ub2e4!"},{"id":"racing-car-retrospective","metadata":{"permalink":"/racing-car-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","description":"1\ub2e8\uacc4//github.com/woowacourse/java-racingcar/pull/510","date":"2023-02-14T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 14\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.625,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","slug":"racing-car-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"unlisted":false,"prevItem":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","permalink":"/ladder-retrospective"},"nextItem":{"title":"Parameterized Tests","permalink":"/parameterized-tests"}},"content":":::note PR \ub9c1\ud06c \\n1\ub2e8\uacc4: https://github.com/woowacourse/java-racingcar/pull/510 \\n2\ub2e8\uacc4: https://github.com/woowacourse/java-racingcar/pull/538 \\n:::\\n\\n### \uc790\ub3d9\ucc28 \uacbd\uc8fc\\n\\n\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158\uc5d0\uc11c\ub294 \ub2e4\uc990\uacfc \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc6b0\ud14c\ucf54 \ub4e4\uc5b4\uc640\uc11c \uccab \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\uc774\ub77c \ub9ce\uc774 \ub5a8\ub838\uc9c0\ub9cc, \ub2e4\uc990\uc774 \ub300\ud654\ub97c \uc798 \uc774\ub04c\uc5b4\uc918 \ub108\ubb34 \uc990\uac70\uc6e0\ub2e4. \\n\\n\uccab\ub0a0\uc740 \uac04\ub2e8\ud788 \ucee8\ubca4\uc158\uacfc \ud658\uacbd\uc744 \uc124\uc815\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc84c\uace0 \ub2e4\uc74c \ub0a0\ubd80\ud130 \uc790\ub3d9\ucc28 \uacbd\uc8fc\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\uc2dc\uc791\uc740 \uac04\ub2e8\ud558\uac8c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud558\uace0, \uc5b4\ub5bb\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud560\uc9c0 \uac19\uc774 \uace0\ubbfc\ud588\ub2e4. \\n\\n\uc2dc\uc791\ud558\uae30 \uc804 \uc544\ub798\uc640 \uac19\uc774 mermaid\ub97c \uc774\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc5d0 \ub300\ud574\uc11c \uac04\ub2e8\ud55c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \ub9cc\ub4e4\uace0 \uc2dc\uc791\ud588\ub2e4. \\nmermaid\ub294 \ucf54\ub4dc\ub85c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \uc0dd\uc131 \ud574\uc8fc\ub294 \ub3c4\uad6c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc774 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.\\n\\n- \ucf54\ub4dc \uae30\ubc18\uc774\ub77c \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \uc0dd\uac01\ud55c \uac83\uc744 \uc2dc\uac01\ud654\ud560 \uc218 \uc788\ub2e4. \\n- github\uc5d0\uc11c mermaid\ub97c \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \ucf54\ub4dc\ub97c \uc774\ud574\ud560 \uc218 \uc788\ub294 \ubd80\uac00\uc801\uc778 \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n```mermaid\\n---\\ntitle: \uc790\ub3d9\ucc28 \uacbd\uc8fc \uccab \ub9ac\ubdf0 \uc694\uccad\uc2dc \uad6c\uc870\\n---\\ngraph TD\\n Cars --\x3e Car\\n Car --\x3e Name\\n Car --\x3e Position\\n RacingGame --\x3e Count\\n RacingGame --\x3e NumberGenerator\\n RacingGame --\x3e Cars\\n RacingCarController --\x3e RacingGame\\n RandomNumberGenerator -.-> NumberGenerator\\n RacingCarController --\x3e InputView\\n InputView --\x3e InputValidator\\n RacingCarController --\x3e OutputView\\n```\\n\\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \ub370 \ud070 \uc5b4\ub824\uc6c0\uc774 \uc788\uc9c0\ub294 \uc54a\uc558\uace0, \ud398\uc5b4\ub97c \ub9c8\uce58\uae30 \uc804 \uc11c\ub85c \uace0\ubbfc\ub418\ub294 \ubd80\ubd84\uc744 \uc815\ub9ac\ud588\uc744 \ub54c \uc88b\uc558\ub2e4.\\n\\n\ud398\uc5b4\ud558\uba74\uc11c \uc798\ud588\ub2e4\uace0 \uc0dd\uac01\ud588\ub358 \uc810\uc740 \uc11c\ub85c\uc758 \uc0dd\uac01\uacfc \ub9ac\ubdf0 \ubc1b\uc740 \uac83\uc744 \uacf5\uc720\ud55c \uac83\uc774\ub2e4. \\n\ub9ac\ud329\ud130\ub9c1\uc744 \uc5b4\ub5bb\uac8c \ud588\ub294\uc9c0? \uc774\ub7f0 \ub9ac\ubdf0\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \uc0dd\uac01\ud558\ub294\uc9c0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c8 \uc218 \uc788\uc5c8\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ub9ac\ud329\ud130\ub9c1\uc774 \ub05d\ub09c \ud6c4 \uba54\uc11c\ub4dc\uba85, \ud14c\uc2a4\ud2b8\uc2dc \ucd9c\ub825\ud558\ub294 \uba54\uc2dc\uc9c0\uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\uac00 \ub9ce\uc774 \ub2ec\ub838\ub2e4. \\n\uac1d\uccb4\uac00 \uc5b4\ub5a4 \ucc45\uc784\uacfc \uc5ed\ud560\uc744 \uac00\uc9c0\ub294\uc9c0 \uc0dd\uac01\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uba85\ud655\ud55c \uba54\uc11c\ub4dc\uba85\uc744 \uc791\uc131\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n\ud3c9\uc18c\uc5d0 \ud504\ub85c\uadf8\ub798\ubc0d \uc774\uc57c\uae30\uac00 \uc544\ub2cc \ub2e4\ub978 \uc8fc\uc81c\ub85c \uc774\uc57c\uae30\ud558\uba74 \uc798 \ub4e4\uc73c\ub824\uace0 \ud558\ub294 \ud3b8\uc774\uc9c0\ub9cc \\n\ub0b4\uac00 \uc88b\uc544\ud558\ub294 \uc8fc\uc81c, \uad00\uc2ec\uac00\ub294 \uc8fc\uc81c\uc778 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub97c \ud560 \ub550 \ub9d0\uc774 \ub9ce\uc544\uc9c4\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130\ub294 \ub354 \ub9ce\uc740 \uc2dc\uac04\uc744 \ud398\uc5b4\uc758 \uc758\uacac\uacfc \uc774\uc57c\uae30\ub97c \ub4e3\ub294 \uacf3\uc5d0 \uc0ac\uc6a9\ud574\uc57c\uaca0\ub2e4.\\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**Assertions extracting**\\n\\n\uacb0\uacfc \ub0b4\ubd80\uc5d0 \uc788\ub294 \uac12\uc744 \ud655\uc778\ud558\uace0 \uc2f6\uc744 \ub54c extracting \ud0a4\uc6cc\ub4dc\ub97c \uc774\uc6a9\ud574\uc11c \ub0b4\ubd80\uc758 \uac12\uc744 \uac80\uc99d\ud560 \uc218 \uc788\ub2e4. \\n\uc774\uc804\uc5d0\ub294 \ud544\uc694\uc5d0 \ub530\ub77c stream\uc744 \uc774\uc6a9\ud558\uc5ec \uac80\uc99d\ud560 \uac12\uc744 \uc0dd\uc131\ud588\uc9c0\ub9cc, \ud574\ub2f9 \ubc29\ubc95\uc744 \uc774\uc6a9\ud574\uc11c \uc808\ucc28\ub97c \uc904\uc77c \uc218 \uc788\uc5c8\ub2e4.\\n\\n```java\\n@Test\\nvoid extracting() {\\n final Cars cars = new Cars(List.of(\\"car1\\", \\"car2\\"));\\n\\n assertThat(cars.getCars())\\n .extracting(Car::getName)\\n .containsExactly(\\"car1\\", \\"car2\\");\\n}\\n```\\n\\n---\\n\\n\uc544\ub798\ub294 \ub9ac\ubdf0\uc5b4\ub2d8\uacfc \ub300\ud654\ub97c \ub098\ub204\uba74\uc11c \uc5bb\uc740 \ub2f5\ubcc0 + \ub098\uc758 \uc758\uacac\uc774\ub2e4.\\n\\n**\uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8**\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc0c1\uc774 \uac80\uc99d\ub41c \uac83\uc774\ub77c\uba74 \uc791\uc131\ud558\uc9c0 \uc54a\uac70\ub098, \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uc791\uc131\ud55c\ub2e4. \\n\uc774\uac74 \uac1c\uc778\uc801\uc778 \uc0dd\uac01\uc774\uc9c0\ub9cc \ub0b4\uac00 \uc548\uc815\uac10\uc774 \ub4e4 \uc218 \uc788\uc744 \uc815\ub3c4\ub85c \ucd9c\ub825 \ubc94\uc704 \ub0b4\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud558\ub294\uc9c0 \uc815\ub3c4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?\\n\\n**\ub2e8\uc21c \uc704\uc784\uc744 \ud558\ub294 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8**\\n\\n\uc704\uc784\uc774\ub77c\ub294 \uac83\uc740 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4. \\n\ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc99d\ud558\ub294 \uac83\ubcf4\ub2e4 \uacb0\uacfc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\ub2e8\uc21c\ud788 \uc704\uc784\ub9cc \ud558\ub294 \ud14c\uc2a4\ud2b8\uc758 \uacbd\uc6b0 \uacb0\uacfc\ub97c \uac80\uc99d\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc911\ubcf5\ub418\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \uc911\ubcf5\ub41c \ud14c\uc2a4\ud2b8\ub97c \uc904\uc774\uae30 \uc704\ud574 \ub0b4\ubd80\uc758 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0 \uac80\uc99d\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\ub294 \uac83\uc744 \uc54c\uac8c \ub418\uc5c8\uc9c0\ub9cc \\n\uc548\uc815\uc801\uc73c\ub85c \uacb0\uacfc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc778 \uac83 \uac19\ub2e4.\\n\\n**\ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c getter \uc0ac\uc6a9**\\n\\n\ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\ub85c \ub3c4\uba54\uc778\uc5d0 \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc740 \uc88b\uc9c0 \ubabb\ud558\ub2e4. \\n\ud544\uc694\uc758 \uacbd\uc6b0 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc9c0\ub9cc, \uae30\uc874\uc5d0 \uc788\ub294 \uba54\uc11c\ub4dc\ub4e4\uc744 \ud65c\uc6a9\ud574\ubcf4\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4. \\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub9e4\uc6b0 \ub3d9\uc758\ud558\uace0, \uc55e\uc73c\ub85c\ub3c4 \ucd5c\ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \ucf54\ub4dc\ub97c \ub3c4\uba54\uc778\uc5d0 \uc791\uc131\ud558\uc9c0 \uc54a\uc744 \uac83 \uac19\ub2e4.\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n\uc9c8\ubb38\uc774\ub098 \uc0dd\uac01\ud560 \uc810\uc774 \uc788\uc744 \ub54c \ub9e4\uc6b0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uac83 \uac19\uc558\ub2e4. \\n\uc0dd\uac01\uc744 \uc815\ub9ac\ud55c \ud6c4 \uc790\uc2e0\uc758 \uc758\uacac\uc744 \uba85\ub8cc\ud558\uac8c \uc804\ub2ec\ud574\uc8fc\uc5c8\ub2e4. \\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc2dd\uc744 \ud6a8\uc728\uc801\uc73c\ub85c \uc2b5\ub4dd\ud55c\ub2e4. \\n\ub09c \uc0dd\uac01\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc740 \ucc44\ub85c \ub0b4\ubc84\ub824 \ub454 \uc595\uc740 \uc9c0\uc2dd\uc774 \ub9ce\uc740 \uac83 \uac19\ub2e4. (\uc774\ub7f0 \uac83\ub3c4 \uc544\ub294 \uac83\uc774\ub77c\uace0 \ud560 \uc218 \uc788\uc744\uae4c?) \\n\uc55e\uc73c\ub85c \uc870\uae08 \ub354 \uba38\ub9bf\uc18d\uc5d0\uc11c \uc815\ub9ac\ud558\uace0, \ubb38\uc81c\uc5d0 \ub300\ud574 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \ub298\ub824\uc57c\uaca0\ub2e4.\\n\\n\uac1c\ubc1c\uc5d0 \uc5f4\uc815\uc744 \uac00\uc9c4 \uac8c \ub290\uaef4\uc9c4\ub2e4. \\n\ub098\ub3c4 \uac1c\ubc1c\uc744 \uc88b\uc544\ud558\uc9c0\ub9cc, \ucd5c\uadfc\uc5d0\ub294 \uc758\uc9c0\uac00 \uc57d\ud574\uc84c\uc5c8\ub2e4. \\n\uc5f4\uc815\uc774 \uac00\ub4dd\ud55c \uc0ac\ub78c\uc744 \ub9cc\ub098\ub2c8 \ub098\ub3c4 \uc5f4\uc815\uc801\uc778 \uc0ac\ub78c\uc774 \ub418\ub294 \uac83 \uac19\ub2e4.\\n\\n\uce6d\ucc2c\uc744 \ub9ce\uc774 \ud574\uc900\ub2e4. \ub2e8\uc21c\ud788 \ub9ce\uc774 \ud574\uc8fc\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc9c4\uc2ec\uc744 \ub2f4\uae34 \uce6d\ucc2c\uc744 \ud574\uc92c\ub2e4. \\n\uce6d\ucc2c\uc740 \uace0\ub798\ub3c4 \ucda4\ucd94\uac8c \ud558\ub358\uac00? \\n\uadf8\ub798\uc11c \uc990\uac70\uc6b4 \ub9c8\uc74c\uc73c\ub85c \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud588\uc5c8\ub358 \uac83 \uac19\ub2e4.\\n\\n\uc5b4\ub5a4 \uc774\uc720 \ub54c\ubb38\uc778\uc9c0 \ubaa8\ub974\uaca0\uc9c0\ub9cc \uac19\uc774 \ud398\uc5b4\ud558\ub294\ub370 \ud3b8\ud55c \ub9c8\uc74c\uc774 \ub4e4\uc5c8\ub2e4. \\n\uc774\uac74 \ubc14\ub85c \ubc30\uc6b8 \uc218 \uc5c6\uc9c0\ub9cc. \\n\ub098\ub3c4 \uac19\uc774 \uc77c\ud560 \ub54c \ud3b8\ud55c \uc0ac\ub78c, \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub418\uae30 \uc704\ud574 \uae4a\uc774 \uace0\ubbfc\ud574\ubd10\uc57c\uaca0\ub2e4."},{"id":"parameterized-tests","metadata":{"permalink":"/parameterized-tests","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-12-Parameterized Tests.mdx","source":"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx","title":"Parameterized Tests","description":"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.","date":"2023-02-12T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 12\uc77c","tags":[{"label":"Java","permalink":"/tags/java"}],"readingTime":3.17,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Parameterized Tests","slug":"parameterized-tests","tags":["Java"]},"unlisted":false,"prevItem":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","permalink":"/racing-car-retrospective"},"nextItem":{"title":"IntelliJ \uc124\uc815","permalink":"/intellij-settings"}},"content":"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4. \\n\uc774 \ub54c `@ParameterizedTest`\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e8\uc77c \ud14c\uc2a4\ud2b8\ub97c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \ubc88 \ubc18\ubcf5\ud560 \uc218 \uc788\ub2e4.\\n\\n## Argument Sources\\n\\n`@ParameterizedTest`\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 Source \uc560\ub178\ud14c\uc774\uc158\uc774 \ud544\uc694\ud558\ub2e4. \\nJUnit\uc774 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c Source\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0, \ud14c\uc2a4\ud2b8\uc5d0 \ub9de\ucdb0 \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### Value Source\\n\\n\uac12\uc744 \uc774\uc6a9\ud558\uc5ec \uc81c\uacf5\ud558\ub294 \ud615\ud0dc\ub85c, \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4. \\n- short, int, long, float, double\\n- byte, char, boolean, String, Class \\n\\n```java\\n@ParameterizedTest\\n@ValueSource(ints = {1, 100, Integer.MAX_VALUE})\\nvoid valueTest(final int value) {\\n Assertions.assertThat(value).isPositive();\\n}\\n```\\n\\n### Null & Empty Source\\n\\nnull \uac12, \ube48 \uac12\uc744 \uc81c\uacf5\ud55c\ub2e4. \\nEmpty Source\uc758 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc5d0 \ud55c\ud574 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n- String\\n- java.util.List, java.util.Set, java.util.Map\\n- primitive arrays \u2014 ex) int[]\\n- object arrays \u2014 ex) String[]\\n\\n```java\\n@ParameterizedTest\\n@NullAndEmptySource\\nvoid nullAndEmptyTest(final String value) {\\n Assertions.assertThat(value).isNullOrEmpty();\\n}\\n```\\n\\n### Enum Source\\n\\nEnumSource\ub97c \uc774\uc6a9\ud558\uc5ec Enum \ub610\ud55c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\nenum Day {\\n MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\\n}\\n\\n@ParameterizedTest\\n@EnumSource(Day.class)\\nvoid enumTest(final Day day) {\\n assertThat(day).isInstanceOf(Day.class);\\n}\\n```\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 mode \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b9\uc9d5 Enum\uc744 \uc81c\uc678\ud558\uac70\ub098, \ud3ec\ud568\uc2dc\ud0ac \uc218 \uc788\ub2e4. (default: Mode.Include)\\n\\n```java\\n@ParameterizedTest\\n@EnumSource(value = Day.class, names = {\\"SATURDAY\\", \\"SUNDAY\\"}, mode = Mode.EXCLUDE)\\nvoid enumTest(final Day day) {\\n // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\\n assertThat(day).isInstanceOf(Day.class);\\n}\\n```\\n\\n### CSV Source\\n\\ncsv \ud615\uc2dd\uc758 \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud55c\ub2e4. \\n\uad6c\ubd84\uc790\uc758 \uae30\ubcf8\uac12\uc740 \uc27c\ud45c(,)\ub85c \uad6c\ubd84\uc790\ub97c \ubcc0\uacbd\ud558\uace0 \uc2f6\uc744 \ub550 delimeter \uac12\uc744 \ub530\ub85c \uc804\ub2ec\ud558\uc5ec \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\uac1c\uc778\uc801\uc73c\ub85c 2\uac1c \uc815\ub3c4\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ud558\ub294 \uacbd\uc6b0 CsvSource\ub97c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n```java\\n@ParameterizedTest\\n@CsvSource({\\"1,1\\", \\"2,4\\", \\"3,9\\", \\"4,16\\"})\\nvoid csvTest(final int number, final int result) {\\n assertThat(number * number).isEqualTo(result);\\n}\\n```\\n\\n### Method Source\\n\\n\ubcf5\uc7a1\ud55c \ud0c0\uc785\uc758 \uac12\uc744 \uc804\ub2ec\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\n\uba54\uc11c\ub4dc\uba85\uc744 \uc785\ub825\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4. \\n\uba54\uc11c\ub4dc\uba85\uc744 \ub530\ub85c \uc785\ub825\ud558\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uba85\uacfc \ub3d9\uc77c\ud55c static \uba54\uc11c\ub4dc\uac00 \uc9c0\uc815\ub41c\ub2e4.\\n\\n```java\\n@ParameterizedTest\\n@MethodSource\\nvoid methodTest(final List numbers, final int count) {\\n assertThat(numbers).hasSize(count);\\n}\\n\\nprivate static Stream methodTest() {\\n return Stream.of(\\n Arguments.of(List.of(1), 1),\\n Arguments.of(List.of(1, 2), 2),\\n Arguments.of(List.of(1, 2, 3), 3)\\n );\\n}\\n```\\n\\n### ETC.\\n\\n\uc704\uc5d0\uc11c \uc5b8\uae09\ud55c \ubc29\ubc95 \uc774\uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ubc29\ubc95\uc73c\ub85c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n- CSV \ud30c\uc77c\uc744 \uc774\uc6a9\ud55c CsvFileSource\\n- ArgumentsProvider \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \uc774\uc6a9\ud558\ub294 ArgumentsSource\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n- [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5)"},{"id":"intellij-settings","metadata":{"permalink":"/intellij-settings","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx","source":"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx","title":"IntelliJ \uc124\uc815","description":"Import \uc790\ub3d9 \uc801\uc6a9","date":"2023-01-30T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 30\uc77c","tags":[{"label":"IntelliJ","permalink":"/tags/intelli-j"}],"readingTime":0.465,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"IntelliJ \uc124\uc815","slug":"intellij-settings","tags":["IntelliJ"]},"unlisted":false,"prevItem":{"title":"Parameterized Tests","permalink":"/parameterized-tests"},"nextItem":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null"}},"content":"### Import \uc790\ub3d9 \uc801\uc6a9\\n\\nPrefrences > Editor > General > Auto Import > Add unambiguous imports on the fly\\n\\n![auto-import](./auto-import.png)\\n\\n### \uc800\uc7a5\uc2dc \ub3d9\uc791\\n\\nPrefrences > Tools > Actions on Save\\n\\n![actions-on-save](./actions-on-save.png)\\n\\nReformat Code: Code Reformmating\\n\\nOptimize imports: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 Import \uc81c\uac70\\n\\nRearrange: Code Style > Arrangement \uc124\uc815 \uae30\ubc18 \ucf54\ub4dc \uc7ac\uc815\ub82c\\n\\n### \uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9\\n\\nPrefrences > Editor > Code Style > Java > Code Generation > Final Modifier\\n\\n![final-modifier](./final-modifier.png)"},{"id":"kotlin-null","metadata":{"permalink":"/kotlin-null","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx","source":"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx","title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","description":"nullable \ud0c0\uc785","date":"2023-01-16T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 16\uc77c","tags":[{"label":"Kotlin","permalink":"/tags/kotlin"}],"readingTime":4.225,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","slug":"kotlin-null","tags":["Kotlin"]},"unlisted":false,"prevItem":{"title":"IntelliJ \uc124\uc815","permalink":"/intellij-settings"},"nextItem":{"title":"JSR-310","permalink":"/jsr-310"}},"content":"import Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n### nullable \ud0c0\uc785\\n\\n\ucf54\ud2c0\ub9b0\uc740 `NullPointerException` \uc608\uc678\ub97c \ucd5c\ub300\ud55c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 \ud0c0\uc785 \uc2dc\uc2a4\ud15c\uc774 \uc124\uacc4\ub418\uc5b4 \uc788\ub2e4. \\n\uc774\ub294 \uc2e4\ud589 \uc2dc\uc810\uc774 \uc544\ub2cc \ucef4\ud30c\uc77c \uc2dc \ubbf8\ub9ac \uc624\ub958\uac00 \ubc1c\uc0dd\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub294 \ubd80\ubd84\uc744 \ubbf8\ub9ac \uac10\uc9c0\ud558\uc5ec NPE \ubc1c\uc0dd\uc758 \uac00\ub2a5\uc131\uc744 \uc904\uc5ec\uc900\ub2e4.\\n\\n\ucf54\ud2c0\ub9b0\uc758 \uacbd\uc6b0 nullable \ud0c0\uc785\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4.\\n\\n```kotlin\\nval number: Int?\\n```\\n\\n\ud0c0\uc785 \ub4a4\uc5d0 `?`\ub97c \ubd99\uc5ec \ud574\ub2f9 \uac12\uc774 null\uc774 \ub420 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4. \\n\ub9cc\uc57d `?`\ub97c \ubd99\uc774\uc9c0 \uc54a\uc744 \ub54c null\uc744 \ubc1b\ub294 \uacbd\uc6b0 \ucef4\ud30c\uc77c \uc2dc \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4.\\n\\n### `?.` Safe Calls \uc5f0\uc0b0\uc790\\n\\n\uc790\ubc14\uc5d0\uc11c NPE\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 null\uc744 \ucc98\ub9ac\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c\ub294 \ubd84\uae30\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.\\n\\n\ucf54\ud2c0\ub9b0\uc740 \uc548\uc804\ud55c \ud638\ucd9c \uc5f0\uc0b0\uc790\uc778 `?.` \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ucc38\uc870 \uac12\uc774 null\uc774 \uc544\ub2d0 \uacbd\uc6b0\uc5d0\ub9cc \uba54\uc11c\ub4dc \ud638\ucd9c\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\ucc38\uc870 \uac12\uc774 null\uc778 \uacbd\uc6b0 \uba54\uc11c\ub4dc \ud638\ucd9c\uc774 \ubb34\uc2dc\ub418\uace0, null\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\\n\\n\\n\\n```java\\npublic String repeat(String word) {\\n if (word == null) {\\n return null;\\n }\\n return word.repeat(2);\\n}\\n```\\n\\n\\n\\n\\n```kotlin\\nfun repeat(word: String?): String? {\\n return word?.repeat(2)\\n}\\n```\\n\\n\\n\\n\\n### `?:` \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\\n\\n\ucc38\uc870\ud558\ub824\ub294 \uac12\uc774 null\uc77c \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud558\uace0 \uc2f6\uc744 \ub54c\ub294 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c? \\n\ucf54\ud2c0\ub9b0\uc740 null\uc774 \uc544\ub2cc \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \ub54c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4.\\n\\n\\n\\n\\n```java\\npublic String stringSafe(String word) {\\n if (word == null) {\\n return \\"\\";\\n }\\n return word;\\n}\\n```\\n\\n\\n\\n\\n```kotlin\\nfun stringSafe(word: String?): String {\\n return word ?: \\"\\"\\n}\\n```\\n\\n\\n\\n\\n\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 throw\ub3c4 \uc2dd\uc774\uae30 \ub54c\ubb38\uc5d0 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 \uc0ac\uc6a9\uc790 \uc815\ubcf4\uac00 \uc788\ub294 \uc800\uc7a5\uc18c\uc5d0 \ucc3e\ub294 \uc0ac\uc6a9\uc790\uac00 \uc5c6\ub294 \uacbd\uc6b0 \uc544\ub798\uc640 \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n```kotlin\\nuserRepository.findByName(name) ?: throw IllegalArgumentException()\\n```\\n\\n### `!!` \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790\\n\\n!! \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud55c\ub2e4\uba74 \uac15\uc81c\ub85c \uc5b4\ub5a4 \uac12\uc774\ub4e0 non-nullable \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc null\uc778 \uac12\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4\uba74 NPE\uac00 \ubc1c\uc0dd\ud558\uac8c \ub41c\ub2e4. \\n\uc77c\ubc18\uc801\uc778 \uacbd\uc6b0\uc5d0\ub294 !! \uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc704\ud5d8\ud558\ub2e4. \\n\uc0ac\uc6a9\ud558\uae30 \uc27d\uc9c0\ub9cc, \ub9ac\uc2a4\ud06c\uac00 \ud06c\uace0 \ud639\uc2dc\ub098 \ud574\ub2f9 \uac12\uc774 \ucd94\ud6c4\uc5d0\ub294 null\uc774 \ub420 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc591\ud574\uc57c \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.\\n\\n```kotlin\\nval length: Int = word!!.length\\n```\\n\\n### `as?` \uc548\uc804\ud55c \uce90\uc2a4\ud305\\n\\n\ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \ub54c \uc9c0\uc815\ud55c \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc5c6\ub2e4\uba74 `ClassCastException`\uc774 \ubc1c\uc0dd\ud55c\ub2e4. \\n\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 as \ub4a4\uc5d0 ?\ub97c \ubd99\uc5ec \uc548\uc804\ud558\uac8c \ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ubbf8\ub9ac \ubcc0\ud658 \uac00\ub2a5\ud55c \ud0c0\uc785\uc778\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uace0, \uc548\uc804\ud558\uac8c \ud0c0\uc785\uc744 \ubcc0\ud658 \ud560 \uc218 \uc788\ub2e4. \\n\\n\ud0c0\uc785 \ubcc0\ud658\uc774 \ubd88\uac00\ub2a5 \ud560 \uacbd\uc6b0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uace0 null\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n```kotlin\\nval value: Int? = something as? Int\\n```\\n\\n### List\uc5d0\uc11c\uc758 null \ucc98\ub9ac\\n\\nList\uc5d0\ub294 null\uc774 \uc544\ub2cc \uac12\ub9cc \ubc18\ud658\ud558\ub294 `filterNotNull` \uc720\ud2f8\ub9ac\ud2f0 \uba54\uc11c\ub4dc\ub97c \uc81c\uacf5\ud55c\ub2e4.\\n\\n```kotlin\\nval foodsWithNull: List = listOf(\\"Pizza\\", \\"Cheese\\", null, \\"Potato\\")\\nval foods = foodsWithNull.filterNotNull()\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n- [Kotlin in Action](https://product.kyobobook.co.kr/detail/S000001804588)\\n- [Effective Kotlin Item 8](https://product.kyobobook.co.kr/detail/S000001033129)\\n- [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin/null-safety)\\n- [Kotlin NullSafety](https://kotlinlang.org/docs/null-safety.html)"},{"id":"jsr-310","metadata":{"permalink":"/jsr-310","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-08-JSR-310.mdx","source":"@site/blog/2023-1/2023-01-08-JSR-310.mdx","title":"JSR-310","description":"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API","date":"2023-01-08T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 8\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Time","permalink":"/tags/time"}],"readingTime":1.685,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"JSR-310","slug":"jsr-310","tags":["Java","Time"]},"unlisted":false,"prevItem":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null"},"nextItem":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation"}},"content":"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API \\nISO-8601\uc744 \uae30\ubc18\uc73c\ub85c \uc791\uc131 \\n\uc124\uacc4 \ubaa9\ud45c \u2192 \ubd88\ubcc0, Fluent API, \uba85\ud655\ud558\uace0 \uba85\uc2dc\uc801, \ud655\uc7a5 \uac00\ub2a5\uc131\\n\\n:::note ISO-8601\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc5d0 \uad00\ub828\ub41c \ub370\uc774\ud130\ub97c \ub2e4\ub8e8\ub294 \uad6d\uc81c \ud45c\uc900\\n\\n:::\\n\\n### LocalDate, LocalTime, LocalDateTime\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4\\n\\n### Instant\\n\\n\uc720\ub2c9\uc2a4 \uc2dc\uac04(1970-01-01, 00:00:00 UTC) \uae30\uc900\uc73c\ub85c \ud2b9\uc815 \uc9c0\uc810\uae4c\uc9c0\uc758 \uc2dc\uac04\uc744 \ucd08\ub85c \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4 \\n\uae30\uacc4\uc758 \uad00\uc810\uc5d0\uc11c \uc2dc\uac04 \ud45c\ud604\\n\\n### Duration, Period\\n\\n\uac04\uaca9\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4\\n\\n### TemporalAdjusters\\n\\n\ubcf5\uc7a1\ud55c \ub0a0\uc9dc \uc870\uc815\uc774 \ud544\uc694\ud560 \ub54c \uc0ac\uc6a9 \\n\ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uc5ec \ucee4\uc2a4\ud140 TemporalAdjuster\ub97c \uad6c\ud604 \uac00\ub2a5\\n\\n```java\\n@FunctionalInterface\\npublic interface TemporalAdjuster {\\n Temporal adjustInto(Temporal temporal);\\n}\\n```\\n\\n### DateTimeFormatter\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04 \ud3ec\ub9f7 \ud074\ub798\uc2a4 \\n\ud2b9\uc815 \ub0a0\uc9dc \ud328\ud134\uc774\ub098, DateTimeFormatterBuilder\ub97c \uc774\uc6a9\ud574\uc11c \ucee4\uc2a4\ud140\ud55c \ud3ec\ub9f7\uc744 \uc0dd\uc131 \uac00\ub2a5\\n\\n### ZoneId, ZoneOffset\\n\\nZoneId\ub294 \uc9c0\uc5ed ID\ub294 `\u2018\uc9c0\uc5ed/\ub3c4\uc2dc\u2019` \ud615\uc2dd, ZoneOffset\uc740 \uc2dc\ucc28 UTC \uae30\uc900 \uace0\uc815\ub41c \uc2dc\uac04 \ucc28\uc774 \uc774\uc6a9 \\nZoneId\uc758 \uacbd\uc6b0 IANA Time Zone Database\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc9c0\uc5ed \uc9d1\ud569 \uc815\ubcf4 \uc0ac\uc6a9\\n\\n```java\\nInstant instant = Instant.now();\\nLocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n- [\ubaa8\ub358 \uc790\ubc14 \uc778 \uc561\uc158](https://product.kyobobook.co.kr/detail/S000001810171)\\n- [Java\uc758 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API](https://d2.naver.com/helloworld/645609)\\n- [ISO-8601](https://www.w3.org/TR/NOTE-datetime)\\n- [JSR-310 Spec](https://download.oracle.com/otn-pub/jcp/date_time-0.2-edr-oth-JSpec/date_time-0_2-edr-spec.pdf?AuthParam=1673171124_74a718be92efe4911c6977c02965aff4)\\n- [Temporal Adjuster](https://www.baeldung.com/java-temporal-adjuster)\\n- [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)"},{"id":"the-essence-of-object-orientation","metadata":{"permalink":"/the-essence-of-object-orientation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx","source":"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx","title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","description":"\ucc45 \uc815\ubcf4","date":"2023-01-07T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 7\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":5.415,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","slug":"the-essence-of-object-orientation","tags":["Book"]},"unlisted":false,"prevItem":{"title":"JSR-310","permalink":"/jsr-310"},"nextItem":{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574 \\n> \uc870\uc601\ud638\\n> \\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\uc870\uc601\ud638\ub2d8\uc758 \uc624\ube0c\uc81d\ud2b8\ub97c \uc77d\uace0 \ub098\uc11c \ub2e4\uc2dc \ud55c \ubc88 \uc77d\uc5b4\ubcf4\uc558\ub2e4. \\n\uc544\uc9c1 \uc774\ud574\uac00 \uc548\ub418\ub294 \ubd80\ubd84\uc774 \ub9ce\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ud56d\uc0c1 \uc0c8\ub85c\uc6c0\uc744 \ub290\ub080\ub2e4. \\n\ub354\ud560 \ub098\uc704 \uc5c6\uc774 \ud73c\ub96d\ud55c \uac1d\uccb4\uc9c0\ud5a5 \ucc45\uc774\uace0, \uc870\uae08 \ub354 \uacf5\ubd80\ud558\uace0 \ub2e4\uc2dc \uc77d\uc5b4\ubd10\uc57c\ub420 \uac83 \uac19\ub2e4. \\n\\n\ucee4\ud53c \uc804\ubb38\uc810, \uc9c0\ud558\ucca0 \ub178\uc120\ub3c4, \uc774\uc0c1\ud55c \ub098\ub77c\uc758 \uc5d8\ub9ac\uc2a4\ub97c \uc608\uc2dc\ub85c \ub4e0 \uc124\uba85\uc774 \ub108\ubb34 \uc88b\uc558\uace0 \\n\uc88b\uc740 \ub0b4\uc6a9\uc744 \ub2f4\uace0 \uc788\uc9c0\ub9cc \uadf8\ub807\ub2e4\uace0 \ub108\ubb34 \ubb34\uac81\uc9c0 \uc54a\uc544 \uac00\ubccd\uac8c \uc77d\uae30\ub3c4 \uc88b\uc740 \uac83 \uac19\ub2e4.\\n\\n### \ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173\\n\\n\ud611\ub825\uc744 \ub2e8\uc21c\ud558\uac8c \ub9cc\ub4e0\ub2e4.\\n\\n- \uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604 \u2192 \ud611\ub825\uc758 \ubcf5\uc7a1\ud568 \uc800\ud558\\n- \ucc45\uc784\uc758 \ucd94\uc0c1\ud654\\n\\n\uc678\ubd80\uc640 \ub0b4\ubd80\ub97c \uba85\ud655\ud558\uac8c \ubd84\ub9ac\ud55c\ub2e4.\\n\\n- \uc694\uccad\ud558\ub294 \uac1d\uccb4\uac00 \ubab0\ub77c\ub3c4 \ub418\ub294 \ubd80\ubd84\uc774 \ucea1\uc290\ud654\ub428\uc73c\ub85c \uc778\ud130\ud398\uc774\uc2a4\uc640 \uad6c\ud604\uc758 \ubd84\ub9ac\\n\\n\ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub0b4\ubd80\uc801\uc778 \ubc29\ubc95\uc744 \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 \uc678\ubd80\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub294\ub2e4.\\n\\n- \ubcc0\uacbd\uc758 \ud30c\uae09\ud6a8\uacfc\ub97c \uac1d\uccb4 \ub0b4\ubd80\ub85c \ucea1\uc290\ud654 \u2192 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \uac1d\uccb4\uc640\uc758 \uacb0\ud569\ub3c4 \uc800\ud558\\n\\n\ud611\ub825\uc758 \ub300\uc0c1\uc744 \ub2e4\uc591\ud558\uac8c \uc120\ud0dd\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\uc131\uc744 \uc81c\uacf5\ud55c\ub2e4.\\n\\n- \uc720\uc5f0\ud55c \uc124\uacc4 \u2192 \uc7ac\uc0ac\uc6a9\uc131 \uc99d\uac00\\n\\n\uac1d\uccb4\uc758 \uc5ed\ud560\uc744 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc9c4\ub2e4.\\n\\n- \uc751\uc9d1\ub3c4\ub97c \ub192\uc740 \uc0c1\ud0dc\ub85c \uc720\uc9c0\\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc758 \ubaa9\ud45c\ub294 \uc2e4\uc138\uacc4\ub97c \ubaa8\ubc29\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\\n\uc624\ud788\ub824 \uc0c8\ub85c\uc6b4 \uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc790\uc758 \uc5ed\ud560\uc740 \ub2e8\uc21c\ud788 \uc2e4\uc138\uacc4\ub97c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc548\uc73c\ub85c \uc62e\uaca8 \ub2f4\ub294 \uac83\uc774 \uc544\ub2c8\ub77c \uace0\uac1d\uacfc \uc0ac\uc6a9\uc790\ub97c \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\ub294 \uc2e0\uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\\np.21\\n> \\n\\n> \uacfc\uac70\uc758 \uc804\ud1b5\uc801\uc778 \uac1c\ubc1c \ubc29\ubc95\uc740 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uc5c4\uaca9\ud558\uac8c \uad6c\ubd84\ud55c\ub2e4.\\n\uc774\uc5d0 \ubc18\ud574 \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c\ub294 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uac1d\uccb4\ub77c\ub294 \ud558\ub098\uc758 \ud2c0 \uc548\uc5d0 \ud568\uaed8 \ubb36\uc5b4 \ub193\uc74c\uc73c\ub85c\uc368 \uac1d\uccb4\uc758 \uc790\uc728\uc131\uc744 \ubcf4\uc7a5\ud55c\ub2e4.\\n\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub85c \uad6c\uc131\ub41c \uacf5\ub3d9\uccb4\ub294 \uc720\uc9c0 \ubcf4\uc218\uac00 \uc27d\uace0 \uc7ac\uc0ac\uc6a9\uc774 \uc6a9\uc774\ud55c \uc2dc\uc2a4\ud15c\uc744 \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uac00\ub2a5\uc131\uc744 \uc81c\uc2dc\ud55c\ub2e4.\\np.33\\n> \\n\\n> **\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubcf8\uc9c8**\\n> \\n> \\n> \uc2dc\uc2a4\ud15c\uc744 \uc0c1\ud638\uc791\uc6a9\ud558\ub294 \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub4e4\uc758 \uacf5\ub3d9\uccb4\ub85c \ubc14\ub77c\ubcf4\uace0 \uac1d\uccb4\ub97c \uc774\uc6a9\ud574 \uc2dc\uc2a4\ud15c\uc744 \ubd84\ud560\ud558\ub294 \ubc29\ubc95\\n> \\n> \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub780 \uc0c1\ud0dc\uc640 \ud589\uc704\ub97c \ud568\uaed8 \uc9c0\ub2c8\uba70 \uc2a4\uc2a4\ub85c \uc790\uae30 \uc790\uc2e0\uc744 \ucc45\uc784\uc9c0\ub294 \uac1d\uccb4\ub97c \uc758\ubbf8\ud55c\ub2e4.\\n> \\n> \uac1d\uccb4\ub294 \uc2dc\uc2a4\ud15c\uc758 \ud589\uc704\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud55c\ub2e4. \uac01 \uac1d\uccb4\ub294 \ud611\ub825 \ub0b4\uc5d0\uc11c \uc815\ud574\uc9c4 \uc5ed\ud560\uc744 \uc218\ud589\ud558\uba70 \uc5ed\ud560\uc740 \uad00\ub828\ub41c \ucc45\uc784\uc758 \uc9d1\ud569\uc774\ub2e4.\\n> \\n> \uac1d\uccb4\ub294 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud558\uae30 \uc704\ud574 \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\uace0, \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c \uac1d\uccb4\ub294 \uba54\uc2dc\uc9c0\ub97c \ucc98\ub9ac\ud558\ub294 \ub370 \uc801\ud569\ud55c \uba54\uc11c\ub4dc\ub97c \uc790\uc728\uc801\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.\\n> p.35\\n> \\n\\n> \ud074\ub798\uc2a4\uc758 \uad6c\uc870\uc640 \uba54\uc11c\ub4dc\uac00 \uc544\ub2c8\ub77c \uac1d\uccb4\uc758 \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc5d0 \uc9d1\uc911\ud558\ub77c.\\n\uac1d\uccb4\uc9c0\ud5a5\uc740 \uac1d\uccb4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774\uc9c0 \ud074\ub798\uc2a4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\\np.38\\n> \\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub3d9\uc801\uc73c\ub85c \ubcc0\ud558\ub294 \uac1d\uccb4\uc758 \u2018\uc0c1\ud0dc\u2019\uc640 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \u2018\ud589\uc704\u2019\ub2e4.\\n\ud074\ub798\uc2a4\ub294 \ud0c0\uc785\uc744 \uad6c\ud604\ud558\uae30 \uc704\ud574 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uad6c\ud604 \uba54\ucee4\ub2c8\uc998\uc774\ub77c\ub294 \uc0ac\uc2e4\uc744 \uae30\uc5b5\ud558\ub77c.\\np.105\\n> \\n\\n> \ucc45\uc784 \uc8fc\ub3c4 \uc124\uacc4\uc758 \ud575\uc2ec\uc740 \uc5b4\ub5a4 \ud589\uc704\uac00 \ud544\uc694\ud55c\uc9c0\ub97c \uba3c\uc800 \uacb0\uc815\ud55c \ud6c4\uc5d0 \uc774 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac1d\uccb4\ub97c \uacb0\uc815\ud558\ub294 \uac83\uc774\ub2e4.\\n\uc774 \uacfc\uc815\uc744 \ud754\ud788 What/Who \uc0ac\uc774\ud074\uc774\ub77c\uace0 \ud55c\ub2e4.\\n\u2019\uc5b4\ub5a4 \ud589\uc704(What)\u2019\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud55c \ud6c4 \u2018\ub204\uac00(who)\u2019 \uadf8 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud574\uc57c \ud55c\ub2e4.\\n\uc5ec\uae30\uc11c \u2018\uc5b4\ub5a4 \ud589\uc704\u2019\uac00 \ubc14\ub85c \uba54\uc2dc\uc9c0\ub2e4.\\np.158\\n>"},{"id":"2022-retrospective","metadata":{"permalink":"/2022-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx","title":"2022\ub144 \ud68c\uace0","description":"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70","date":"2023-01-02T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 2\uc77c","tags":[{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.705,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"2022\ub144 \ud68c\uace0","slug":"2022-retrospective","tags":["Retrospective"]},"unlisted":false,"prevItem":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation"},"nextItem":{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","permalink":"/book-writer"}},"content":"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70 \\n\\n### \uc804\uc5ed\\n\\n\uc57d 1\ub144 6\uac1c\uc6d4\uac04\uc758 \uacf5\uad70 \uc815\ubcf4\ubcf4\ud638\ubcd1 \uc0dd\ud65c\uc744 \ub9c8\uce58\uace0 \uc804\uc5ed\uc744 \ud588\ub2e4. \\n\uc870\uae30 \uc804\uc5ed \ub54c\ubb38\uc5d0 2021\ub144 12\uc6d4\uc5d0 \ub098\uc654\uc9c0\ub9cc, \uc2e4\uc81c \uc804\uc5ed \ub0a0\uc9dc\ub294 2022\ub144\uc774\ub2c8 \ud68c\uace0\uc5d0 \uc801\uc5b4\ub3c4 \uc0c1\uad00\uc5c6\uaca0\uc9c0. \\n\\n\uc870\uae08 \ub354 \ubbf8\ub798\uc5d0 \ub300\ud55c \uc0dd\uac01\uc744 \ud574\ubcfc\uac78 \uadf8\ub7ac\ub2e4. \\n\uc804\uc5ed\uc744 \ud588\uc9c0\ub9cc \ubb50 \ud558\ub098 \uc81c\ub300\ub85c \ud560 \uc904 \uc544\ub294 \uac83\ub3c4 \uc5c6\uc73c\ub2c8 \ub113\uc740 \ubc14\ub2f7\uc18d\uc5d0 \ub369\uadf8\ub7ec\ub2c8 \ub193\uc544\uc9c4 \uae30\ubd84\uc774 \uad1c\ud788 \ub4e4\uc5c8\uc5c8\ub2e4. \\n\uc77c\ucc0d \uc0dd\uac01\uc744 \uc815\ub9ac\ud558\uc5ec \ubc29\ud5a5\uc744 \uc7a1\uc9c0 \ubabb\ud588\uae30\uc5d0 \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub0a8\uc558\ub2e4. \\n\\n### \uc790\ubc14\\n\\n\uc804\uc5ed\uc744 \ud558\uace0 \uc9c4\ub85c\ub97c \uace0\ubbfc\ud558\ub2e4 \ud5a5\ub85c\ub2d8\uc758 [\uc790\ubc14 \uacf5\ud654\uad6d](https://jojoldu.tistory.com/609) \ud3ec\uc2a4\ud305\uc744 \uc77d\uace0 \ub098\uc11c \uc790\ubc14 \uacf5\ubd80\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\uc720\uba85\ud55c \uc778\ud504\ub7f0\uc758 \uae40\uc601\ud55c\ub2d8\uc758 \uc2a4\ud504\ub9c1 \uac15\uc758\ub3c4 \uc788\uace0, \uc88b\uc740 \uc790\ubc14 \uac1c\ubc1c \uc11c\uc801\uc774 \ub9ce\uc544\uc11c \ub3c5\ud559\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4. \\n\ud558\ub2e4 \ubcf4\ub2c8 \uc790\ubc14\uc640 \uc2a4\ud504\ub9c1\uc744 \uacf5\ubd80\ud558\uba74\uc11c \u201c\uc65c \uc9c4\uc791\ud558\uc9c0 \uc54a\uc558\uc9c0\u201d\ub77c\ub294 \uc0dd\uac01\ub3c4 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\uc591\uc9c8\uc758 \uc790\ub8cc\ub3c4 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0, \uc608\uc804\uc5d0 \ub178\ub4dc\ub85c \uac1c\ubc1c\ud588\uc744 \ub54c \ud480\uc9c0 \ubabb\ud588\ub358 \ub2f5\ub2f5\ud568\uc744 \ub9ce\uc774 \ud574\uc18c\ud588\ub358 \uac83 \uac19\ub2e4.\\n\\n23\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae4a\uac8c \uc790\ubc14\ub97c \uacf5\ubd80\ud574\ubcfc \uc0dd\uac01\uc774\ub2e4. \\n\uc5b8\uc5b4\ub97c \ud558\ub098 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ub9ce\uc740 \ub3c4\uc6c0\uc774 \ub418\ub294 \uac83 \uac19\ub2e4.\\n\\n### \uc2a4\ud130\ub514\\n\\n\uae40\uc601\ud55c\ub2d8\uc758 \uac15\uc758\ub97c \uac70\uc758 \ub2e4 \ub4e4\uc5c8\uc744 \ub54c\ucbe4, \ud56d\uc0c1 \uac15\uc758\uc5d0\uc11c \uc5b8\uae09\ub418\ub294 \ud1a0\ube44\uc758 \uc2a4\ud504\ub9c1\uc744 \uc77d\uc5b4\ubcf4\uace0 \uc2f6\uc5b4\uc84c\uace0 \\n\ud63c\uc790 \uacf5\ubd80\ud558\uae30\uc5d0\ub294 \ub3d9\uae30\ubd80\uc5ec\ub3c4 \ubd80\uc871\ud588\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud130\ub514\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\uc744 \ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uacf5\ubd80\ub97c \ud560 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\uc9c0\ub9cc \ub098\uc5d0\uac8c\ub294 \ub0b4\uc6a9\uc774 \uaf64\ub098 \uc5b4\ub824\uc6cc\uc11c \uc2dc\uac04\uc744 \ub9ce\uc774 \uc18c\ube44\ud588\ub2e4. \\n\uac19\uc774 \uc2a4\ud130\ub514\ud558\uc2dc\ub294 \ubd84\uacfc 7\uac1c\uc6d4 \ub3d9\uc548 \uc2a4\ud130\ub514\ub97c \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00 \ucd1d 3\uad8c\uc758 \ucc45\uc744 \uc77d\uc744 \uc218 \uc788\uc5c8\ub2e4.\\n\\n### \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\\n\\n\uad70 \ubcf5\ubb34 \uc911\uc77c \ub54c \uc9c0\uc6d0\ud588\ub2e4 \ub5a8\uc5b4\uc9c4 \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ub2e4\uc2dc \uc9c0\uc6d0\ud588\ub2e4. \\n\uc774\ubc88 \uc5f0\ub3c4\uc5d0 \ucde8\uc5c5\uc744 \ud558\ub294 \uac8c \ubaa9\ud45c\uc600\uc9c0\ub9cc \ub0b4\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud2b9\ubcc4\ud55c \ubb34\uae30\uac00 \uc5c6\ub2e4\ub294 \uac78 \uae68\ub2ec\uc558\ub2e4. \\n\uc801\uc9c0 \uc54a\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574 \uc900\ube44\ub97c \ud588\uace0, \uac10\uc0ac\ud558\uac8c\ub3c4 \uc774\ubc88\uc5d0\ub294 \ucd5c\uc885 \ud569\uaca9\uc744 \ud588\ub2e4. \\n\\n\ub09c \uc0ac\ub78c\ub4e4\uacfc \uc18c\ud1b5\ud558\uace0, \ud611\uc5c5\ud558\ub294 \ub2a5\ub825\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ud1b5\ud574 \uadf8 \ube48 \ubd80\ubd84\uc744 \ucc44\uc6b0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### 2023\ub144\uc5d0\ub294\\n\\n\ub9c8\uc74c\uc758 \uc5ec\uc720\uac00 \uc5c6\uc5c8\ub358 2022\ub144\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ud558\uace0 \uc2f6\uc740 \uac74 \ub9ce\uc9c0\ub9cc, \uc774\ubc88\uc5d0\ub294 \uc5ec\uc720\ub97c \uac00\uc9c0\uace0 \ud560 \uc218 \uc788\ub294 \uac83\uc5d0 \ucd5c\uc120\uc744 \ub2e4\ud574\uc57c\uaca0\ub2e4."},{"id":"book-writer","metadata":{"permalink":"/book-writer","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx","source":"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx","title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","description":"\ucc45 \uc815\ubcf4","date":"2023-01-01T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 1\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":4.425,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","slug":"book-writer","tags":["Book"]},"unlisted":false,"prevItem":{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \\n> \ubc15\uc194\ubbf8 \\n>\\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\uc800\uc790\uc758 \uacbd\ud5d8\uacfc \ud568\uaed8 \uae00\uc4f0\uae30\uc5d0 \ub300\ud55c \uac00\ubcbc\uc6b4 \uc870\uc5b8\uc774 \ub2f4\uaca8\uc788\uc5b4 \uac00\ubccd\uac8c \uc77d\uae30 \uc88b\uc558\ub2e4. \\n\uae00\uc744 \uc798 \uc791\uc131\ud574 \ubcf4\uace0 \uc2f6\uc744 \ub54c \uc801\uc6a9\ud574 \ubcfc \uc218 \uc788\ub294 \uc815\ubcf4\uac00 \ub9ce\uc544\uc11c \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub2e4. \\n\\n\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\uc758 \ud504\ub9ac\ucf54\uc2a4\ub97c \uc9c4\ud589\ud560 \ub54c \ud6c4\uae30\ub97c \uc791\uc131\ud558\uace0 \ub098\uba74 \ud56d\uc0c1 \uae00\uc774 \ub531\ub531\ud558\ub2e4\ub294 \ub290\ub08c\uc744 \ubc1b\uc558\ub2e4. \\n\ub2e4\ub978 \uc9c0\uc6d0\uc790\ub4e4\uc758 \uc77d\uae30 \ud3b8\ud558\uace0, \ubc1d\uc740 \ub290\ub08c\uc744 \uc8fc\ub294 \uae00\uc744 \ubcf4\uba74 \ubd80\ub7ec\uc6b4 \ub9c8\uc74c\uc744 \uac00\uc9c0\uae30\ub3c4 \ud588\ub2e4. \\n\uc774 \ucc45\uc744 \uc77d\uc5c8\uc73c\ub2c8 2023\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae00\uc744 \uc798 \uc801\uc5b4\ubcf4\ub824\uace0 \ud55c\ub2e4.\\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \ubb38\uc7a5\uc774 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74\\n\ub0b4\uc6a9\uc744 \uc77c\ubaa9\uc694\uc5f0\ud558\uac8c \uc815\ub9ac\ud588\uace0, \uae00\uc758 \uc758\ub3c4\ub3c4 \uc090\ub6a4\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub3c4 \uc801\uc808\ud55c \uac83\uc73c\ub85c \uace8\ub790\ub294\ub370\u2026 \uadf8\ub7f0\ub370\ub3c4 \uc5b4\ub518\uac00\uac00 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74? \ucd95\ucd95 \ucc98\uc9c0\uace0 \ub530\ubd84\ud558\ub2e4\uba74? \ub9d0\uaf2c\ub9ac\ub97c \ubaa8\uc870\ub9ac \u2018~\ub2e4\u2019\ub85c \ud1b5\uc77c\ud55c \uac74 \uc544\ub2cc\uc9c0 \uc810\uac80\ud574 \ubcf4\uc138\uc694.\\n> \\n\\n> \ub9d0\uaf2c\ub9ac\ub97c \uc798 \uac16\uace0 \ub180\uc544\uc57c \ud569\ub2c8\ub2e4. \ubb38\uc7a5\uc758 \ub9c8\uc9c0\ub9c9 \uae00\uc790\ub97c \ub9e4\ubc88 \ub2e4\ub974\uac8c \uace0\uccd0\uc4f0\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uae00\uc5d0 \ud65c\uae30\ub97c \ub354\ud560 \uc218 \uc788\uc8e0. \ub54c\ub860 \ubb38\uc7a5\uc744 \ub2e4 \ub9c8\uce58\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub85c\ub9cc \ub05d\ub9fa\ub294 \uac83\ub3c4 \ubc29\ubc95. \ubb38\uc7a5\uacfc \ubb38\uc7a5 \uc0ac\uc774\uc5d0 \uc27c\ud45c\uac00 \ub4e4\uc5b4\uc11c\uba70 \uae00 \uc804\uccb4\uc5d0 \ud65c\uae30\uac00 \ub3cc\uac8c \ub3fc\uc694. \ubb38\uc7a5\uc758 \uae38\uc774\ub3c4 \ub2e4\ucc44\ub85c\uc6cc\uc9c0\ub294 \ub355\ubd84\uc5d0 \ub364\uc73c\ub85c \uc5bb\uac8c \ub418\ub294 \uac83\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ubc14\ub85c, \uae00\uc758 \ub9ac\ub4ec.\\n> \\n\\n> \uc774\uc804 \ubb38\uc7a5\uc5d0\uc11c \ub05d\ub09c \uae00\uc790\ub85c, \ub2e4\uc74c \ubb38\uc7a5\uc744 \ub05d\ub9fa\uc9c0 \uc54a\uae30. \ud55c\ub450 \ubb38\ub2e8\ub9c8\ub2e4 \ub2e8\uc5b4 \uc218\uc900\uc758 \uc544\uc8fc \uc9e7\uc740 \ubb38\uc7a5 \ubc30\uce58\ud558\uae30.\\n> \\n\\n> \uae00\uc758 \uc9c4\uc9dc \uc774\uc720, \uae00\uc758 \uc9c4\uc9dc \ubaa9\uc801, \uae00\uc758 \uc9c4\uc9dc \ub300\uc0c1\uc744 \ucc3e\uc73c\ub824\uace0 \uc560\uc37c\uc2b5\ub2c8\ub2e4. \uc9c0\uae08\ucc98\ub7fc \ud2c0\uc744 \ub5a0\uc62c\ub9b0\ub2e4\uac70\ub098, \ub208\uce58\ub97c \ubcf8\ub2e4\uac70\ub098, \uc815\uce58\uc801\uc778 \uc148\ub3c4 \ud558\uc9c0 \uc54a\uc558\uc5b4\uc694.\\n> \\n\\n> \uc81c\ubaa9\uc740 \uc9e7\uac8c, \ubcf4\uae30 \uc27d\uac8c, \uc77d\uae30 \uc27d\uac8c, \ubc1c\uc74c\uc774 \ube44\uc2b7\ud558\uac8c, \uc21c\uc11c\ub97c \ubc14\uafd4\uc11c\\n> \\n\\n> \uae00\uc744 \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ub2e4\ub4ec\uc744 \ub54c, \ub178\ub798\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubd05\ub2c8\ub2e4. \uac10\ud788 \uac00 \ub2ff\uc744 \uc218 \uc5c6\ub294 \ubaa9\ud45c\uc774\uaca0\uc9c0\ub9cc, \ud560 \uc218 \uc788\ub294 \ucd5c\uc18c\ud55c\uc758 \ub9ac\ub4ec\uc774\ub77c\ub3c4 \ubd99\uc5ec\uc8fc\uace0 \uc2f6\uc5b4\uc694.\\n> \\n\\n> \uc5ec\ub294 \ub9d0\uacfc \ub9c8\uc9c0\ub9c9 \ub9d0\uc5d0 \uc791\uc815\ud558\uace0 \ub9c8\uc74c\uc744 \ub2f4\ub294 \uc5f0\uc2b5\uc744 \ud574\ubd05\uc2dc\ub2e4. \uae00\uc758 \uc5b4\ub290 \uad6c\uc11d\uc774\ub77c\ub3c4 \ubed4\ud55c \uae00\uc790\ub294 \ub0a8\uae30\uc9c0 \uc54a\uaca0\ub178\ub77c \ub2e4\uc9d0\ud558\uba70 \uc368\ubcf4\ub294 \uac81\ub2c8\ub2e4. \ub098\ub9cc\uc774 \uac00\uc9c4 \uc720\uc77c\ud55c \uba54\uc2dc\uc9c0\uc5d0 \uc9d1\uc911\ud558\uba74\uc11c\uc694. \uadf8\ub7fc \uc0dd\uac01\uc774 \ub2ec\ub77c\uc9c0\uace0, \uace0\ub974\ub294 \ub2e8\uc5b4\ub3c4 \ub2ec\ub77c\uc9c0\uace0, \ub0a8\uae34 \ubb38\uc7a5\ub3c4 \ub2ec\ub77c\uc838\uc694. \uacb0\uad6d\uc5d0\ub294 \uae00\uc744 \uc4f4 \uc0ac\ub78c\uc778 \ub098 \uc790\uc2e0\ub3c4 \ub0a8\ub2ec\ub77c\uc9c8 \uac81\ub2c8\ub2e4.\\n> \\n\\n> \ub9de\ucda4\ubc95\uc740 \uc911\uc694\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub9de\ucda4\ubc95\ubcf4\ub2e4 \ub354 \uc911\uc694\ud55c \uac74 \uac70\uae30\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc785\ub2c8\ub2e4. \ub0b4 \ub9c8\uc74c\uc744 \uae00\uc5d0 \ub2f4\uc544 \uc2e4\uc5b4 \ubcf4\ub0b4\uae30 \uc804, \ub9de\ucda4\ubc95\uc744 \uc810\uac80\ud558\ub294 \uc774\uc720 \uc5ed\uc2dc \uadf8\uac81\ub2c8\ub2e4. \uc624\uc9c1 \ub0b4 \ub9c8\uc74c\uc774 \ub0a8\uc5d0\uac8c \uc77d\ud788\ub294 \ub3d9\uc548 \ubc29\ud574\uac00 \ub418\uc9c0 \uc54a\uae30\ub97c \ubc14\ub77c\uae30 \ub54c\ubb38\uc774\uc8e0. \ub0b4\uac00 \uc4f4 \uae00\ub3c4, \ub0a8\uc774 \uc4f4 \uae00\ub3c4. \uc5b8\uc81c\ub098 \uadf8 \uc548\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc774 \uba3c\uc800\uc785\ub2c8\ub2e4.\\n> \\n\\n> \uae00\uc744 \uc4f4\ub2e4\uace0 \uae00\uc774 \uc644\uc131\ub418\ub294 \uac8c \uc544\ub2c8\uc5d0\uc694. \uae00\uacfc \ub2ee\uc740 \ubaa8\uc2b5\uc73c\ub85c \uc0b4 \ub54c, \uae00\uc740 \ube44\ub85c\uc18c \uc644\uc131\ub429\ub2c8\ub2e4.\\n>"}]}')}}]); \ No newline at end of file diff --git a/assets/js/b2c8756c.4aff2828.js b/assets/js/b2c8756c.af1e0a2c.js similarity index 97% rename from assets/js/b2c8756c.4aff2828.js rename to assets/js/b2c8756c.af1e0a2c.js index 4c626987e..69d169b2c 100644 --- a/assets/js/b2c8756c.4aff2828.js +++ b/assets/js/b2c8756c.af1e0a2c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1213],{80936:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>a});var t=r(85893),o=r(3905);const s={title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",slug:"order-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/order-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4: AWS \ubc30\ud3ec",date:"2023-06-04T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 4\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.67,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",slug:"order-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",permalink:"/level2-interview-retrospective"},nextItem:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",permalink:"/tecochat-retrospective-3"}},l={authorsImageUrls:[]},a=[{value:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158",id:"\uc7a5\ubc14\uad6c\ub2c8-\uc8fc\ubb38-\ubbf8\uc158",level:3},{value:"\ubc30\ud3ec",id:"\ubc30\ud3ec",level:3},{value:"\ud611\uc5c5",id:"\ud611\uc5c5",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84",id:"\uc0c8\ub85c-\ubc30\uc6b4-\ubd80\ubd84",level:3}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: AWS \ubc30\ud3ec",(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-shopping-order/pull/7",children:"https://github.com/woowacourse/jwp-shopping-order/pull/7"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc7a5\ubc14\uad6c\ub2c8-\uc8fc\ubb38-\ubbf8\uc158",children:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158"}),"\n",(0,t.jsxs)(n.p,{children:["\ubc30\ud3ec \ubc0f \ud611\uc5c5\uc744 \ud560 \uc218 \uc788\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9c8\ucf54, \uc6b0\uac00, \uc6b0\ucf54, \uc6b0\uc2a4 \uadf8\ub9ac\uace0 \ub098\uae4c\uc9c0 \ud569\uccd0\uc11c 5\uba85\uc774 \ud55c \ud300\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc30\ud3ec",children:"\ubc30\ud3ec"}),"\n",(0,t.jsxs)(n.p,{children:["\uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac AWS\ub97c \uc774\uc6a9\ud574 \ubc30\ud3ec\ub97c \ud574\uc57c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac01\uc790 \ud558\ub098\uc758 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc744 \uc218 \uc788\uc5c8\uace0, \ud300 \ubcc4\ub85c DB\ub97c \uc704\ud55c \ucd94\uac00 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uacbd\ud5d8\uc744 \ud574\ubcfc \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ud22c\uc790\ud558\uc9c4 \uc54a\uc558\uace0, \ub2e4\uc74c\uacfc \uac19\uc774 \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'echo "Start Deploy Script"\nREPOSITORY_NAME=/home/ubuntu/jwp-shopping-order\nPROJECT_NAME=jwp-shopping-order\n\necho "Change Directory"\ncd $REPOSITORY_NAME\n\necho "Git Pull"\ngit pull origin step2\n\necho "Build"\n./gradlew bootJar\n\necho "Copy, Start Server"\nmv ./build/libs/$PROJECT_NAME.jar .\n\nPID=$(pgrep -f $PROJECT_NAME)\n\nif [ -n $PID ]; then\n kill -9 $PID\n\tsleep 5\nfi\n\nnohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ud611\uc5c5",children:"\ud611\uc5c5"}),"\n",(0,t.jsxs)(n.p,{children:["\uc77c\ub2e8 \uc6b0\uc2a4\ub791 \uc6b0\ucf54\uac00 \uba3c\uc800 \uc7a0\uc2e4\ub85c \uc640\uc918\uc11c \ub108\ubb34 \uac10\uc0ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc31\uc5d4\ub4dc\uac00 \uc544\ub2cc \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \ud574\ubcf4\ub294 \uccab \ud611\uc5c5\uc774\ub77c \uc57d\uac04 \ub450\uadfc\uac70\ub838\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc608\uc0c1\uc678\ub85c \ub300\ud654\uac00 \uc798 \ub418\uc5b4\uc11c, \ube60\ub974\uac8c \uba85\uc138\ub97c \uc815\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc5ec\ub7ec\uac00\uc9c0 \ubc29\ubc95\uc5d0 \ub300\ud55c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud574\ubcf4\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc31\uc5d4\ub4dc\uc640 \ud14c\uc774\ube14 \uba85\uc138\ub098 \ucfe0\ud3f0 \uad6c\ud604\uc5d0 \ub300\ud574\uc11c \uc774\uc57c\uae30\ud560 \ub54c \uc7a5\ub2e8\uc5d0 \ub300\ud574 \ub9ce\uc774 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc5ec\uc11c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud588\ub2e4\uba74 \ub354 \uc88b\uc740 \uacb0\uacfc\ubb3c\uc774 \ub098\uc624\uc9c0 \uc54a\uc558\uc744\uae4c?",(0,t.jsx)(n.br,{}),"\n","\uc55e\uc73c\ub85c \uc120\ud0dd\uc758 \uc21c\uac04\uc5d0\uc11c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub4e4\uc5ec\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ubc30\uc6b4-\ubd80\ubd84",children:"\uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"expose headers"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc6f9 \ud398\uc774\uc9c0\uc5d0\uc11c Location \ud5e4\ub354\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c ",(0,t.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header",children:"\ud5c8\uc6a9 \ubaa9\ub85d\uc5d0 \uc874\uc7ac\ud558\ub294 \uc751\ub2f5\ud5e4\ub354"}),"\ub9cc \ubc18\ud658\ud55c\ub2e4\ub294 \uac83\uc744 \ubaa8\ub974\uace0 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub97c expose headers \uc124\uc815\uc744 \ud1b5\ud574 \ud574\uacb0\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","nginx \uc124\uc815\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \ucd94\uac00\ud574 \uc8fc\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"add_header 'Access-Control-Expose-Headers' 'Location'\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158"})}),"\n",(0,t.jsxs)(n.p,{children:["\ub2e8\uc21c \uc870\ud68c \uc694\uccad\uc5d0 \ub300\ud55c \uc131\ub2a5\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc900\ub2e4\ub294 \uac83\uc774\ub77c\uace0 \uac04\ub2e8\ud788\ub9cc \uc54c\uace0 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88\uc5d0 \ucf54\uba58\ud2b8\uac00 \ub2ec\ub824\uc11c \uc870\uae08 \ub354 \uc790\uc138\ud788 \uacf5\ubd80\ud574 \ubcf4\uae30\ub85c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Transactional(readOnly = true)\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc774 \ub3d9\uc791\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"setReadOnly(true) \uc124\uc815\uc774 \ub41c Connection\uc73c\ub85c \uc5f0\uacb0\uc744 \uc2dc\ub3c4\ub97c \ud55c\ub2e4. \uc774 \uc124\uc815\uc744 \ud558\ub294 \uacbd\uc6b0 DB\ub9c8\ub2e4 \ub2e4\ub974\uac8c \ub3d9\uc791\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"h2\uc758 Connection \uad6c\ud604\uccb4\ub294 readOnly \uc124\uc815\uc744 \ubb34\uc2dc\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 Transactional \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"MySQL 8.0(InnoDB \uc0ac\uc6a9 \uc2dc)\uc758 \uacbd\uc6b0 \uc77d\uae30 \uc804\uc6a9\uc73c\ub85c \uc54c\ub824\uc9c4 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158 ID\ub97c \uc124\uc815\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uc870\ud68c \uc18d\ub3c4\uac00 \ub354 \ube68\ub77c\uc9c4\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["ORM \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 prepareTransactionalConnection\ub97c \ud638\ucd9c\ud55c\ub2e4\uace0 \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ud604\uc5c5\uc5d0\uc11c\ub294 \uace0\uac00\uc6a9\uc131 \ub0b4\uacb0\ud568\uc131 \ub4f1\uc744 \uc704\ud558\uc5ec \ud074\ub7ec\uc2a4\ud130\ub97c \uad6c\uc131\ud558\uc5ec \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uace0, \uc774 \uacbd\uc6b0 readOnly \uc124\uc815\uc774 \ub418\uc5b4\uc788\ub2e4\uba74 \uc77d\uae30 \uc804\uc6a9 DB\ub85c \uc9c8\uc758\uac00 \ub4e4\uc5b4\uac00\uc11c \ubd80\ud558 \ubd84\uc0b0\uc758 \ud6a8\uacfc\uac00 \uc788\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.strong,{children:["DAO\uc5d0 ",(0,t.jsx)(n.code,{children:"@Transactional"})," \uc801\uc6a9"]})}),"\n",(0,t.jsxs)(n.p,{children:["DAO\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \ubcf4\ub294 \uac74 \uc5b4\ub5bb\uaca0\ub0d0\uace0 \ub9ac\ubdf0\uac00 \ub2ec\ub824\uc11c \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Service \uacc4\uce35\uc5d0 \uc774\ubbf8 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \uc8fc\uace0 \uc788\uae30\uc5d0 \ud544\uc694 \uc5c6\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","DAO\ub97c \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574(\ud655\uc7a5\uc131 \uace0\ub824) ",(0,t.jsx)(n.code,{children:"@Transactional"}),"\uc744 \uc801\uc6a9\ud558\ub294 \uac83\ub3c4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."]})]})}function d(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function s(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=t.createContext({}),a=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,s=e.originalType,l=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=a(r),u=o,j=h["".concat(l,".").concat(u)]||h[u]||p[u]||s;return r?t.createElement(j,i(i({ref:n},d),{},{components:r})):t.createElement(j,i({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1213],{80936:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>a});var t=r(85893),o=r(3905);const s={title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",slug:"order-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/order-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4: AWS \ubc30\ud3ec",date:"2023-06-04T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 4\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.67,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",slug:"order-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",permalink:"/tecochat-retrospective-3"},nextItem:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",permalink:"/level2-interview-retrospective"}},l={authorsImageUrls:[]},a=[{value:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158",id:"\uc7a5\ubc14\uad6c\ub2c8-\uc8fc\ubb38-\ubbf8\uc158",level:3},{value:"\ubc30\ud3ec",id:"\ubc30\ud3ec",level:3},{value:"\ud611\uc5c5",id:"\ud611\uc5c5",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84",id:"\uc0c8\ub85c-\ubc30\uc6b4-\ubd80\ubd84",level:3}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: AWS \ubc30\ud3ec",(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/jwp-shopping-order/pull/7",children:"https://github.com/woowacourse/jwp-shopping-order/pull/7"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc7a5\ubc14\uad6c\ub2c8-\uc8fc\ubb38-\ubbf8\uc158",children:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158"}),"\n",(0,t.jsxs)(n.p,{children:["\ubc30\ud3ec \ubc0f \ud611\uc5c5\uc744 \ud560 \uc218 \uc788\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9c8\ucf54, \uc6b0\uac00, \uc6b0\ucf54, \uc6b0\uc2a4 \uadf8\ub9ac\uace0 \ub098\uae4c\uc9c0 \ud569\uccd0\uc11c 5\uba85\uc774 \ud55c \ud300\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc30\ud3ec",children:"\ubc30\ud3ec"}),"\n",(0,t.jsxs)(n.p,{children:["\uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac AWS\ub97c \uc774\uc6a9\ud574 \ubc30\ud3ec\ub97c \ud574\uc57c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uac01\uc790 \ud558\ub098\uc758 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc744 \uc218 \uc788\uc5c8\uace0, \ud300 \ubcc4\ub85c DB\ub97c \uc704\ud55c \ucd94\uac00 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uacbd\ud5d8\uc744 \ud574\ubcfc \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ud22c\uc790\ud558\uc9c4 \uc54a\uc558\uace0, \ub2e4\uc74c\uacfc \uac19\uc774 \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'echo "Start Deploy Script"\nREPOSITORY_NAME=/home/ubuntu/jwp-shopping-order\nPROJECT_NAME=jwp-shopping-order\n\necho "Change Directory"\ncd $REPOSITORY_NAME\n\necho "Git Pull"\ngit pull origin step2\n\necho "Build"\n./gradlew bootJar\n\necho "Copy, Start Server"\nmv ./build/libs/$PROJECT_NAME.jar .\n\nPID=$(pgrep -f $PROJECT_NAME)\n\nif [ -n $PID ]; then\n kill -9 $PID\n\tsleep 5\nfi\n\nnohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ud611\uc5c5",children:"\ud611\uc5c5"}),"\n",(0,t.jsxs)(n.p,{children:["\uc77c\ub2e8 \uc6b0\uc2a4\ub791 \uc6b0\ucf54\uac00 \uba3c\uc800 \uc7a0\uc2e4\ub85c \uc640\uc918\uc11c \ub108\ubb34 \uac10\uc0ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc31\uc5d4\ub4dc\uac00 \uc544\ub2cc \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \ud574\ubcf4\ub294 \uccab \ud611\uc5c5\uc774\ub77c \uc57d\uac04 \ub450\uadfc\uac70\ub838\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc608\uc0c1\uc678\ub85c \ub300\ud654\uac00 \uc798 \ub418\uc5b4\uc11c, \ube60\ub974\uac8c \uba85\uc138\ub97c \uc815\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc5ec\ub7ec\uac00\uc9c0 \ubc29\ubc95\uc5d0 \ub300\ud55c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud574\ubcf4\uae30"})}),"\n",(0,t.jsxs)(n.p,{children:["\ubc31\uc5d4\ub4dc\uc640 \ud14c\uc774\ube14 \uba85\uc138\ub098 \ucfe0\ud3f0 \uad6c\ud604\uc5d0 \ub300\ud574\uc11c \uc774\uc57c\uae30\ud560 \ub54c \uc7a5\ub2e8\uc5d0 \ub300\ud574 \ub9ce\uc774 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc5ec\uc11c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud588\ub2e4\uba74 \ub354 \uc88b\uc740 \uacb0\uacfc\ubb3c\uc774 \ub098\uc624\uc9c0 \uc54a\uc558\uc744\uae4c?",(0,t.jsx)(n.br,{}),"\n","\uc55e\uc73c\ub85c \uc120\ud0dd\uc758 \uc21c\uac04\uc5d0\uc11c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub4e4\uc5ec\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ubc30\uc6b4-\ubd80\ubd84",children:"\uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"expose headers"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc6f9 \ud398\uc774\uc9c0\uc5d0\uc11c Location \ud5e4\ub354\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c ",(0,t.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header",children:"\ud5c8\uc6a9 \ubaa9\ub85d\uc5d0 \uc874\uc7ac\ud558\ub294 \uc751\ub2f5\ud5e4\ub354"}),"\ub9cc \ubc18\ud658\ud55c\ub2e4\ub294 \uac83\uc744 \ubaa8\ub974\uace0 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub97c expose headers \uc124\uc815\uc744 \ud1b5\ud574 \ud574\uacb0\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","nginx \uc124\uc815\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \ucd94\uac00\ud574 \uc8fc\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"add_header 'Access-Control-Expose-Headers' 'Location'\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158"})}),"\n",(0,t.jsxs)(n.p,{children:["\ub2e8\uc21c \uc870\ud68c \uc694\uccad\uc5d0 \ub300\ud55c \uc131\ub2a5\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc900\ub2e4\ub294 \uac83\uc774\ub77c\uace0 \uac04\ub2e8\ud788\ub9cc \uc54c\uace0 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88\uc5d0 \ucf54\uba58\ud2b8\uac00 \ub2ec\ub824\uc11c \uc870\uae08 \ub354 \uc790\uc138\ud788 \uacf5\ubd80\ud574 \ubcf4\uae30\ub85c \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Transactional(readOnly = true)\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc774 \ub3d9\uc791\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"setReadOnly(true) \uc124\uc815\uc774 \ub41c Connection\uc73c\ub85c \uc5f0\uacb0\uc744 \uc2dc\ub3c4\ub97c \ud55c\ub2e4. \uc774 \uc124\uc815\uc744 \ud558\ub294 \uacbd\uc6b0 DB\ub9c8\ub2e4 \ub2e4\ub974\uac8c \ub3d9\uc791\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"h2\uc758 Connection \uad6c\ud604\uccb4\ub294 readOnly \uc124\uc815\uc744 \ubb34\uc2dc\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 Transactional \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"MySQL 8.0(InnoDB \uc0ac\uc6a9 \uc2dc)\uc758 \uacbd\uc6b0 \uc77d\uae30 \uc804\uc6a9\uc73c\ub85c \uc54c\ub824\uc9c4 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158 ID\ub97c \uc124\uc815\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uc870\ud68c \uc18d\ub3c4\uac00 \ub354 \ube68\ub77c\uc9c4\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["ORM \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 prepareTransactionalConnection\ub97c \ud638\ucd9c\ud55c\ub2e4\uace0 \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ud604\uc5c5\uc5d0\uc11c\ub294 \uace0\uac00\uc6a9\uc131 \ub0b4\uacb0\ud568\uc131 \ub4f1\uc744 \uc704\ud558\uc5ec \ud074\ub7ec\uc2a4\ud130\ub97c \uad6c\uc131\ud558\uc5ec \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uace0, \uc774 \uacbd\uc6b0 readOnly \uc124\uc815\uc774 \ub418\uc5b4\uc788\ub2e4\uba74 \uc77d\uae30 \uc804\uc6a9 DB\ub85c \uc9c8\uc758\uac00 \ub4e4\uc5b4\uac00\uc11c \ubd80\ud558 \ubd84\uc0b0\uc758 \ud6a8\uacfc\uac00 \uc788\ub2e4\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.strong,{children:["DAO\uc5d0 ",(0,t.jsx)(n.code,{children:"@Transactional"})," \uc801\uc6a9"]})}),"\n",(0,t.jsxs)(n.p,{children:["DAO\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \ubcf4\ub294 \uac74 \uc5b4\ub5bb\uaca0\ub0d0\uace0 \ub9ac\ubdf0\uac00 \ub2ec\ub824\uc11c \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Service \uacc4\uce35\uc5d0 \uc774\ubbf8 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \uc8fc\uace0 \uc788\uae30\uc5d0 \ud544\uc694 \uc5c6\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","DAO\ub97c \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574(\ud655\uc7a5\uc131 \uace0\ub824) ",(0,t.jsx)(n.code,{children:"@Transactional"}),"\uc744 \uc801\uc6a9\ud558\ub294 \uac83\ub3c4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."]})]})}function d(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function s(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=t.createContext({}),a=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,s=e.originalType,l=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=a(r),u=o,j=h["".concat(l,".").concat(u)]||h[u]||p[u]||s;return r?t.createElement(j,i(i({ref:n},d),{},{components:r})):t.createElement(j,i({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/b2ebb6fd.301d7a2d.js b/assets/js/b2ebb6fd.4d905b58.js similarity index 98% rename from assets/js/b2ebb6fd.301d7a2d.js rename to assets/js/b2ebb6fd.4d905b58.js index 2cb279a35..d0fd105b6 100644 --- a/assets/js/b2ebb6fd.301d7a2d.js +++ b/assets/js/b2ebb6fd.4d905b58.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4091],{8343:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var i=s(85893),t=s(3905);const a={title:"Jenkins\ub85c CI/CD \uc124\uc815",slug:"jenkins",tags:["Jenkins","Elastic Beanstalk"]},r=void 0,l={permalink:"/jenkins",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",source:"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",title:"Jenkins\ub85c CI/CD \uc124\uc815",description:"\uc124\uc815 \ud658\uacbd",date:"2023-04-30T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 30\uc77c",tags:[{label:"Jenkins",permalink:"/tags/jenkins"},{label:"Elastic Beanstalk",permalink:"/tags/elastic-beanstalk"}],readingTime:7.495,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Jenkins\ub85c CI/CD \uc124\uc815",slug:"jenkins",tags:["Jenkins","Elastic Beanstalk"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",permalink:"/tecochat-retrospective-2"},nextItem:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",permalink:"/tecochat-retrospective-1"}},o={authorsImageUrls:[]},c=[{value:"\uc124\uc815 \ud658\uacbd",id:"\uc124\uc815-\ud658\uacbd",level:3},{value:"[EC2 CLI] Swap \uba54\ubaa8\ub9ac \uc124\uc815",id:"ec2-cli-swap-\uba54\ubaa8\ub9ac-\uc124\uc815",level:3},{value:"[EC2 CLI] jenkins \uc124\uce58",id:"ec2-cli-jenkins-\uc124\uce58",level:3},{value:"[EC2 CLI] Jenkins \uc2dc\uc791",id:"ec2-cli-jenkins-\uc2dc\uc791",level:3},{value:"[EC2 CLI] nginx & git \uc124\uce58",id:"ec2-cli-nginx--git-\uc124\uce58",level:3},{value:"[EC2 CLI] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815",id:"ec2-cli-nginx-\ub9ac\ubc84\uc2a4-\ud504\ub85d\uc2dc-\uc124\uc815",level:3},{value:"[Jenkins] Jenkins \uc811\uc18d",id:"jenkins-jenkins-\uc811\uc18d",level:3},{value:"[Jenkins] Jenkins Blue Ocean \uc124\uce58",id:"jenkins-jenkins-blue-ocean-\uc124\uce58",level:3},{value:"[AWS IAM & EC2] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30",id:"aws-iam--ec2-iam\uc73c\ub85c-ec2-\uc778\uc2a4\ud134\uc2a4-\uad8c\ud55c-\uc124\uc815\ud558\uae30",level:3},{value:"[AWS S3] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131",id:"aws-s3-jar-\ud30c\uc77c\uc744-\uc5c5\ub85c\ub4dc-\ud560-s3-\ubc84\ud0b7-\uc0dd\uc131",level:3},{value:"[Github] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131",id:"github-blue-ocean\uc5d0\uc11c-\ud30c\uc774\ud504\ub77c\uc778-\uc0dd\uc131\uc5d0-\ud544\uc694\ud55c-github-token-\uc0dd\uc131",level:3},{value:"[Jenkins] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791",id:"jenkins-\ube14\ub8e8-\uc624\uc158-\uc2dc\uc791",level:3},{value:"[Github Repsoitory] Jenkinsfile \uc124\uc815",id:"github-repsoitory-jenkinsfile-\uc124\uc815",level:3},{value:"[Github] Webhooks \uc124\uc815",id:"github-webhooks-\uc124\uc815",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",br:"br",code:"code",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"\uc124\uc815-\ud658\uacbd",children:"\uc124\uc815 \ud658\uacbd"}),"\n",(0,i.jsxs)(n.p,{children:["\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc774\ubbf8\uc9c0: Amazon Linux 2023 AMI",(0,i.jsx)(n.br,{}),"\n","\uc544\ud0a4\ud14d\uccd0: ARM",(0,i.jsx)(n.br,{}),"\n","\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small",(0,i.jsx)(n.br,{}),"\n","\ud658\uacbd \uad6c\uc131\uc774 \uc644\ub8cc\ub41c Elastic Beanstalk",(0,i.jsx)(n.br,{}),"\n","\ub2e8\uc77c Spring Boot \ud504\ub85c\uc81d\ud2b8\uac00 \uc874\uc7ac\ud558\ub294 Github Repository"]}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-swap-\uba54\ubaa8\ub9ac-\uc124\uc815",children:"[EC2 CLI] Swap \uba54\ubaa8\ub9ac \uc124\uc815"}),"\n",(0,i.jsxs)(n.p,{children:["t4g.small\uc774 \ub7a8\uc774 2G\uc778\ub370 \ub7a8\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \ub290\uaef4\uc838\uc11c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc544\ub798 \uba85\ub839\uc5b4\ub97c \ub530\ub77c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud558\uace0 free -h \uba85\ub839\uc5b4\ub97c \ud1b5\ud574 \uc798 \uc124\uc815\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# fallocate \uc774\uc6a9\ud558\uc5ec \uc2a4\uc651 \ud30c\uc77c \uc0dd\uc131\nsudo fallocate -l 2G /swapfile\n\n# \uad8c\ud55c \uc124\uc815\nsudo chmod 600 /swapfile\n\n# \ud30c\uc77c\uc744 Swap \ud3ec\ub9f7\uc73c\ub85c \ubcc0\uacbd \ud6c4 \uc2dc\uc2a4\ud15c\uc5d0 \ub4f1\ub85d\nsudo mkswap /swapfile\nsudo swapon /swapfile\n\n# Swap \uba54\ubaa8\ub9ac \ubd80\ud305\uc2dc \uc790\ub3d9\uc73c\ub85c \ub9c8\uc6b4\ud2b8\ud558\ub3c4\ub85d \uc801\uc6a9\n# \ucd5c\ud558\ub2e8\uc5d0 \ub2e4\uc74c \uad6c\ubb38 \uc124\uc815 -> /swapfile swap swap defaults 0 0\nsudo vim /etc/fstab\n"})}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-jenkins-\uc124\uce58",children:"[EC2 CLI] jenkins \uc124\uce58"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo wget -O /etc/yum.repos.d/jenkins.repo \\\n https://pkg.jenkins.io/redhat-stable/jenkins.repo\nsudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key\nsudo yum upgrade\nsudo yum install java-17-amazon-corretto-devel\nsudo yum install jenkins\nsudo systemctl daemon-reload\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos",children:"Jenkins \uacf5\uc2dd \ud648\ud398\uc774\uc9c0"})," \ub97c \ucc38\uace0\ud558\uc5ec \uc124\uce58\ud558\ub294 \uac8c \uc88b\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-jenkins-\uc2dc\uc791",children:"[EC2 CLI] Jenkins \uc2dc\uc791"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo systemctl enable jenkins\nsudo systemctl start jenkins\n"})}),"\n",(0,i.jsx)(n.p,{children:"enable\ub85c \uc124\uc815\ud558\uc5ec \ubd80\ud305\uc2dc \uc790\ub3d9\uc2dc\uc791 \ub418\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-nginx--git-\uc124\uce58",children:"[EC2 CLI] nginx & git \uc124\uce58"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo yum install nginx\nsudo systemctl enable nginx\nsudo systemctl start nginx\n\nsudo yum install git\n"})}),"\n",(0,i.jsx)(n.p,{children:"nginx\uc640 \ucf54\ub4dc\ub97c \ubd88\ub7ec\uc62c \ub54c \uc0ac\uc6a9\ud560 git\uc744 \uc124\uce58\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-nginx-\ub9ac\ubc84\uc2a4-\ud504\ub85d\uc2dc-\uc124\uc815",children:"[EC2 CLI] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:"\uc544\ub798 \uc124\uc815 \ud30c\uc77c\uc740 \uacf5\uc2dd \ud648\ud398\uc774\uc9c0\uc5d0\uc11c \uc548\ub0b4\ud55c \uae30\ubcf8\uc801\uc778 \uc124\uc815 \ud30c\uc77c\uc774\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'upstream jenkins {\n keepalive 32; # keepalive connections\n server 127.0.0.1:8080; # jenkins ip and port\n}\n\n# Required for Jenkins websocket agents\nmap $http_upgrade $connection_upgrade {\n default upgrade;\n \'\' close;\n}\n\nserver {\n listen 80; # Listen on port 80 for IPv4 requests\n\n server_name jenkins.example.com; # replace \'jenkins.example.com\' with your server domain name\n\n # this is the jenkins web root directory\n # (mentioned in the output of "systemctl cat jenkins")\n root /var/run/jenkins/war/;\n\n access_log /var/log/nginx/jenkins.access.log;\n error_log /var/log/nginx/jenkins.error.log;\n\n # pass through headers from Jenkins that Nginx considers invalid\n ignore_invalid_headers off;\n\n location ~ "^/static/[0-9a-fA-F]{8}\\/(.*)$" {\n # rewrite all static files into requests to the root\n # E.g /static/12345678/css/something.css will become /css/something.css\n rewrite "^/static/[0-9a-fA-F]{8}\\/(.*)" /$1 last;\n }\n\n location /userContent {\n # have nginx handle all the static requests to userContent folder\n # note : This is the $JENKINS_HOME dir\n root /var/lib/jenkins/;\n if (!-f $request_filename){\n # this file does not exist, might be a directory or a /**view** url\n rewrite (.*) /$1 last;\n break;\n }\n sendfile on;\n }\n\n location / {\n sendfile off;\n proxy_pass http://jenkins;\n proxy_redirect default;\n proxy_http_version 1.1;\n\n # Required for Jenkins websocket agents\n proxy_set_header Connection $connection_upgrade;\n proxy_set_header Upgrade $http_upgrade;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_max_temp_file_size 0;\n\n #this is the maximum upload size\n client_max_body_size 10m;\n client_body_buffer_size 128k;\n\n proxy_connect_timeout 90;\n proxy_send_timeout 90;\n proxy_read_timeout 90;\n proxy_buffering off;\n proxy_request_buffering off; # Required for HTTP CLI commands\n proxy_set_header Connection ""; # Clear for keepalive\n }\n\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Jenkins\ub294 8080 \ud3ec\ud2b8\ub85c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc\ub97c \uc124\uc815\ud574\uc900\ub2e4.",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.code,{children:"/etc/nginx/conf.d"}),"\xa0\uc544\ub798\xa0",(0,i.jsx)(n.code,{children:"default.conf"}),"\xa0\ud30c\uc77c\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uace0 \uc704\uc640 \uac19\uc774 \uc785\ub825\ud558\uace0 \uc800\uc7a5\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","nginx\uc758 \uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\uc5d0 \uc874\uc7ac\ud558\ub294\xa0",(0,i.jsx)(n.code,{children:"include /etc/nginx/conf.d/*.conf;"}),"\xa0\uc124\uc815 \ub54c\ubb38\uc5d0\xa0",(0,i.jsx)(n.code,{children:".conf"}),"\xa0\ub85c \ub05d\ub09c\ub2e4\uba74 \uc124\uc815\uc774 \uc801\uc6a9\ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc124\uc815 \ud6c4\xa0",(0,i.jsx)(n.code,{children:"sudo nginx -t"}),"\ub85c \uc124\uc815\ud30c\uc77c\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud558\uace0,\xa0",(0,i.jsx)(n.code,{children:"sudo systemctl restart nginx"}),"\xa0\uba85\ub839\uc5b4\ub85c nginx\ub97c \uc7ac\uc2dc\uc791\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-jenkins-\uc811\uc18d",children:"[Jenkins] Jenkins \uc811\uc18d"}),"\n",(0,i.jsxs)(n.p,{children:["Jenkins\ub97c \uc124\uce58\ud55c EC2 \uc778\uc2a4\ud134\uc2a4 \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc5d0 80\ubc88 \ud3ec\ud2b8\uac00 \uc5f4\ub824\uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","EC2\uc758 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \ub4e4\uc5b4\uac00\uba74 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-start",src:s(71399).Z+"",width:"2008",height:"1836"})}),"\n",(0,i.jsxs)(n.p,{children:["\ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud558\ub294\ub370 ",(0,i.jsx)(n.code,{children:"sudo cat /var/lib/jenkins/secrets/initialAdminPasswor"})," \ub97c \uc785\ub825\ud574 \ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc5bb\uc744 \uc218 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 \ud50c\ub7ec\uadf8\uc778 \uc124\uc815 \ucc3d\uc774 \ub098\uc62c\ud150\ub370 ",(0,i.jsx)(n.code,{children:"install suggested plugins"}),"\uc744 \ud074\ub9ad\ud558\uc5ec Jenkins\uac00 \ucd94\ucc9c\ud558\ub294 \uae30\ubcf8 \ud50c\ub7ec\uadf8\uc778\ub4e4\uc744 \uc124\uce58\ud558\uba74 \ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud50c\ub7ec\uadf8\uc778\uc744 \uc124\uce58\ud558\uba74 \uacc4\uc815 \ubc0f \uc8fc\uc18c \uc124\uc815\uc744 \ud574\uc57c\ud558\ub294\ub370 \uc774\uac74 \ud3b8\ud558\uac8c \uc124\uc815\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-jenkins-blue-ocean-\uc124\uce58",children:"[Jenkins] Jenkins Blue Ocean \uc124\uce58"}),"\n",(0,i.jsx)(n.p,{children:"Jenkins \uad00\ub9ac \u2192 Plugin Manager\uc5d0\uc11c Blue Ocean\uc744 \uac80\uc0c9\ud574 \uc124\uce58\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"aws-iam--ec2-iam\uc73c\ub85c-ec2-\uc778\uc2a4\ud134\uc2a4-\uad8c\ud55c-\uc124\uc815\ud558\uae30",children:"[AWS IAM & EC2] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30"}),"\n",(0,i.jsxs)(n.p,{children:["S3\uc640 Elastic Beanstalk\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub824\uba74 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk \ub450 \uac1c\uc758 \uc815\ucc45\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uc5ed\ud560\uc744 \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","IAM\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc774 \uc5ed\ud560\uc744 \ud558\ub098 \uc0c8\ub85c \uc0dd\uc131\ud55c\ub2e4."]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"\uc5d4\ud130\ud2f0 \uc120\ud0dd"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam1",src:s(30618).Z+"",width:"2282",height:"1028"})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsx)(n.li,{children:"\uad8c\ud55c \ucd94\uac00"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam2",src:s(56786).Z+"",width:"2300",height:"880"})}),"\n",(0,i.jsxs)(n.ol,{start:"3",children:["\n",(0,i.jsx)(n.li,{children:"\uc774\ub984 \uc9c0\uc815, \uac80\ud1a0 \ubc0f \uc0dd\uc131"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam3",src:s(63303).Z+"",width:"1872",height:"1724"})}),"\n",(0,i.jsxs)(n.ol,{start:"4",children:["\n",(0,i.jsx)(n.li,{children:"\uc0dd\uc131\ud55c IAM EC2 Jenkins \uc778\uc2a4\ud134\uc2a4\ub97c \uc120\ud0dd\ud558\uace0, \uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc744 \ub20c\ub7ec Role \uc124\uc815"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam4",src:s(82150).Z+"",width:"2264",height:"602"})}),"\n",(0,i.jsx)(n.h3,{id:"aws-s3-jar-\ud30c\uc77c\uc744-\uc5c5\ub85c\ub4dc-\ud560-s3-\ubc84\ud0b7-\uc0dd\uc131",children:"[AWS S3] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131"}),"\n",(0,i.jsx)(n.p,{children:"\ubc84\ud0b7\uc744 \uc0dd\uc131\ud560 \ub54c \ub2e4\uc74c \uc124\uc815\uc744 \uc81c\uc678\ud558\uace0 \ubaa8\ub450 \ucc28\ub2e8 \ud65c\uc131\ud654\ub97c \ud574\uc900\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"\uc0c8 ACL(\uc561\uc138\uc2a4 \uc81c\uc5b4 \ubaa9\ub85d)\uc744 \ud1b5\ud574 \ubd80\uc5ec\ub41c \ubc84\ud0b7 \ubc0f \uac1d\uccb4\uc5d0 \ub300\ud55c \ud37c\ube14\ub9ad \uc561\uc138\uc2a4 \ucc28\ub2e8"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-s3",src:s(36238).Z+"",width:"1636",height:"1258"})}),"\n",(0,i.jsx)(n.h3,{id:"github-blue-ocean\uc5d0\uc11c-\ud30c\uc774\ud504\ub77c\uc778-\uc0dd\uc131\uc5d0-\ud544\uc694\ud55c-github-token-\uc0dd\uc131",children:"[Github] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131"}),"\n",(0,i.jsxs)(n.p,{children:["repo, user",":email"," \uad8c\ud55c\uc774 \uc788\ub294 \ud1a0\ud070\uc774 \ud544\uc694\ud558\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-\ube14\ub8e8-\uc624\uc158-\uc2dc\uc791",children:"[Jenkins] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean1",src:s(29666).Z+"",width:"2390",height:"1372"})}),"\n",(0,i.jsxs)(n.p,{children:["\ube14\ub8e8 \uc624\uc158 \uc5f4\uae30\ub85c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc0dd\uc131\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud1a0\ud070 \uc785\ub825 \u2192 \uc870\uc9c1 \uc120\ud0dd \u2192 CI/CD \uc124\uc815\ud560 Repository \uc120\ud0dd\uc744 \ud558\uba74 \ud30c\uc774\ud504\ub77c\uc778 \ucc3d\uc73c\ub85c \ub118\uc5b4\uac04\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Jenkinsfile\uc744 \uc9c1\uc811 \uc791\uc131\ud558\uc5ec \uc124\uc815\ud558\uae30 \uc704\ud574 \uac04\ub2e8\ud558\uac8c print \ud558\ub098 \ucd9c\ub825\ud558\ub294 \uac83\uc73c\ub85c \uc124\uc815\ud588\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean2",src:s(49614).Z+"",width:"2076",height:"638"})}),"\n",(0,i.jsx)(n.p,{children:"\ud30c\uc774\ud504\ub77c\uc778\uc774 \uc2e4\ud589\ub420 \ud150\ub370 pipeline status\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ucd08\ub85d\ubd88\uc774 \ub728\uba74 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean3",src:s(71079).Z+"",width:"1084",height:"626"})}),"\n",(0,i.jsx)(n.h3,{id:"github-repsoitory-jenkinsfile-\uc124\uc815",children:"[Github Repsoitory] Jenkinsfile \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:"\ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\uc744 \ud1b5\ud574 \uc124\uc815\ud558\uba74 Jenkinsfile\uc774 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc9c0\uace0, \uc544\ub798\uc640 \uac19\uc774 \uc6d0\ud558\ub294 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc124\uc815\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"pipeline {\n agent any\n stages {\n stage('build and test') {\n steps {\n sh '/gradlew clean build'\n }\n }\n stage('zip') {\n steps {\n sh 'mv ./build/libs/woowachat.jar .'\n sh 'zip -r woowachat.zip .platform delivery.jar Procfile'\n }\n }\n stage('upload') {\n steps {\n sh 'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2'\n }\n }\n stage('deploy') {\n steps {\n sh 'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket=\"woowa-chat\",S3Key=\"woowachat.zip\"'\n sh 'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}'\n }\n }\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"github-webhooks-\uc124\uc815",children:"[Github] Webhooks \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"github-hook",src:s(36642).Z+"",width:"1428",height:"1148"})}),"\n",(0,i.jsxs)(n.p,{children:["push \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud560 \ub54c ",(0,i.jsx)(n.code,{children:"http://Jenkins\uc8fc\uc18c/github-webhook/"})," \ub85c post request\ub97c \ud558\ub3c4\ub85d \uc6f9\ud6c5\uc744 \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos",children:"Install Jenkins - CentOS, Jenkins"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/",children:"Nginx Reverse Proxy Configuration, Jenkins"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html",children:"Amazon Corretto 17 JDK Install, AWS"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/linux/al2023/release-notes/all-packages-al2023-20230419.html",children:"Amazon Linux 2023 packages, AWS"})]})]})}function h(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3905:(e,n,s)=>{s.d(n,{ah:()=>c});var i=s(67294);function t(e,n,s){return n in e?Object.defineProperty(e,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[n]=s,e}function a(e,n){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),s.push.apply(s,i)}return s}function r(e){for(var n=1;n=0||(t[s]=e[s]);return t}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,s)&&(t[s]=e[s])}return t}var o=i.createContext({}),c=function(e){var n=i.useContext(o),s=n;return e&&(s="function"==typeof e?e(n):r(r({},n),e)),s},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},h=i.forwardRef((function(e,n){var s=e.components,t=e.mdxType,a=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),p=c(s),u=t,j=p["".concat(o,".").concat(u)]||p[u]||d[u]||a;return s?i.createElement(j,r(r({ref:n},h),{},{components:s})):i.createElement(j,r({ref:n},h))}));h.displayName="MDXCreateElement"},30618:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam1-e6d63be6b9f41d63e91d604138e6b07c.png"},56786:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam2-557683fc91b1c22330d081d6050dfe82.png"},63303:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam3-94248e9194dd58bb16d0289af47a4260.png"},82150:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam4-54ccc5a4e64d31f7eeab89d39ebf772f.png"},36238:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-s3-757380d36e5492c962f75dae024994e5.png"},36642:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/github-hook-e9ebe0acb3ff0086ecebbd8c857ffe39.png"},29666:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean1-bd108d887d700ea081e4b0a3d83ad459.png"},49614:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean2-408c6c90e4a5371becc4d1013fba1212.png"},71079:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean3-4050a206b3efe95a3c9f39c3f7a47ad7.png"},71399:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-start-dce0d7051054c398d2a707c75c685234.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4091],{8343:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var i=s(85893),t=s(3905);const a={title:"Jenkins\ub85c CI/CD \uc124\uc815",slug:"jenkins",tags:["Jenkins","Elastic Beanstalk"]},r=void 0,l={permalink:"/jenkins",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",source:"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",title:"Jenkins\ub85c CI/CD \uc124\uc815",description:"\uc124\uc815 \ud658\uacbd",date:"2023-04-30T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 30\uc77c",tags:[{label:"Jenkins",permalink:"/tags/jenkins"},{label:"Elastic Beanstalk",permalink:"/tags/elastic-beanstalk"}],readingTime:7.495,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Jenkins\ub85c CI/CD \uc124\uc815",slug:"jenkins",tags:["Jenkins","Elastic Beanstalk"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",permalink:"/tecochat-retrospective-1"},nextItem:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",permalink:"/tecochat-retrospective-2"}},o={authorsImageUrls:[]},c=[{value:"\uc124\uc815 \ud658\uacbd",id:"\uc124\uc815-\ud658\uacbd",level:3},{value:"[EC2 CLI] Swap \uba54\ubaa8\ub9ac \uc124\uc815",id:"ec2-cli-swap-\uba54\ubaa8\ub9ac-\uc124\uc815",level:3},{value:"[EC2 CLI] jenkins \uc124\uce58",id:"ec2-cli-jenkins-\uc124\uce58",level:3},{value:"[EC2 CLI] Jenkins \uc2dc\uc791",id:"ec2-cli-jenkins-\uc2dc\uc791",level:3},{value:"[EC2 CLI] nginx & git \uc124\uce58",id:"ec2-cli-nginx--git-\uc124\uce58",level:3},{value:"[EC2 CLI] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815",id:"ec2-cli-nginx-\ub9ac\ubc84\uc2a4-\ud504\ub85d\uc2dc-\uc124\uc815",level:3},{value:"[Jenkins] Jenkins \uc811\uc18d",id:"jenkins-jenkins-\uc811\uc18d",level:3},{value:"[Jenkins] Jenkins Blue Ocean \uc124\uce58",id:"jenkins-jenkins-blue-ocean-\uc124\uce58",level:3},{value:"[AWS IAM & EC2] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30",id:"aws-iam--ec2-iam\uc73c\ub85c-ec2-\uc778\uc2a4\ud134\uc2a4-\uad8c\ud55c-\uc124\uc815\ud558\uae30",level:3},{value:"[AWS S3] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131",id:"aws-s3-jar-\ud30c\uc77c\uc744-\uc5c5\ub85c\ub4dc-\ud560-s3-\ubc84\ud0b7-\uc0dd\uc131",level:3},{value:"[Github] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131",id:"github-blue-ocean\uc5d0\uc11c-\ud30c\uc774\ud504\ub77c\uc778-\uc0dd\uc131\uc5d0-\ud544\uc694\ud55c-github-token-\uc0dd\uc131",level:3},{value:"[Jenkins] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791",id:"jenkins-\ube14\ub8e8-\uc624\uc158-\uc2dc\uc791",level:3},{value:"[Github Repsoitory] Jenkinsfile \uc124\uc815",id:"github-repsoitory-jenkinsfile-\uc124\uc815",level:3},{value:"[Github] Webhooks \uc124\uc815",id:"github-webhooks-\uc124\uc815",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",br:"br",code:"code",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"\uc124\uc815-\ud658\uacbd",children:"\uc124\uc815 \ud658\uacbd"}),"\n",(0,i.jsxs)(n.p,{children:["\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc774\ubbf8\uc9c0: Amazon Linux 2023 AMI",(0,i.jsx)(n.br,{}),"\n","\uc544\ud0a4\ud14d\uccd0: ARM",(0,i.jsx)(n.br,{}),"\n","\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small",(0,i.jsx)(n.br,{}),"\n","\ud658\uacbd \uad6c\uc131\uc774 \uc644\ub8cc\ub41c Elastic Beanstalk",(0,i.jsx)(n.br,{}),"\n","\ub2e8\uc77c Spring Boot \ud504\ub85c\uc81d\ud2b8\uac00 \uc874\uc7ac\ud558\ub294 Github Repository"]}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-swap-\uba54\ubaa8\ub9ac-\uc124\uc815",children:"[EC2 CLI] Swap \uba54\ubaa8\ub9ac \uc124\uc815"}),"\n",(0,i.jsxs)(n.p,{children:["t4g.small\uc774 \ub7a8\uc774 2G\uc778\ub370 \ub7a8\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \ub290\uaef4\uc838\uc11c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc544\ub798 \uba85\ub839\uc5b4\ub97c \ub530\ub77c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud558\uace0 free -h \uba85\ub839\uc5b4\ub97c \ud1b5\ud574 \uc798 \uc124\uc815\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# fallocate \uc774\uc6a9\ud558\uc5ec \uc2a4\uc651 \ud30c\uc77c \uc0dd\uc131\nsudo fallocate -l 2G /swapfile\n\n# \uad8c\ud55c \uc124\uc815\nsudo chmod 600 /swapfile\n\n# \ud30c\uc77c\uc744 Swap \ud3ec\ub9f7\uc73c\ub85c \ubcc0\uacbd \ud6c4 \uc2dc\uc2a4\ud15c\uc5d0 \ub4f1\ub85d\nsudo mkswap /swapfile\nsudo swapon /swapfile\n\n# Swap \uba54\ubaa8\ub9ac \ubd80\ud305\uc2dc \uc790\ub3d9\uc73c\ub85c \ub9c8\uc6b4\ud2b8\ud558\ub3c4\ub85d \uc801\uc6a9\n# \ucd5c\ud558\ub2e8\uc5d0 \ub2e4\uc74c \uad6c\ubb38 \uc124\uc815 -> /swapfile swap swap defaults 0 0\nsudo vim /etc/fstab\n"})}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-jenkins-\uc124\uce58",children:"[EC2 CLI] jenkins \uc124\uce58"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo wget -O /etc/yum.repos.d/jenkins.repo \\\n https://pkg.jenkins.io/redhat-stable/jenkins.repo\nsudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key\nsudo yum upgrade\nsudo yum install java-17-amazon-corretto-devel\nsudo yum install jenkins\nsudo systemctl daemon-reload\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos",children:"Jenkins \uacf5\uc2dd \ud648\ud398\uc774\uc9c0"})," \ub97c \ucc38\uace0\ud558\uc5ec \uc124\uce58\ud558\ub294 \uac8c \uc88b\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-jenkins-\uc2dc\uc791",children:"[EC2 CLI] Jenkins \uc2dc\uc791"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo systemctl enable jenkins\nsudo systemctl start jenkins\n"})}),"\n",(0,i.jsx)(n.p,{children:"enable\ub85c \uc124\uc815\ud558\uc5ec \ubd80\ud305\uc2dc \uc790\ub3d9\uc2dc\uc791 \ub418\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-nginx--git-\uc124\uce58",children:"[EC2 CLI] nginx & git \uc124\uce58"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sudo yum install nginx\nsudo systemctl enable nginx\nsudo systemctl start nginx\n\nsudo yum install git\n"})}),"\n",(0,i.jsx)(n.p,{children:"nginx\uc640 \ucf54\ub4dc\ub97c \ubd88\ub7ec\uc62c \ub54c \uc0ac\uc6a9\ud560 git\uc744 \uc124\uce58\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"ec2-cli-nginx-\ub9ac\ubc84\uc2a4-\ud504\ub85d\uc2dc-\uc124\uc815",children:"[EC2 CLI] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:"\uc544\ub798 \uc124\uc815 \ud30c\uc77c\uc740 \uacf5\uc2dd \ud648\ud398\uc774\uc9c0\uc5d0\uc11c \uc548\ub0b4\ud55c \uae30\ubcf8\uc801\uc778 \uc124\uc815 \ud30c\uc77c\uc774\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'upstream jenkins {\n keepalive 32; # keepalive connections\n server 127.0.0.1:8080; # jenkins ip and port\n}\n\n# Required for Jenkins websocket agents\nmap $http_upgrade $connection_upgrade {\n default upgrade;\n \'\' close;\n}\n\nserver {\n listen 80; # Listen on port 80 for IPv4 requests\n\n server_name jenkins.example.com; # replace \'jenkins.example.com\' with your server domain name\n\n # this is the jenkins web root directory\n # (mentioned in the output of "systemctl cat jenkins")\n root /var/run/jenkins/war/;\n\n access_log /var/log/nginx/jenkins.access.log;\n error_log /var/log/nginx/jenkins.error.log;\n\n # pass through headers from Jenkins that Nginx considers invalid\n ignore_invalid_headers off;\n\n location ~ "^/static/[0-9a-fA-F]{8}\\/(.*)$" {\n # rewrite all static files into requests to the root\n # E.g /static/12345678/css/something.css will become /css/something.css\n rewrite "^/static/[0-9a-fA-F]{8}\\/(.*)" /$1 last;\n }\n\n location /userContent {\n # have nginx handle all the static requests to userContent folder\n # note : This is the $JENKINS_HOME dir\n root /var/lib/jenkins/;\n if (!-f $request_filename){\n # this file does not exist, might be a directory or a /**view** url\n rewrite (.*) /$1 last;\n break;\n }\n sendfile on;\n }\n\n location / {\n sendfile off;\n proxy_pass http://jenkins;\n proxy_redirect default;\n proxy_http_version 1.1;\n\n # Required for Jenkins websocket agents\n proxy_set_header Connection $connection_upgrade;\n proxy_set_header Upgrade $http_upgrade;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_max_temp_file_size 0;\n\n #this is the maximum upload size\n client_max_body_size 10m;\n client_body_buffer_size 128k;\n\n proxy_connect_timeout 90;\n proxy_send_timeout 90;\n proxy_read_timeout 90;\n proxy_buffering off;\n proxy_request_buffering off; # Required for HTTP CLI commands\n proxy_set_header Connection ""; # Clear for keepalive\n }\n\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Jenkins\ub294 8080 \ud3ec\ud2b8\ub85c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc\ub97c \uc124\uc815\ud574\uc900\ub2e4.",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.code,{children:"/etc/nginx/conf.d"}),"\xa0\uc544\ub798\xa0",(0,i.jsx)(n.code,{children:"default.conf"}),"\xa0\ud30c\uc77c\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uace0 \uc704\uc640 \uac19\uc774 \uc785\ub825\ud558\uace0 \uc800\uc7a5\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","nginx\uc758 \uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\uc5d0 \uc874\uc7ac\ud558\ub294\xa0",(0,i.jsx)(n.code,{children:"include /etc/nginx/conf.d/*.conf;"}),"\xa0\uc124\uc815 \ub54c\ubb38\uc5d0\xa0",(0,i.jsx)(n.code,{children:".conf"}),"\xa0\ub85c \ub05d\ub09c\ub2e4\uba74 \uc124\uc815\uc774 \uc801\uc6a9\ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc124\uc815 \ud6c4\xa0",(0,i.jsx)(n.code,{children:"sudo nginx -t"}),"\ub85c \uc124\uc815\ud30c\uc77c\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud558\uace0,\xa0",(0,i.jsx)(n.code,{children:"sudo systemctl restart nginx"}),"\xa0\uba85\ub839\uc5b4\ub85c nginx\ub97c \uc7ac\uc2dc\uc791\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-jenkins-\uc811\uc18d",children:"[Jenkins] Jenkins \uc811\uc18d"}),"\n",(0,i.jsxs)(n.p,{children:["Jenkins\ub97c \uc124\uce58\ud55c EC2 \uc778\uc2a4\ud134\uc2a4 \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc5d0 80\ubc88 \ud3ec\ud2b8\uac00 \uc5f4\ub824\uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","EC2\uc758 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \ub4e4\uc5b4\uac00\uba74 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-start",src:s(71399).Z+"",width:"2008",height:"1836"})}),"\n",(0,i.jsxs)(n.p,{children:["\ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud558\ub294\ub370 ",(0,i.jsx)(n.code,{children:"sudo cat /var/lib/jenkins/secrets/initialAdminPasswor"})," \ub97c \uc785\ub825\ud574 \ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc5bb\uc744 \uc218 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 \ud50c\ub7ec\uadf8\uc778 \uc124\uc815 \ucc3d\uc774 \ub098\uc62c\ud150\ub370 ",(0,i.jsx)(n.code,{children:"install suggested plugins"}),"\uc744 \ud074\ub9ad\ud558\uc5ec Jenkins\uac00 \ucd94\ucc9c\ud558\ub294 \uae30\ubcf8 \ud50c\ub7ec\uadf8\uc778\ub4e4\uc744 \uc124\uce58\ud558\uba74 \ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud50c\ub7ec\uadf8\uc778\uc744 \uc124\uce58\ud558\uba74 \uacc4\uc815 \ubc0f \uc8fc\uc18c \uc124\uc815\uc744 \ud574\uc57c\ud558\ub294\ub370 \uc774\uac74 \ud3b8\ud558\uac8c \uc124\uc815\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-jenkins-blue-ocean-\uc124\uce58",children:"[Jenkins] Jenkins Blue Ocean \uc124\uce58"}),"\n",(0,i.jsx)(n.p,{children:"Jenkins \uad00\ub9ac \u2192 Plugin Manager\uc5d0\uc11c Blue Ocean\uc744 \uac80\uc0c9\ud574 \uc124\uce58\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"aws-iam--ec2-iam\uc73c\ub85c-ec2-\uc778\uc2a4\ud134\uc2a4-\uad8c\ud55c-\uc124\uc815\ud558\uae30",children:"[AWS IAM & EC2] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30"}),"\n",(0,i.jsxs)(n.p,{children:["S3\uc640 Elastic Beanstalk\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub824\uba74 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk \ub450 \uac1c\uc758 \uc815\ucc45\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uc5ed\ud560\uc744 \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","IAM\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc774 \uc5ed\ud560\uc744 \ud558\ub098 \uc0c8\ub85c \uc0dd\uc131\ud55c\ub2e4."]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"\uc5d4\ud130\ud2f0 \uc120\ud0dd"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam1",src:s(30618).Z+"",width:"2282",height:"1028"})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsx)(n.li,{children:"\uad8c\ud55c \ucd94\uac00"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam2",src:s(56786).Z+"",width:"2300",height:"880"})}),"\n",(0,i.jsxs)(n.ol,{start:"3",children:["\n",(0,i.jsx)(n.li,{children:"\uc774\ub984 \uc9c0\uc815, \uac80\ud1a0 \ubc0f \uc0dd\uc131"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam3",src:s(63303).Z+"",width:"1872",height:"1724"})}),"\n",(0,i.jsxs)(n.ol,{start:"4",children:["\n",(0,i.jsx)(n.li,{children:"\uc0dd\uc131\ud55c IAM EC2 Jenkins \uc778\uc2a4\ud134\uc2a4\ub97c \uc120\ud0dd\ud558\uace0, \uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc744 \ub20c\ub7ec Role \uc124\uc815"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-iam4",src:s(82150).Z+"",width:"2264",height:"602"})}),"\n",(0,i.jsx)(n.h3,{id:"aws-s3-jar-\ud30c\uc77c\uc744-\uc5c5\ub85c\ub4dc-\ud560-s3-\ubc84\ud0b7-\uc0dd\uc131",children:"[AWS S3] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131"}),"\n",(0,i.jsx)(n.p,{children:"\ubc84\ud0b7\uc744 \uc0dd\uc131\ud560 \ub54c \ub2e4\uc74c \uc124\uc815\uc744 \uc81c\uc678\ud558\uace0 \ubaa8\ub450 \ucc28\ub2e8 \ud65c\uc131\ud654\ub97c \ud574\uc900\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"\uc0c8 ACL(\uc561\uc138\uc2a4 \uc81c\uc5b4 \ubaa9\ub85d)\uc744 \ud1b5\ud574 \ubd80\uc5ec\ub41c \ubc84\ud0b7 \ubc0f \uac1d\uccb4\uc5d0 \ub300\ud55c \ud37c\ube14\ub9ad \uc561\uc138\uc2a4 \ucc28\ub2e8"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"aws-s3",src:s(36238).Z+"",width:"1636",height:"1258"})}),"\n",(0,i.jsx)(n.h3,{id:"github-blue-ocean\uc5d0\uc11c-\ud30c\uc774\ud504\ub77c\uc778-\uc0dd\uc131\uc5d0-\ud544\uc694\ud55c-github-token-\uc0dd\uc131",children:"[Github] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131"}),"\n",(0,i.jsxs)(n.p,{children:["repo, user",":email"," \uad8c\ud55c\uc774 \uc788\ub294 \ud1a0\ud070\uc774 \ud544\uc694\ud558\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"jenkins-\ube14\ub8e8-\uc624\uc158-\uc2dc\uc791",children:"[Jenkins] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean1",src:s(29666).Z+"",width:"2390",height:"1372"})}),"\n",(0,i.jsxs)(n.p,{children:["\ube14\ub8e8 \uc624\uc158 \uc5f4\uae30\ub85c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc0dd\uc131\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud1a0\ud070 \uc785\ub825 \u2192 \uc870\uc9c1 \uc120\ud0dd \u2192 CI/CD \uc124\uc815\ud560 Repository \uc120\ud0dd\uc744 \ud558\uba74 \ud30c\uc774\ud504\ub77c\uc778 \ucc3d\uc73c\ub85c \ub118\uc5b4\uac04\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Jenkinsfile\uc744 \uc9c1\uc811 \uc791\uc131\ud558\uc5ec \uc124\uc815\ud558\uae30 \uc704\ud574 \uac04\ub2e8\ud558\uac8c print \ud558\ub098 \ucd9c\ub825\ud558\ub294 \uac83\uc73c\ub85c \uc124\uc815\ud588\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean2",src:s(49614).Z+"",width:"2076",height:"638"})}),"\n",(0,i.jsx)(n.p,{children:"\ud30c\uc774\ud504\ub77c\uc778\uc774 \uc2e4\ud589\ub420 \ud150\ub370 pipeline status\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ucd08\ub85d\ubd88\uc774 \ub728\uba74 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"jenkins-blue-ocean3",src:s(71079).Z+"",width:"1084",height:"626"})}),"\n",(0,i.jsx)(n.h3,{id:"github-repsoitory-jenkinsfile-\uc124\uc815",children:"[Github Repsoitory] Jenkinsfile \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:"\ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\uc744 \ud1b5\ud574 \uc124\uc815\ud558\uba74 Jenkinsfile\uc774 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc9c0\uace0, \uc544\ub798\uc640 \uac19\uc774 \uc6d0\ud558\ub294 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc124\uc815\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"pipeline {\n agent any\n stages {\n stage('build and test') {\n steps {\n sh '/gradlew clean build'\n }\n }\n stage('zip') {\n steps {\n sh 'mv ./build/libs/woowachat.jar .'\n sh 'zip -r woowachat.zip .platform delivery.jar Procfile'\n }\n }\n stage('upload') {\n steps {\n sh 'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2'\n }\n }\n stage('deploy') {\n steps {\n sh 'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket=\"woowa-chat\",S3Key=\"woowachat.zip\"'\n sh 'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}'\n }\n }\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"github-webhooks-\uc124\uc815",children:"[Github] Webhooks \uc124\uc815"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"github-hook",src:s(36642).Z+"",width:"1428",height:"1148"})}),"\n",(0,i.jsxs)(n.p,{children:["push \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud560 \ub54c ",(0,i.jsx)(n.code,{children:"http://Jenkins\uc8fc\uc18c/github-webhook/"})," \ub85c post request\ub97c \ud558\ub3c4\ub85d \uc6f9\ud6c5\uc744 \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos",children:"Install Jenkins - CentOS, Jenkins"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/",children:"Nginx Reverse Proxy Configuration, Jenkins"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html",children:"Amazon Corretto 17 JDK Install, AWS"}),(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/linux/al2023/release-notes/all-packages-al2023-20230419.html",children:"Amazon Linux 2023 packages, AWS"})]})]})}function h(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3905:(e,n,s)=>{s.d(n,{ah:()=>c});var i=s(67294);function t(e,n,s){return n in e?Object.defineProperty(e,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[n]=s,e}function a(e,n){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),s.push.apply(s,i)}return s}function r(e){for(var n=1;n=0||(t[s]=e[s]);return t}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,s)&&(t[s]=e[s])}return t}var o=i.createContext({}),c=function(e){var n=i.useContext(o),s=n;return e&&(s="function"==typeof e?e(n):r(r({},n),e)),s},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},h=i.forwardRef((function(e,n){var s=e.components,t=e.mdxType,a=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),p=c(s),u=t,j=p["".concat(o,".").concat(u)]||p[u]||d[u]||a;return s?i.createElement(j,r(r({ref:n},h),{},{components:s})):i.createElement(j,r({ref:n},h))}));h.displayName="MDXCreateElement"},30618:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam1-e6d63be6b9f41d63e91d604138e6b07c.png"},56786:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam2-557683fc91b1c22330d081d6050dfe82.png"},63303:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam3-94248e9194dd58bb16d0289af47a4260.png"},82150:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-iam4-54ccc5a4e64d31f7eeab89d39ebf772f.png"},36238:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/aws-s3-757380d36e5492c962f75dae024994e5.png"},36642:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/github-hook-e9ebe0acb3ff0086ecebbd8c857ffe39.png"},29666:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean1-bd108d887d700ea081e4b0a3d83ad459.png"},49614:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean2-408c6c90e4a5371becc4d1013fba1212.png"},71079:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-blue-ocean3-4050a206b3efe95a3c9f39c3f7a47ad7.png"},71399:(e,n,s)=>{s.d(n,{Z:()=>i});const i=s.p+"assets/images/jenkins-start-dce0d7051054c398d2a707c75c685234.png"}}]); \ No newline at end of file diff --git a/assets/js/b41adc00.633c89b0.js b/assets/js/b41adc00.70ad5b86.js similarity index 97% rename from assets/js/b41adc00.633c89b0.js rename to assets/js/b41adc00.70ad5b86.js index 1ba90e545..835cc1b62 100644 --- a/assets/js/b41adc00.633c89b0.js +++ b/assets/js/b41adc00.70ad5b86.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1391],{33849:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(85893),a=n(3905);const o={title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"jdbc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/jdbc-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-jdbc/pull/267",date:"2023-10-10T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 10\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.83,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"jdbc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",permalink:"/refactoring-retrospective"},nextItem:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/mvc-retrospective"}},s={authorsImageUrls:[]},l=[{value:"Jdbc \uad6c\ud604",id:"jdbc-\uad6c\ud604",level:3},{value:"JdbcTemplate",id:"jdbctemplate",level:3},{value:"\ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9",id:"\ud2b8\ub79c\uc7ad\uc158-\uc801\uc6a9",level:3},{value:"\ub9c8\ubb34\ub9ac",id:"\ub9c8\ubb34\ub9ac",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,r.jsxs)(t.p,{children:["1\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267"}),(0,r.jsx)(t.br,{}),"\n","2\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358"}),(0,r.jsx)(t.br,{}),"\n","3\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448"}),(0,r.jsx)(t.br,{}),"\n","4\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515"})]})}),"\n",(0,r.jsx)(t.h3,{id:"jdbc-\uad6c\ud604",children:"Jdbc \uad6c\ud604"}),"\n",(0,r.jsxs)(t.p,{children:["\uc774\ubc88 \ubbf8\uc158\uc740 Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uace0, Transaction \uacbd\uacc4 \uc124\uc815\uacfc \ub3d9\uae30\ud654\ud558\ub294 \ubd80\ubd84\uc744 \uad6c\ud604\ud574 \ubcf4\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ubbf8\uc158 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"JDBC \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uba74\uc11c \uc911\ubcf5\uc744 \uc81c\uac70\ud558\ub294 \uc5f0\uc2b5\uc744 \ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\ub97c \ub192\uc778\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"\ucd5c\ub300\ud55c Java\uac00 \uc81c\uacf5\ud558\ub294 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud588\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"jdbctemplate",children:"JdbcTemplate"}),"\n",(0,r.jsxs)(t.p,{children:["JdbcTemplate\uc740 Connection\uc744 \uc774\uc6a9\ud558\uc5ec PreparedStatement\ub97c \uc0dd\uc131\ud558\ub294 \ubd80\ubd84, \uadf8\ub9ac\uace0 PreparedStatement\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ubd84\ub9ac\ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc801\uc808\ud558\uac8c \uc801\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \ube44\uad50\uc801 \uac04\ub2e8\ud558\uac8c \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608\uc804\uc5d0\ub3c4 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c ",(0,r.jsx)(t.a,{href:"./custom-jdbc-template",children:"JdbcTemplate\uc744 \uad6c\ud604"}),"\ud55c \uc801\uc774 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \uc790\uc6d0 \ud560\ub2f9\uacfc \ud574\uc81c \ubd80\ubd84\uc5d0 \ub300\ud55c \uc911\ubcf5\ub3c4 \uc81c\uac70\ud588\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:'public class JdbcTemplate {\n\n private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);\n\n private final DataSource dataSource;\n private final StatementCreator statementCreator;\n private final StatementExecutor statementExecutor;\n\n public JdbcTemplate(final DataSource dataSource) {\n this(dataSource, new StatementCreator(), new StatementExecutor());\n }\n\n JdbcTemplate(\n final DataSource dataSource,\n final StatementCreator statementCreator,\n final StatementExecutor statementExecutor\n ) {\n this.dataSource = dataSource;\n this.statementCreator = statementCreator;\n this.statementExecutor = statementExecutor;\n }\n\n private T query(\n final String sql,\n final PreparedStatementCallback preparedStatementCallback,\n final Object... parameters\n ) {\n final Connection connection = DataSourceUtils.getConnection(dataSource);\n try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {\n return preparedStatementCallback.execute(preparedStatement);\n } catch (final SQLException e) {\n log.error(e.getMessage(), e);\n throw new DataAccessException(e);\n } finally {\n DataSourceUtils.releaseConnection(connection, dataSource);\n }\n }\n\n public void update(final String sql, final Object... parameters) {\n query(sql, PreparedStatement::executeUpdate, parameters);\n }\n\n public Optional queryForObject(final String sql, final RowMapper rowMapper, final Object... parameters) {\n final List results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\n if (results.size() > 1) {\n throw new DataAccessException("2\uac1c \uc774\uc0c1\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.");\n }\n return results.stream().findAny();\n }\n\n public List queryForList(final String sql, final RowMapper rowMapper, final Object... parameters) {\n return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\n }\n}\n'})}),"\n",(0,r.jsx)(t.h3,{id:"\ud2b8\ub79c\uc7ad\uc158-\uc801\uc6a9",children:"\ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9"}),"\n",(0,r.jsxs)(t.p,{children:["3, 4\ub2e8\uacc4\ub294 \uae30\uc874\uc758 \ucf54\ub4dc\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uace0 \ub05d\ub098\ub294 \ubd80\ubd84\uc778 \ud2b8\ub79c\uc7ad\uc158 \uacbd\uacc4\ub97c \uc124\uc815\ud558\uace0 ThreadLocal\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654(Transaction synchronization)\ub97c \uc801\uc6a9\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654\ub780 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uae30 \uc704\ud55c Connection \uac1d\uccb4\ub97c ThreadLocal\uacfc \uac19\uc740 \uacf5\uac04\uc5d0 \ub530\ub85c \uc800\uc7a5 \ud6c4, \ud544\uc694\ud560 \ub54c \uc800\uc7a5\ub41c Connection\uc744 \uac00\uc838\ub2e4 \uc0ac\uc6a9\ud558\ub294 \ubc29\uc2dd\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub294\ub370, ThreadLocal\uc5d0 Connection \uac1d\uccb4\uac00 \uc544\ub2cc, Connection \uac1d\uccb4\uc640 Transaction\uc774 \uc9c4\ud589 \uc911\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 flag\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \uc800\uc7a5\ud574\uc11c \uc0ac\uc6a9\ud558\ub3c4\ub85d \ud588\ub2e4."]}),"\n",(0,r.jsx)(t.mermaid,{value:"graph LR\n\tTransactionTemplate --\x3e TransactionManager\n\tTransactionManager --\x3e TransactionSynchronizationManager\n\tDataSourceUtils --\x3e TransactionSynchronizationManager\n\tJdbcTemplate --\x3e DataSourceUtils"}),"\n",(0,r.jsx)(t.h3,{id:"\ub9c8\ubb34\ub9ac",children:"\ub9c8\ubb34\ub9ac"}),"\n",(0,r.jsxs)(t.p,{children:["Jdbc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c AOP\ub098 Transactional\uc5d0 \ub300\ud55c \ud559\uc2b5 \ud14c\uc2a4\ud2b8\ub3c4 \uc9c4\ud589\ud558\uace0, \uc57d\uac04 \uc54c\ucc2c \ubbf8\uc158\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uaf3c\uaf3c\ud788 \ucf54\ub4dc\ub97c \ubd10\uc900 \ub9ac\ubdf0\uc5b4 \ud638\uc774 \uadf8\ub9ac\uace0 \uc5f0\ud734 \ub3d9\uc548 \uacc4\uc18d \ud2f0\ud0a4\ud0c0\uce74 \ud558\uba74\uc11c \uc7ac\ubc0c\uac8c \ub9ac\ubdf0\ud55c \ubbfc\ud2b8\uc5d0\uac8c \uac10\uc0ac\ud558\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud68c\uace0 \uc774\ub9cc \ub05d\ub0b4\uace0 \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud558\ub7ec\uac00\uc57c\uaca0\ub2e4. \ud83d\ude0a"]})]})}function d(e={}){const{wrapper:t}={...(0,a.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>l});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),u=l(n),b=a,m=u["".concat(s,".").concat(b)]||u[b]||p[b]||o;return n?r.createElement(m,c(c({ref:t},d),{},{components:n})):r.createElement(m,c({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1391],{33849:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(85893),a=n(3905);const o={title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"jdbc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,i={permalink:"/jdbc-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/jwp-dashboard-jdbc/pull/267",date:"2023-10-10T00:00:00.000Z",formattedDate:"2023\ub144 10\uc6d4 10\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.83,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"jdbc-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/mvc-retrospective"},nextItem:{title:"\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0",permalink:"/refactoring-retrospective"}},s={authorsImageUrls:[]},l=[{value:"Jdbc \uad6c\ud604",id:"jdbc-\uad6c\ud604",level:3},{value:"JdbcTemplate",id:"jdbctemplate",level:3},{value:"\ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9",id:"\ud2b8\ub79c\uc7ad\uc158-\uc801\uc6a9",level:3},{value:"\ub9c8\ubb34\ub9ac",id:"\ub9c8\ubb34\ub9ac",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,r.jsxs)(t.p,{children:["1\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267"}),(0,r.jsx)(t.br,{}),"\n","2\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358"}),(0,r.jsx)(t.br,{}),"\n","3\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448"}),(0,r.jsx)(t.br,{}),"\n","4\ub2e8\uacc4: ",(0,r.jsx)(t.a,{href:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515",children:"https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515"})]})}),"\n",(0,r.jsx)(t.h3,{id:"jdbc-\uad6c\ud604",children:"Jdbc \uad6c\ud604"}),"\n",(0,r.jsxs)(t.p,{children:["\uc774\ubc88 \ubbf8\uc158\uc740 Jdbc \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uace0, Transaction \uacbd\uacc4 \uc124\uc815\uacfc \ub3d9\uae30\ud654\ud558\ub294 \ubd80\ubd84\uc744 \uad6c\ud604\ud574 \ubcf4\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ubbf8\uc158 \ubaa9\ud45c\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"JDBC \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uad6c\ud604\ud558\uba74\uc11c \uc911\ubcf5\uc744 \uc81c\uac70\ud558\ub294 \uc5f0\uc2b5\uc744 \ud55c\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\ub97c \ub192\uc778\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"\ucd5c\ub300\ud55c Java\uac00 \uc81c\uacf5\ud558\ub294 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub9ac\ud329\ud130\ub9c1 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud588\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"jdbctemplate",children:"JdbcTemplate"}),"\n",(0,r.jsxs)(t.p,{children:["JdbcTemplate\uc740 Connection\uc744 \uc774\uc6a9\ud558\uc5ec PreparedStatement\ub97c \uc0dd\uc131\ud558\ub294 \ubd80\ubd84, \uadf8\ub9ac\uace0 PreparedStatement\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ubd84\ub9ac\ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc801\uc808\ud558\uac8c \uc801\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \ube44\uad50\uc801 \uac04\ub2e8\ud558\uac8c \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608\uc804\uc5d0\ub3c4 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c ",(0,r.jsx)(t.a,{href:"./custom-jdbc-template",children:"JdbcTemplate\uc744 \uad6c\ud604"}),"\ud55c \uc801\uc774 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \uc790\uc6d0 \ud560\ub2f9\uacfc \ud574\uc81c \ubd80\ubd84\uc5d0 \ub300\ud55c \uc911\ubcf5\ub3c4 \uc81c\uac70\ud588\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:'public class JdbcTemplate {\n\n private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);\n\n private final DataSource dataSource;\n private final StatementCreator statementCreator;\n private final StatementExecutor statementExecutor;\n\n public JdbcTemplate(final DataSource dataSource) {\n this(dataSource, new StatementCreator(), new StatementExecutor());\n }\n\n JdbcTemplate(\n final DataSource dataSource,\n final StatementCreator statementCreator,\n final StatementExecutor statementExecutor\n ) {\n this.dataSource = dataSource;\n this.statementCreator = statementCreator;\n this.statementExecutor = statementExecutor;\n }\n\n private T query(\n final String sql,\n final PreparedStatementCallback preparedStatementCallback,\n final Object... parameters\n ) {\n final Connection connection = DataSourceUtils.getConnection(dataSource);\n try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {\n return preparedStatementCallback.execute(preparedStatement);\n } catch (final SQLException e) {\n log.error(e.getMessage(), e);\n throw new DataAccessException(e);\n } finally {\n DataSourceUtils.releaseConnection(connection, dataSource);\n }\n }\n\n public void update(final String sql, final Object... parameters) {\n query(sql, PreparedStatement::executeUpdate, parameters);\n }\n\n public Optional queryForObject(final String sql, final RowMapper rowMapper, final Object... parameters) {\n final List results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\n if (results.size() > 1) {\n throw new DataAccessException("2\uac1c \uc774\uc0c1\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.");\n }\n return results.stream().findAny();\n }\n\n public List queryForList(final String sql, final RowMapper rowMapper, final Object... parameters) {\n return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);\n }\n}\n'})}),"\n",(0,r.jsx)(t.h3,{id:"\ud2b8\ub79c\uc7ad\uc158-\uc801\uc6a9",children:"\ud2b8\ub79c\uc7ad\uc158 \uc801\uc6a9"}),"\n",(0,r.jsxs)(t.p,{children:["3, 4\ub2e8\uacc4\ub294 \uae30\uc874\uc758 \ucf54\ub4dc\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uace0 \ub05d\ub098\ub294 \ubd80\ubd84\uc778 \ud2b8\ub79c\uc7ad\uc158 \uacbd\uacc4\ub97c \uc124\uc815\ud558\uace0 ThreadLocal\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654(Transaction synchronization)\ub97c \uc801\uc6a9\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158 \ub3d9\uae30\ud654\ub780 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud558\uae30 \uc704\ud55c Connection \uac1d\uccb4\ub97c ThreadLocal\uacfc \uac19\uc740 \uacf5\uac04\uc5d0 \ub530\ub85c \uc800\uc7a5 \ud6c4, \ud544\uc694\ud560 \ub54c \uc800\uc7a5\ub41c Connection\uc744 \uac00\uc838\ub2e4 \uc0ac\uc6a9\ud558\ub294 \ubc29\uc2dd\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub294\ub370, ThreadLocal\uc5d0 Connection \uac1d\uccb4\uac00 \uc544\ub2cc, Connection \uac1d\uccb4\uc640 Transaction\uc774 \uc9c4\ud589 \uc911\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 flag\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \uc800\uc7a5\ud574\uc11c \uc0ac\uc6a9\ud558\ub3c4\ub85d \ud588\ub2e4."]}),"\n",(0,r.jsx)(t.mermaid,{value:"graph LR\n\tTransactionTemplate --\x3e TransactionManager\n\tTransactionManager --\x3e TransactionSynchronizationManager\n\tDataSourceUtils --\x3e TransactionSynchronizationManager\n\tJdbcTemplate --\x3e DataSourceUtils"}),"\n",(0,r.jsx)(t.h3,{id:"\ub9c8\ubb34\ub9ac",children:"\ub9c8\ubb34\ub9ac"}),"\n",(0,r.jsxs)(t.p,{children:["Jdbc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c AOP\ub098 Transactional\uc5d0 \ub300\ud55c \ud559\uc2b5 \ud14c\uc2a4\ud2b8\ub3c4 \uc9c4\ud589\ud558\uace0, \uc57d\uac04 \uc54c\ucc2c \ubbf8\uc158\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uaf3c\uaf3c\ud788 \ucf54\ub4dc\ub97c \ubd10\uc900 \ub9ac\ubdf0\uc5b4 \ud638\uc774 \uadf8\ub9ac\uace0 \uc5f0\ud734 \ub3d9\uc548 \uacc4\uc18d \ud2f0\ud0a4\ud0c0\uce74 \ud558\uba74\uc11c \uc7ac\ubc0c\uac8c \ub9ac\ubdf0\ud55c \ubbfc\ud2b8\uc5d0\uac8c \uac10\uc0ac\ud558\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud68c\uace0 \uc774\ub9cc \ub05d\ub0b4\uace0 \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud558\ub7ec\uac00\uc57c\uaca0\ub2e4. \ud83d\ude0a"]})]})}function d(e={}){const{wrapper:t}={...(0,a.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>l});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),u=l(n),b=a,m=u["".concat(s,".").concat(b)]||u[b]||p[b]||o;return n?r.createElement(m,c(c({ref:t},d),{},{components:n})):r.createElement(m,c({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/b6ffb0cb.4afb0eea.js b/assets/js/b6ffb0cb.13ba99fe.js similarity index 98% rename from assets/js/b6ffb0cb.4afb0eea.js rename to assets/js/b6ffb0cb.13ba99fe.js index 200a67677..d6a068f19 100644 --- a/assets/js/b6ffb0cb.4afb0eea.js +++ b/assets/js/b6ffb0cb.13ba99fe.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2156],{1738:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>i,default:()=>x,frontMatter:()=>s,metadata:()=>c,toc:()=>l});var t=n(85893),a=n(3905);const s={title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",slug:"racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/racing-car-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-racingcar/pull/510",date:"2023-02-14T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 14\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.625,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",slug:"racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",permalink:"/ladder-retrospective"},nextItem:{title:"Parameterized Tests",permalink:"/parameterized-tests"}},o={authorsImageUrls:[]},l=[{value:"\uc790\ub3d9\ucc28 \uacbd\uc8fc",id:"\uc790\ub3d9\ucc28-\uacbd\uc8fc",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",hr:"hr",li:"li",mermaid:"mermaid",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-racingcar/pull/510",children:"https://github.com/woowacourse/java-racingcar/pull/510"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-racingcar/pull/538",children:"https://github.com/woowacourse/java-racingcar/pull/538"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\uc790\ub3d9\ucc28-\uacbd\uc8fc",children:"\uc790\ub3d9\ucc28 \uacbd\uc8fc"}),"\n",(0,t.jsxs)(r.p,{children:["\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158\uc5d0\uc11c\ub294 \ub2e4\uc990\uacfc \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\ud14c\ucf54 \ub4e4\uc5b4\uc640\uc11c \uccab \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\uc774\ub77c \ub9ce\uc774 \ub5a8\ub838\uc9c0\ub9cc, \ub2e4\uc990\uc774 \ub300\ud654\ub97c \uc798 \uc774\ub04c\uc5b4\uc918 \ub108\ubb34 \uc990\uac70\uc6e0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uccab\ub0a0\uc740 \uac04\ub2e8\ud788 \ucee8\ubca4\uc158\uacfc \ud658\uacbd\uc744 \uc124\uc815\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc84c\uace0 \ub2e4\uc74c \ub0a0\ubd80\ud130 \uc790\ub3d9\ucc28 \uacbd\uc8fc\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc2dc\uc791\uc740 \uac04\ub2e8\ud558\uac8c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud558\uace0, \uc5b4\ub5bb\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud560\uc9c0 \uac19\uc774 \uace0\ubbfc\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc2dc\uc791\ud558\uae30 \uc804 \uc544\ub798\uc640 \uac19\uc774 mermaid\ub97c \uc774\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc5d0 \ub300\ud574\uc11c \uac04\ub2e8\ud55c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \ub9cc\ub4e4\uace0 \uc2dc\uc791\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","mermaid\ub294 \ucf54\ub4dc\ub85c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \uc0dd\uc131 \ud574\uc8fc\ub294 \ub3c4\uad6c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc774 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"\ucf54\ub4dc \uae30\ubc18\uc774\ub77c \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \uc0dd\uac01\ud55c \uac83\uc744 \uc2dc\uac01\ud654\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(r.li,{children:"github\uc5d0\uc11c mermaid\ub97c \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \ucf54\ub4dc\ub97c \uc774\ud574\ud560 \uc218 \uc788\ub294 \ubd80\uac00\uc801\uc778 \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(r.mermaid,{value:"---\ntitle: \uc790\ub3d9\ucc28 \uacbd\uc8fc \uccab \ub9ac\ubdf0 \uc694\uccad\uc2dc \uad6c\uc870\n---\ngraph TD\n Cars --\x3e Car\n Car --\x3e Name\n Car --\x3e Position\n RacingGame --\x3e Count\n RacingGame --\x3e NumberGenerator\n RacingGame --\x3e Cars\n RacingCarController --\x3e RacingGame\n RandomNumberGenerator -.-> NumberGenerator\n RacingCarController --\x3e InputView\n InputView --\x3e InputValidator\n RacingCarController --\x3e OutputView"}),"\n",(0,t.jsx)(r.p,{children:"\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \ub370 \ud070 \uc5b4\ub824\uc6c0\uc774 \uc788\uc9c0\ub294 \uc54a\uc558\uace0, \ud398\uc5b4\ub97c \ub9c8\uce58\uae30 \uc804 \uc11c\ub85c \uace0\ubbfc\ub418\ub294 \ubd80\ubd84\uc744 \uc815\ub9ac\ud588\uc744 \ub54c \uc88b\uc558\ub2e4."}),"\n",(0,t.jsxs)(r.p,{children:["\ud398\uc5b4\ud558\uba74\uc11c \uc798\ud588\ub2e4\uace0 \uc0dd\uac01\ud588\ub358 \uc810\uc740 \uc11c\ub85c\uc758 \uc0dd\uac01\uacfc \ub9ac\ubdf0 \ubc1b\uc740 \uac83\uc744 \uacf5\uc720\ud55c \uac83\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub9ac\ud329\ud130\ub9c1\uc744 \uc5b4\ub5bb\uac8c \ud588\ub294\uc9c0? \uc774\ub7f0 \ub9ac\ubdf0\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \uc0dd\uac01\ud558\ub294\uc9c0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c8 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\ub9ac\ud329\ud130\ub9c1\uc774 \ub05d\ub09c \ud6c4 \uba54\uc11c\ub4dc\uba85, \ud14c\uc2a4\ud2b8\uc2dc \ucd9c\ub825\ud558\ub294 \uba54\uc2dc\uc9c0\uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\uac00 \ub9ce\uc774 \ub2ec\ub838\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uac1d\uccb4\uac00 \uc5b4\ub5a4 \ucc45\uc784\uacfc \uc5ed\ud560\uc744 \uac00\uc9c0\ub294\uc9c0 \uc0dd\uac01\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uba85\ud655\ud55c \uba54\uc11c\ub4dc\uba85\uc744 \uc791\uc131\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ud3c9\uc18c\uc5d0 \ud504\ub85c\uadf8\ub798\ubc0d \uc774\uc57c\uae30\uac00 \uc544\ub2cc \ub2e4\ub978 \uc8fc\uc81c\ub85c \uc774\uc57c\uae30\ud558\uba74 \uc798 \ub4e4\uc73c\ub824\uace0 \ud558\ub294 \ud3b8\uc774\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \uc88b\uc544\ud558\ub294 \uc8fc\uc81c, \uad00\uc2ec\uac00\ub294 \uc8fc\uc81c\uc778 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub97c \ud560 \ub550 \ub9d0\uc774 \ub9ce\uc544\uc9c4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130\ub294 \ub354 \ub9ce\uc740 \uc2dc\uac04\uc744 \ud398\uc5b4\uc758 \uc758\uacac\uacfc \uc774\uc57c\uae30\ub97c \ub4e3\ub294 \uacf3\uc5d0 \uc0ac\uc6a9\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Assertions extracting"})}),"\n",(0,t.jsxs)(r.p,{children:["\uacb0\uacfc \ub0b4\ubd80\uc5d0 \uc788\ub294 \uac12\uc744 \ud655\uc778\ud558\uace0 \uc2f6\uc744 \ub54c extracting \ud0a4\uc6cc\ub4dc\ub97c \uc774\uc6a9\ud574\uc11c \ub0b4\ubd80\uc758 \uac12\uc744 \uac80\uc99d\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0\ub294 \ud544\uc694\uc5d0 \ub530\ub77c stream\uc744 \uc774\uc6a9\ud558\uc5ec \uac80\uc99d\ud560 \uac12\uc744 \uc0dd\uc131\ud588\uc9c0\ub9cc, \ud574\ub2f9 \ubc29\ubc95\uc744 \uc774\uc6a9\ud574\uc11c \uc808\ucc28\ub97c \uc904\uc77c \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'@Test\nvoid extracting() {\n final Cars cars = new Cars(List.of("car1", "car2"));\n\n assertThat(cars.getCars())\n .extracting(Car::getName)\n .containsExactly("car1", "car2");\n}\n'})}),"\n",(0,t.jsx)(r.hr,{}),"\n",(0,t.jsx)(r.p,{children:"\uc544\ub798\ub294 \ub9ac\ubdf0\uc5b4\ub2d8\uacfc \ub300\ud654\ub97c \ub098\ub204\uba74\uc11c \uc5bb\uc740 \ub2f5\ubcc0 + \ub098\uc758 \uc758\uacac\uc774\ub2e4."}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8"})}),"\n",(0,t.jsxs)(r.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc0c1\uc774 \uac80\uc99d\ub41c \uac83\uc774\ub77c\uba74 \uc791\uc131\ud558\uc9c0 \uc54a\uac70\ub098, \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uc791\uc131\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uac74 \uac1c\uc778\uc801\uc778 \uc0dd\uac01\uc774\uc9c0\ub9cc \ub0b4\uac00 \uc548\uc815\uac10\uc774 \ub4e4 \uc218 \uc788\uc744 \uc815\ub3c4\ub85c \ucd9c\ub825 \ubc94\uc704 \ub0b4\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud558\ub294\uc9c0 \uc815\ub3c4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub2e8\uc21c \uc704\uc784\uc744 \ud558\ub294 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc704\uc784\uc774\ub77c\ub294 \uac83\uc740 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc99d\ud558\ub294 \uac83\ubcf4\ub2e4 \uacb0\uacfc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub2e8\uc21c\ud788 \uc704\uc784\ub9cc \ud558\ub294 \ud14c\uc2a4\ud2b8\uc758 \uacbd\uc6b0 \uacb0\uacfc\ub97c \uac80\uc99d\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc911\ubcf5\ub418\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \uc911\ubcf5\ub41c \ud14c\uc2a4\ud2b8\ub97c \uc904\uc774\uae30 \uc704\ud574 \ub0b4\ubd80\uc758 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0 \uac80\uc99d\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\ub294 \uac83\uc744 \uc54c\uac8c \ub418\uc5c8\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\uc548\uc815\uc801\uc73c\ub85c \uacb0\uacfc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c getter \uc0ac\uc6a9"})}),"\n",(0,t.jsxs)(r.p,{children:["\ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\ub85c \ub3c4\uba54\uc778\uc5d0 \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc740 \uc88b\uc9c0 \ubabb\ud558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud544\uc694\uc758 \uacbd\uc6b0 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc9c0\ub9cc, \uae30\uc874\uc5d0 \uc788\ub294 \uba54\uc11c\ub4dc\ub4e4\uc744 \ud65c\uc6a9\ud574\ubcf4\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub9e4\uc6b0 \ub3d9\uc758\ud558\uace0, \uc55e\uc73c\ub85c\ub3c4 \ucd5c\ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \ucf54\ub4dc\ub97c \ub3c4\uba54\uc778\uc5d0 \uc791\uc131\ud558\uc9c0 \uc54a\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\uc9c8\ubb38\uc774\ub098 \uc0dd\uac01\ud560 \uc810\uc774 \uc788\uc744 \ub54c \ub9e4\uc6b0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc0dd\uac01\uc744 \uc815\ub9ac\ud55c \ud6c4 \uc790\uc2e0\uc758 \uc758\uacac\uc744 \uba85\ub8cc\ud558\uac8c \uc804\ub2ec\ud574\uc8fc\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc2dd\uc744 \ud6a8\uc728\uc801\uc73c\ub85c \uc2b5\ub4dd\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub09c \uc0dd\uac01\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc740 \ucc44\ub85c \ub0b4\ubc84\ub824 \ub454 \uc595\uc740 \uc9c0\uc2dd\uc774 \ub9ce\uc740 \uac83 \uac19\ub2e4. (\uc774\ub7f0 \uac83\ub3c4 \uc544\ub294 \uac83\uc774\ub77c\uace0 \ud560 \uc218 \uc788\uc744\uae4c?)",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc870\uae08 \ub354 \uba38\ub9bf\uc18d\uc5d0\uc11c \uc815\ub9ac\ud558\uace0, \ubb38\uc81c\uc5d0 \ub300\ud574 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \ub298\ub824\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uac1c\ubc1c\uc5d0 \uc5f4\uc815\uc744 \uac00\uc9c4 \uac8c \ub290\uaef4\uc9c4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \uac1c\ubc1c\uc744 \uc88b\uc544\ud558\uc9c0\ub9cc, \ucd5c\uadfc\uc5d0\ub294 \uc758\uc9c0\uac00 \uc57d\ud574\uc84c\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc5f4\uc815\uc774 \uac00\ub4dd\ud55c \uc0ac\ub78c\uc744 \ub9cc\ub098\ub2c8 \ub098\ub3c4 \uc5f4\uc815\uc801\uc778 \uc0ac\ub78c\uc774 \ub418\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uce6d\ucc2c\uc744 \ub9ce\uc774 \ud574\uc900\ub2e4. \ub2e8\uc21c\ud788 \ub9ce\uc774 \ud574\uc8fc\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc9c4\uc2ec\uc744 \ub2f4\uae34 \uce6d\ucc2c\uc744 \ud574\uc92c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uce6d\ucc2c\uc740 \uace0\ub798\ub3c4 \ucda4\ucd94\uac8c \ud558\ub358\uac00?",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\uc11c \uc990\uac70\uc6b4 \ub9c8\uc74c\uc73c\ub85c \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud588\uc5c8\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc5b4\ub5a4 \uc774\uc720 \ub54c\ubb38\uc778\uc9c0 \ubaa8\ub974\uaca0\uc9c0\ub9cc \uac19\uc774 \ud398\uc5b4\ud558\ub294\ub370 \ud3b8\ud55c \ub9c8\uc74c\uc774 \ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uac74 \ubc14\ub85c \ubc30\uc6b8 \uc218 \uc5c6\uc9c0\ub9cc.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \uac19\uc774 \uc77c\ud560 \ub54c \ud3b8\ud55c \uc0ac\ub78c, \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub418\uae30 \uc704\ud574 \uae4a\uc774 \uace0\ubbfc\ud574\ubd10\uc57c\uaca0\ub2e4."]})]})}function x(e={}){const{wrapper:r}={...(0,a.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function a(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function s(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(a[n]=e[n]);return a}(e,r);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var o=t.createContext({}),l=function(e){var r=t.useContext(o),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},x=t.forwardRef((function(e,r){var n=e.components,a=e.mdxType,s=e.originalType,o=e.parentName,x=c(e,["components","mdxType","originalType","parentName"]),d=l(n),j=a,h=d["".concat(o,".").concat(j)]||d[j]||p[j]||s;return n?t.createElement(h,i(i({ref:r},x),{},{components:n})):t.createElement(h,i({ref:r},x))}));x.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2156],{1738:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>i,default:()=>x,frontMatter:()=>s,metadata:()=>c,toc:()=>l});var t=n(85893),a=n(3905);const s={title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",slug:"racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,c={permalink:"/racing-car-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-racingcar/pull/510",date:"2023-02-14T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 14\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:7.625,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",slug:"racing-car-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"Parameterized Tests",permalink:"/parameterized-tests"},nextItem:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",permalink:"/ladder-retrospective"}},o={authorsImageUrls:[]},l=[{value:"\uc790\ub3d9\ucc28 \uacbd\uc8fc",id:"\uc790\ub3d9\ucc28-\uacbd\uc8fc",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function p(e){const r={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",hr:"hr",li:"li",mermaid:"mermaid",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(r.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-racingcar/pull/510",children:"https://github.com/woowacourse/java-racingcar/pull/510"}),(0,t.jsx)(r.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(r.a,{href:"https://github.com/woowacourse/java-racingcar/pull/538",children:"https://github.com/woowacourse/java-racingcar/pull/538"})]})}),"\n",(0,t.jsx)(r.h3,{id:"\uc790\ub3d9\ucc28-\uacbd\uc8fc",children:"\uc790\ub3d9\ucc28 \uacbd\uc8fc"}),"\n",(0,t.jsxs)(r.p,{children:["\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158\uc5d0\uc11c\ub294 \ub2e4\uc990\uacfc \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc6b0\ud14c\ucf54 \ub4e4\uc5b4\uc640\uc11c \uccab \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\uc774\ub77c \ub9ce\uc774 \ub5a8\ub838\uc9c0\ub9cc, \ub2e4\uc990\uc774 \ub300\ud654\ub97c \uc798 \uc774\ub04c\uc5b4\uc918 \ub108\ubb34 \uc990\uac70\uc6e0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uccab\ub0a0\uc740 \uac04\ub2e8\ud788 \ucee8\ubca4\uc158\uacfc \ud658\uacbd\uc744 \uc124\uc815\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc84c\uace0 \ub2e4\uc74c \ub0a0\ubd80\ud130 \uc790\ub3d9\ucc28 \uacbd\uc8fc\ub97c \uc2dc\uc791\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc2dc\uc791\uc740 \uac04\ub2e8\ud558\uac8c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud558\uace0, \uc5b4\ub5bb\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud560\uc9c0 \uac19\uc774 \uace0\ubbfc\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc2dc\uc791\ud558\uae30 \uc804 \uc544\ub798\uc640 \uac19\uc774 mermaid\ub97c \uc774\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc5d0 \ub300\ud574\uc11c \uac04\ub2e8\ud55c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \ub9cc\ub4e4\uace0 \uc2dc\uc791\ud588\ub2e4.",(0,t.jsx)(r.br,{}),"\n","mermaid\ub294 \ucf54\ub4dc\ub85c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \uc0dd\uc131 \ud574\uc8fc\ub294 \ub3c4\uad6c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc774 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"\ucf54\ub4dc \uae30\ubc18\uc774\ub77c \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \uc0dd\uac01\ud55c \uac83\uc744 \uc2dc\uac01\ud654\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(r.li,{children:"github\uc5d0\uc11c mermaid\ub97c \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \ucf54\ub4dc\ub97c \uc774\ud574\ud560 \uc218 \uc788\ub294 \ubd80\uac00\uc801\uc778 \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(r.mermaid,{value:"---\ntitle: \uc790\ub3d9\ucc28 \uacbd\uc8fc \uccab \ub9ac\ubdf0 \uc694\uccad\uc2dc \uad6c\uc870\n---\ngraph TD\n Cars --\x3e Car\n Car --\x3e Name\n Car --\x3e Position\n RacingGame --\x3e Count\n RacingGame --\x3e NumberGenerator\n RacingGame --\x3e Cars\n RacingCarController --\x3e RacingGame\n RandomNumberGenerator -.-> NumberGenerator\n RacingCarController --\x3e InputView\n InputView --\x3e InputValidator\n RacingCarController --\x3e OutputView"}),"\n",(0,t.jsx)(r.p,{children:"\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \ub370 \ud070 \uc5b4\ub824\uc6c0\uc774 \uc788\uc9c0\ub294 \uc54a\uc558\uace0, \ud398\uc5b4\ub97c \ub9c8\uce58\uae30 \uc804 \uc11c\ub85c \uace0\ubbfc\ub418\ub294 \ubd80\ubd84\uc744 \uc815\ub9ac\ud588\uc744 \ub54c \uc88b\uc558\ub2e4."}),"\n",(0,t.jsxs)(r.p,{children:["\ud398\uc5b4\ud558\uba74\uc11c \uc798\ud588\ub2e4\uace0 \uc0dd\uac01\ud588\ub358 \uc810\uc740 \uc11c\ub85c\uc758 \uc0dd\uac01\uacfc \ub9ac\ubdf0 \ubc1b\uc740 \uac83\uc744 \uacf5\uc720\ud55c \uac83\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub9ac\ud329\ud130\ub9c1\uc744 \uc5b4\ub5bb\uac8c \ud588\ub294\uc9c0? \uc774\ub7f0 \ub9ac\ubdf0\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \uc0dd\uac01\ud558\ub294\uc9c0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c8 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\ub9ac\ud329\ud130\ub9c1\uc774 \ub05d\ub09c \ud6c4 \uba54\uc11c\ub4dc\uba85, \ud14c\uc2a4\ud2b8\uc2dc \ucd9c\ub825\ud558\ub294 \uba54\uc2dc\uc9c0\uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\uac00 \ub9ce\uc774 \ub2ec\ub838\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uac1d\uccb4\uac00 \uc5b4\ub5a4 \ucc45\uc784\uacfc \uc5ed\ud560\uc744 \uac00\uc9c0\ub294\uc9c0 \uc0dd\uac01\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uba85\ud655\ud55c \uba54\uc11c\ub4dc\uba85\uc744 \uc791\uc131\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\ud3c9\uc18c\uc5d0 \ud504\ub85c\uadf8\ub798\ubc0d \uc774\uc57c\uae30\uac00 \uc544\ub2cc \ub2e4\ub978 \uc8fc\uc81c\ub85c \uc774\uc57c\uae30\ud558\uba74 \uc798 \ub4e4\uc73c\ub824\uace0 \ud558\ub294 \ud3b8\uc774\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\ub0b4\uac00 \uc88b\uc544\ud558\ub294 \uc8fc\uc81c, \uad00\uc2ec\uac00\ub294 \uc8fc\uc81c\uc778 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub97c \ud560 \ub550 \ub9d0\uc774 \ub9ce\uc544\uc9c4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130\ub294 \ub354 \ub9ce\uc740 \uc2dc\uac04\uc744 \ud398\uc5b4\uc758 \uc758\uacac\uacfc \uc774\uc57c\uae30\ub97c \ub4e3\ub294 \uacf3\uc5d0 \uc0ac\uc6a9\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Assertions extracting"})}),"\n",(0,t.jsxs)(r.p,{children:["\uacb0\uacfc \ub0b4\ubd80\uc5d0 \uc788\ub294 \uac12\uc744 \ud655\uc778\ud558\uace0 \uc2f6\uc744 \ub54c extracting \ud0a4\uc6cc\ub4dc\ub97c \uc774\uc6a9\ud574\uc11c \ub0b4\ubd80\uc758 \uac12\uc744 \uac80\uc99d\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0\ub294 \ud544\uc694\uc5d0 \ub530\ub77c stream\uc744 \uc774\uc6a9\ud558\uc5ec \uac80\uc99d\ud560 \uac12\uc744 \uc0dd\uc131\ud588\uc9c0\ub9cc, \ud574\ub2f9 \ubc29\ubc95\uc744 \uc774\uc6a9\ud574\uc11c \uc808\ucc28\ub97c \uc904\uc77c \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'@Test\nvoid extracting() {\n final Cars cars = new Cars(List.of("car1", "car2"));\n\n assertThat(cars.getCars())\n .extracting(Car::getName)\n .containsExactly("car1", "car2");\n}\n'})}),"\n",(0,t.jsx)(r.hr,{}),"\n",(0,t.jsx)(r.p,{children:"\uc544\ub798\ub294 \ub9ac\ubdf0\uc5b4\ub2d8\uacfc \ub300\ud654\ub97c \ub098\ub204\uba74\uc11c \uc5bb\uc740 \ub2f5\ubcc0 + \ub098\uc758 \uc758\uacac\uc774\ub2e4."}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8"})}),"\n",(0,t.jsxs)(r.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc0c1\uc774 \uac80\uc99d\ub41c \uac83\uc774\ub77c\uba74 \uc791\uc131\ud558\uc9c0 \uc54a\uac70\ub098, \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uc791\uc131\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uac74 \uac1c\uc778\uc801\uc778 \uc0dd\uac01\uc774\uc9c0\ub9cc \ub0b4\uac00 \uc548\uc815\uac10\uc774 \ub4e4 \uc218 \uc788\uc744 \uc815\ub3c4\ub85c \ucd9c\ub825 \ubc94\uc704 \ub0b4\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud558\ub294\uc9c0 \uc815\ub3c4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ub2e8\uc21c \uc704\uc784\uc744 \ud558\ub294 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8"})}),"\n",(0,t.jsxs)(r.p,{children:["\uc704\uc784\uc774\ub77c\ub294 \uac83\uc740 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc99d\ud558\ub294 \uac83\ubcf4\ub2e4 \uacb0\uacfc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub2e8\uc21c\ud788 \uc704\uc784\ub9cc \ud558\ub294 \ud14c\uc2a4\ud2b8\uc758 \uacbd\uc6b0 \uacb0\uacfc\ub97c \uac80\uc99d\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc911\ubcf5\ub418\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \uc911\ubcf5\ub41c \ud14c\uc2a4\ud2b8\ub97c \uc904\uc774\uae30 \uc704\ud574 \ub0b4\ubd80\uc758 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0 \uac80\uc99d\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\ub294 \uac83\uc744 \uc54c\uac8c \ub418\uc5c8\uc9c0\ub9cc",(0,t.jsx)(r.br,{}),"\n","\uc548\uc815\uc801\uc73c\ub85c \uacb0\uacfc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc778 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"\ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c getter \uc0ac\uc6a9"})}),"\n",(0,t.jsxs)(r.p,{children:["\ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\ub85c \ub3c4\uba54\uc778\uc5d0 \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc740 \uc88b\uc9c0 \ubabb\ud558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ud544\uc694\uc758 \uacbd\uc6b0 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc9c0\ub9cc, \uae30\uc874\uc5d0 \uc788\ub294 \uba54\uc11c\ub4dc\ub4e4\uc744 \ud65c\uc6a9\ud574\ubcf4\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub9e4\uc6b0 \ub3d9\uc758\ud558\uace0, \uc55e\uc73c\ub85c\ub3c4 \ucd5c\ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \ucf54\ub4dc\ub97c \ub3c4\uba54\uc778\uc5d0 \uc791\uc131\ud558\uc9c0 \uc54a\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(r.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(r.p,{children:["\uc9c8\ubb38\uc774\ub098 \uc0dd\uac01\ud560 \uc810\uc774 \uc788\uc744 \ub54c \ub9e4\uc6b0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc0dd\uac01\uc744 \uc815\ub9ac\ud55c \ud6c4 \uc790\uc2e0\uc758 \uc758\uacac\uc744 \uba85\ub8cc\ud558\uac8c \uc804\ub2ec\ud574\uc8fc\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc2dd\uc744 \ud6a8\uc728\uc801\uc73c\ub85c \uc2b5\ub4dd\ud55c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub09c \uc0dd\uac01\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc740 \ucc44\ub85c \ub0b4\ubc84\ub824 \ub454 \uc595\uc740 \uc9c0\uc2dd\uc774 \ub9ce\uc740 \uac83 \uac19\ub2e4. (\uc774\ub7f0 \uac83\ub3c4 \uc544\ub294 \uac83\uc774\ub77c\uace0 \ud560 \uc218 \uc788\uc744\uae4c?)",(0,t.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc870\uae08 \ub354 \uba38\ub9bf\uc18d\uc5d0\uc11c \uc815\ub9ac\ud558\uace0, \ubb38\uc81c\uc5d0 \ub300\ud574 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \ub298\ub824\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uac1c\ubc1c\uc5d0 \uc5f4\uc815\uc744 \uac00\uc9c4 \uac8c \ub290\uaef4\uc9c4\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \uac1c\ubc1c\uc744 \uc88b\uc544\ud558\uc9c0\ub9cc, \ucd5c\uadfc\uc5d0\ub294 \uc758\uc9c0\uac00 \uc57d\ud574\uc84c\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc5f4\uc815\uc774 \uac00\ub4dd\ud55c \uc0ac\ub78c\uc744 \ub9cc\ub098\ub2c8 \ub098\ub3c4 \uc5f4\uc815\uc801\uc778 \uc0ac\ub78c\uc774 \ub418\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uce6d\ucc2c\uc744 \ub9ce\uc774 \ud574\uc900\ub2e4. \ub2e8\uc21c\ud788 \ub9ce\uc774 \ud574\uc8fc\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc9c4\uc2ec\uc744 \ub2f4\uae34 \uce6d\ucc2c\uc744 \ud574\uc92c\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uce6d\ucc2c\uc740 \uace0\ub798\ub3c4 \ucda4\ucd94\uac8c \ud558\ub358\uac00?",(0,t.jsx)(r.br,{}),"\n","\uadf8\ub798\uc11c \uc990\uac70\uc6b4 \ub9c8\uc74c\uc73c\ub85c \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud588\uc5c8\ub358 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(r.p,{children:["\uc5b4\ub5a4 \uc774\uc720 \ub54c\ubb38\uc778\uc9c0 \ubaa8\ub974\uaca0\uc9c0\ub9cc \uac19\uc774 \ud398\uc5b4\ud558\ub294\ub370 \ud3b8\ud55c \ub9c8\uc74c\uc774 \ub4e4\uc5c8\ub2e4.",(0,t.jsx)(r.br,{}),"\n","\uc774\uac74 \ubc14\ub85c \ubc30\uc6b8 \uc218 \uc5c6\uc9c0\ub9cc.",(0,t.jsx)(r.br,{}),"\n","\ub098\ub3c4 \uac19\uc774 \uc77c\ud560 \ub54c \ud3b8\ud55c \uc0ac\ub78c, \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub418\uae30 \uc704\ud574 \uae4a\uc774 \uace0\ubbfc\ud574\ubd10\uc57c\uaca0\ub2e4."]})]})}function x(e={}){const{wrapper:r}={...(0,a.ah)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,r,n)=>{n.d(r,{ah:()=>l});var t=n(67294);function a(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function s(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(a[n]=e[n]);return a}(e,r);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var o=t.createContext({}),l=function(e){var r=t.useContext(o),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},x=t.forwardRef((function(e,r){var n=e.components,a=e.mdxType,s=e.originalType,o=e.parentName,x=c(e,["components","mdxType","originalType","parentName"]),d=l(n),j=a,h=d["".concat(o,".").concat(j)]||d[j]||p[j]||s;return n?t.createElement(h,i(i({ref:r},x),{},{components:n})):t.createElement(h,i({ref:r},x))}));x.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/bace0b37.f928003e.js b/assets/js/bace0b37.8f6c96e7.js similarity index 98% rename from assets/js/bace0b37.f928003e.js rename to assets/js/bace0b37.8f6c96e7.js index dda77075f..f8327a971 100644 --- a/assets/js/bace0b37.f928003e.js +++ b/assets/js/bace0b37.8f6c96e7.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2362],{10795:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>o});var t=r(85893),c=r(3905);const i={title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",slug:"accidental-duplication",tags:["DTO"]},s=void 0,l={permalink:"/accidental-duplication",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",source:"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",description:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",date:"2023-05-24T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 24\uc77c",tags:[{label:"DTO",permalink:"/tags/dto"}],readingTime:7.525,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",slug:"accidental-duplication",tags:["DTO"]},unlisted:!1,prevItem:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",permalink:"/subway-retrospective"},nextItem:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",permalink:"/shopping-cart-retrospective"}},a={authorsImageUrls:[]},o=[{value:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815",id:"\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158\uc5d0\uc11c\uc758-\uc0c1\ud488-\ucd94\uac00-\ubc0f-\uc218\uc815",level:3},{value:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",id:"\uc911\ubcf5\uacfc-\uc6b0\ubc1c\uc801-\uc911\ubcf5",level:3},{value:"\ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c",id:"\ud558\ub098\ub85c-\uc0ac\uc6a9\ud558\ub294-\uac74-\uc548\uc88b\uc544\ubcf4\uc774\uace0-\uc911\ubcf5\uc740-\uc81c\uac70\ud558\uace0-\uc2f6\uc740-\ub9c8\uc74c",level:3},{value:"\uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc",id:"\uc911\ubcf5-\uc81c\uac70-\uc804-\ucf54\ub4dc",level:3},{value:"\uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30",id:"\uc778\ud130\ud398\uc774\uc2a4-\uc791\uc131\ud558\uae30",level:3},{value:"\uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30",id:"\uad6c\ud604\uccb4-\uc791\uc131\ud558\uae30",level:3},{value:"\uc815\ub9ac",id:"\uc815\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,c.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uccad\uc5d0 \ub2f4\uae34 Body\ub97c \ud1b5\ud574 \uc804\ub2ec\ubc1b\uc740 \uac12\uc744 DTO\ub85c \ub9e4\ud551\ud558\uc5ec \ucd94\uac00\uc640 \uc218\uc815\uc744 \ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158\uc5d0\uc11c\uc758-\uc0c1\ud488-\ucd94\uac00-\ubc0f-\uc218\uc815",children:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf51",src:r(92725).Z+"",width:"2028",height:"704"})}),"\n",(0,t.jsxs)(n.p,{children:["\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d\ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0\uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc704 \uacbd\uc6b0\ub294 \uc911\ubcf5\uc77c\uae4c? \uc911\ubcf5\uc774 \uc544\ub2d0\uae4c?"]}),"\n",(0,t.jsx)(n.p,{children:"\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ub9ac\ubdf0\ub97c \ubc1b\uc558\ub2e4."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ProductSaveRequest"}),"\uc640 ",(0,t.jsx)(n.code,{children:"ProductUpdateRequest"}),"\uac00 \uc644\uc804\ud788 \ub3d9\uc77c\ud55c\ub370, \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc744\uae4c? \ub77c\ub294 \ub9ac\ubdf0\ub97c \ub0a8\uacbc\uc5c8\uc5b4\uc694. \uc0ac\uc2e4 \uc0dd\uc131\uacfc \uc218\uc815\uc740 \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac1c\uc5f0\uc131\uc774 \ub192\uc544\uc11c \ubbf8\ub9ac \ubd84\ub9ac\ud574\ub193\ub294 \uac8c \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\uae34 \ud55c\ub370, \uadf8\ub798\ub3c4 \uc911\ubcf5\uc740 \uc2eb\uc5b4\uc11c \uc800\ub3c4 \uc694\uc998 \uc774\ub7f0\uc800\ub7f0 \ubc29\ubc95\ub4e4\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub294 \uc911 \uc785\ub2c8\ub2e4. \ud5c8\ube0c\ub294 \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc5b4\ub5a4 \uc0dd\uac01\uc744 \uac00\uc9c0\uace0 \uc788\uc744\uc9c0 \uad81\uae08\ud558\ub124\uc694 \u314e\u314e"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc9c8\ubb38\uc5d0 \ub300\ud574 \uc544\ub798\uc640 \uac19\uc774 \ub2f5\ubcc0\uc744 \ud588\ub2e4."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc800\uc7a5\uacfc \uc218\uc815\ud560 \ub54c \ud544\uc694\ud55c \ud544\ub4dc\uac12\uc774 \ub3d9\uc77c\ud558\uc5ec \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c\ub294 \ud558\ub098\ub85c \uc0ac\uc6a9\ud574\ub3c4 \ub41c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud558\uc9c0\ub9cc, \ub9d0\uc500\ud574\uc8fc\uc2e0\ub300\ub85c \uc694\uad6c\uc0ac\ud56d\uc774 \ubcc0\uacbd\ub41c\ub2e4\uba74 \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\ub2e4\uace0 \ud310\ub2e8\ud558\uc600\uc2b5\ub2c8\ub2e4!"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc911\ubcf5\uacfc-\uc6b0\ubc1c\uc801-\uc911\ubcf5",children:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5"}),"\n",(0,t.jsx)(n.p,{children:"\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec\uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uac70\uc9d3\ub41c \uc911\ubcf5, \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131\uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc704 \uc0c1\ud669\uc740 \uc6b0\ubc1c\uc801 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc778\ub2e4. \uadf8\ub798\ub3c4 \uc911\ubcf5\uc744 \uc81c\uac70\ud574\ubcfc \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?"}),"\n",(0,t.jsx)(n.h3,{id:"\ud558\ub098\ub85c-\uc0ac\uc6a9\ud558\ub294-\uac74-\uc548\uc88b\uc544\ubcf4\uc774\uace0-\uc911\ubcf5\uc740-\uc81c\uac70\ud558\uace0-\uc2f6\uc740-\ub9c8\uc74c",children:"\ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c0\uae08\uc740 \ucd94\uac00, \uc218\uc815 2\uac00\uc9c0 \uacbd\uc6b0 \ubc16\uc5d0 \uc5c6\uc9c0\ub9cc \uc870\uae08 \ub354 \ubcf5\uc7a1\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc8fc\uc5b4\uc838\uc11c 10\uac00\uc9c0 \uacbd\uc6b0\ub85c \uc785\ub825\uc744 \ubc1b\uc73c\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c?",(0,t.jsx)(n.br,{}),"\n","\uc11c\ube44\uc2a4 \uacc4\uce35\uc5d0\uc11c\ub3c4 \uacc4\uce35\uc758 \ubd84\ub9ac\ub97c \uc704\ud574\uc11c \ub2e4\ub978 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uba74 20\uac1c\uc758 DTO\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud560\uae4c?",(0,t.jsx)(n.br,{}),"\n","\ub9ac\ubdf0\uc5b4\uac00 \uc54c\ub824\uc900 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud55c \ubc29\ubc95\uc744 \ud1b5\ud574 \uc774\ub97c \ud574\uacb0\ud574\ubcf4\uc790!"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc911\ubcf5-\uc81c\uac70-\uc804-\ucf54\ub4dc",children:"\uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc"}),"\n",(0,t.jsxs)(n.p,{children:["\ud604\uc7ac \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Controller\uc640 Service\uc5d0\uc11c \uc800\uc7a5, \uc218\uc815\ud560 \ub54c \uac01\uac01\uc758 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.\n\ud604\uc7ac DTO\ub294 controller, service \ud328\ud0a4\uc9c0 \ub0b4\uc5d0 \uc788\ub294 \uac83\uc774 \uc544\ub2c8\ub77c dto\ub77c\ub294 \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\ud558\uace0 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductService\n\u251c\u2500\u2500 dto\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf52",src:r(12314).Z+"",width:"1528",height:"912"})}),"\n",(0,t.jsx)(n.h3,{id:"\uc778\ud130\ud398\uc774\uc2a4-\uc791\uc131\ud558\uae30",children:"\uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf53",src:r(56531).Z+"",width:"1518",height:"904"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc11c\ube44\uc2a4 \ub808\uc774\uc5b4\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uac12\ub4e4\uc744 \uc778\ud130\ud398\uc774\uc2a4\ub85c \uc815\uc758\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 service \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub85c \uc62e\uaca8\uc900\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public interface ProductSaveRequest {\n\n String getName();\n\n String getImage();\n\n Long getPrice();\n}\n\n// ProductService\npublic Long save(final ProductSaveRequest request) {\n final Product product = new Product(request.getName(), request.getImage(), request.getPrice());\n return productDao.saveAndGetId(product);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uad6c\ud604\uccb4-\uc791\uc131\ud558\uae30",children:"\uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf54",src:r(82237).Z+"",width:"1508",height:"896"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c \uc791\uc131\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc791\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uccad\uc740 ProductRequest \ud074\ub798\uc2a4\ub85c \ubc1b\uace0, \uc11c\ube44\uc2a4\uc5d0 \uc804\ub2ec\ud560 \ub550 \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\uc758 \uba85\uc138\ub9cc \ub9de\ucd94\uba74 \ubb38\uc81c\uc5c6\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductController\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductRequest\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'public class ProductRequest implements ProductSaveRequest, ProductUpdateRequest {\n\n @NotBlank(message = "\uc774\ub984\uc740 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.")\n @Size(min = 1, max = 100, message = "\uc774\ub984\uc740 \ucd5c\uc18c {min}\uc790 \uc774\uc0c1, {max}\uc790 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.")\n private final String name;\n\n @NotBlank(message = "\uc774\ubbf8\uc9c0\ub294 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.")\n private final String image;\n\n @Range(message = "\uac00\uaca9\uc740 \ucd5c\uc18c {min}\uc6d0 \uc774\uc0c1, {max}\uc6d0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.")\n private final long price;\n\n public ProductRequest(final String name, final String image, final long price) {\n this.name = name;\n this.image = image;\n this.price = price;\n }\n\n @Override\n public String getName() {\n return name;\n }\n\n @Override\n public String getImage() {\n return image;\n }\n\n @Override\n public long getPrice() {\n return price;\n }\n}\n\n// ProductController\n@PostMapping("/products")\npublic ResponseEntity save(@Valid @RequestBody final ProductRequest request) {\n final Long id = productService.save(request);\n return ResponseEntity.created(URI.create("/products/" + id)).build();\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\uc815\ub9ac",children:"\uc815\ub9ac"}),"\n",(0,t.jsx)(n.p,{children:"\uc704\uc640 \uac19\uc774 \uad6c\ud604\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Service\uc5d0\uc11c \ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc5d0 \ub300\ud55c DTO\ub97c \uc54c\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uacf5\ud1b5\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 DTO\ub97c \uc81c\uc678\ud558\uace0 DTO \ud328\ud0a4\uc9c0\uc5d0 \ub300\ud55c \uacb0\ud569\ub3c4\uac00 \ub0ae\uc544\uc9c0\uace0, \uac01 \ub808\uc774\uc5b4\uc758 \uc751\uc9d1\ub3c4\uac00 \uc99d\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc694\uccad \uac1d\uccb4\ub9cc \ub2e4\ub974\uace0 \uc11c\ube44\uc2a4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ud589\uc704\ub97c \uc218\ud589\ud558\ub294 \uacbd\uc6b0 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc704 \ubc29\ubc95\uc744 \uc9c0\uae08 \ubbf8\uc158\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560\uae4c \ud558\ub2e4\uac00, \ub098\uc911\uc5d0 \ud544\uc694\ud560 \ub54c \uc801\uc6a9\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\uc544\uc11c \ubbf8\uc158\uc5d0\ub294 \uc801\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0c1\ud669\uc5d0 \ub9de\ucdb0 \uc801\uc7ac\uc801\uc18c\uc5d0 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud574\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98 16\uc7a5 \ub3c5\ub9bd\uc131, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://techblog.woowahan.com/2647/",children:"https://techblog.woowahan.com/2647/"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/",children:"https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/"})]})]})}function u(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var t=r(67294);function c(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(c[r]=e[r]);return c}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var a=t.createContext({}),o=function(e){var n=t.useContext(a),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,c=e.mdxType,i=e.originalType,a=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=o(r),h=c,g=p["".concat(a,".").concat(h)]||p[h]||d[h]||i;return r?t.createElement(g,s(s({ref:n},u),{},{components:r})):t.createElement(g,s({ref:n},u))}));u.displayName="MDXCreateElement"},92725:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf51-ccd4f91674b224578f2b295b3fccaf2c.png"},12314:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf52-0b4f9f493909fc139f0e4579f7569a6b.png"},56531:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf53-1b6b93bc790ba29844083df5b70dbd2c.png"},82237:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf54-15b381e0a024487f54608d438e5385f9.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2362],{10795:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>o});var t=r(85893),c=r(3905);const i={title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",slug:"accidental-duplication",tags:["DTO"]},s=void 0,l={permalink:"/accidental-duplication",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",source:"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",description:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",date:"2023-05-24T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 24\uc77c",tags:[{label:"DTO",permalink:"/tags/dto"}],readingTime:7.525,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",slug:"accidental-duplication",tags:["DTO"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0",permalink:"/shopping-cart-retrospective"},nextItem:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",permalink:"/subway-retrospective"}},a={authorsImageUrls:[]},o=[{value:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815",id:"\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158\uc5d0\uc11c\uc758-\uc0c1\ud488-\ucd94\uac00-\ubc0f-\uc218\uc815",level:3},{value:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5",id:"\uc911\ubcf5\uacfc-\uc6b0\ubc1c\uc801-\uc911\ubcf5",level:3},{value:"\ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c",id:"\ud558\ub098\ub85c-\uc0ac\uc6a9\ud558\ub294-\uac74-\uc548\uc88b\uc544\ubcf4\uc774\uace0-\uc911\ubcf5\uc740-\uc81c\uac70\ud558\uace0-\uc2f6\uc740-\ub9c8\uc74c",level:3},{value:"\uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc",id:"\uc911\ubcf5-\uc81c\uac70-\uc804-\ucf54\ub4dc",level:3},{value:"\uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30",id:"\uc778\ud130\ud398\uc774\uc2a4-\uc791\uc131\ud558\uae30",level:3},{value:"\uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30",id:"\uad6c\ud604\uccb4-\uc791\uc131\ud558\uae30",level:3},{value:"\uc815\ub9ac",id:"\uc815\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,c.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uccad\uc5d0 \ub2f4\uae34 Body\ub97c \ud1b5\ud574 \uc804\ub2ec\ubc1b\uc740 \uac12\uc744 DTO\ub85c \ub9e4\ud551\ud558\uc5ec \ucd94\uac00\uc640 \uc218\uc815\uc744 \ud588\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc7a5\ubc14\uad6c\ub2c8-\ubbf8\uc158\uc5d0\uc11c\uc758-\uc0c1\ud488-\ucd94\uac00-\ubc0f-\uc218\uc815",children:"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf51",src:r(92725).Z+"",width:"2028",height:"704"})}),"\n",(0,t.jsxs)(n.p,{children:["\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d\ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0\uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc704 \uacbd\uc6b0\ub294 \uc911\ubcf5\uc77c\uae4c? \uc911\ubcf5\uc774 \uc544\ub2d0\uae4c?"]}),"\n",(0,t.jsx)(n.p,{children:"\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ub9ac\ubdf0\ub97c \ubc1b\uc558\ub2e4."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ProductSaveRequest"}),"\uc640 ",(0,t.jsx)(n.code,{children:"ProductUpdateRequest"}),"\uac00 \uc644\uc804\ud788 \ub3d9\uc77c\ud55c\ub370, \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc744\uae4c? \ub77c\ub294 \ub9ac\ubdf0\ub97c \ub0a8\uacbc\uc5c8\uc5b4\uc694. \uc0ac\uc2e4 \uc0dd\uc131\uacfc \uc218\uc815\uc740 \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac1c\uc5f0\uc131\uc774 \ub192\uc544\uc11c \ubbf8\ub9ac \ubd84\ub9ac\ud574\ub193\ub294 \uac8c \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\uae34 \ud55c\ub370, \uadf8\ub798\ub3c4 \uc911\ubcf5\uc740 \uc2eb\uc5b4\uc11c \uc800\ub3c4 \uc694\uc998 \uc774\ub7f0\uc800\ub7f0 \ubc29\ubc95\ub4e4\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub294 \uc911 \uc785\ub2c8\ub2e4. \ud5c8\ube0c\ub294 \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc5b4\ub5a4 \uc0dd\uac01\uc744 \uac00\uc9c0\uace0 \uc788\uc744\uc9c0 \uad81\uae08\ud558\ub124\uc694 \u314e\u314e"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc9c8\ubb38\uc5d0 \ub300\ud574 \uc544\ub798\uc640 \uac19\uc774 \ub2f5\ubcc0\uc744 \ud588\ub2e4."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc800\uc7a5\uacfc \uc218\uc815\ud560 \ub54c \ud544\uc694\ud55c \ud544\ub4dc\uac12\uc774 \ub3d9\uc77c\ud558\uc5ec \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c\ub294 \ud558\ub098\ub85c \uc0ac\uc6a9\ud574\ub3c4 \ub41c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud558\uc9c0\ub9cc, \ub9d0\uc500\ud574\uc8fc\uc2e0\ub300\ub85c \uc694\uad6c\uc0ac\ud56d\uc774 \ubcc0\uacbd\ub41c\ub2e4\uba74 \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\ub2e4\uace0 \ud310\ub2e8\ud558\uc600\uc2b5\ub2c8\ub2e4!"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc911\ubcf5\uacfc-\uc6b0\ubc1c\uc801-\uc911\ubcf5",children:"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5"}),"\n",(0,t.jsx)(n.p,{children:"\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec\uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uac70\uc9d3\ub41c \uc911\ubcf5, \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131\uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc704 \uc0c1\ud669\uc740 \uc6b0\ubc1c\uc801 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc778\ub2e4. \uadf8\ub798\ub3c4 \uc911\ubcf5\uc744 \uc81c\uac70\ud574\ubcfc \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?"}),"\n",(0,t.jsx)(n.h3,{id:"\ud558\ub098\ub85c-\uc0ac\uc6a9\ud558\ub294-\uac74-\uc548\uc88b\uc544\ubcf4\uc774\uace0-\uc911\ubcf5\uc740-\uc81c\uac70\ud558\uace0-\uc2f6\uc740-\ub9c8\uc74c",children:"\ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c0\uae08\uc740 \ucd94\uac00, \uc218\uc815 2\uac00\uc9c0 \uacbd\uc6b0 \ubc16\uc5d0 \uc5c6\uc9c0\ub9cc \uc870\uae08 \ub354 \ubcf5\uc7a1\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc8fc\uc5b4\uc838\uc11c 10\uac00\uc9c0 \uacbd\uc6b0\ub85c \uc785\ub825\uc744 \ubc1b\uc73c\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c?",(0,t.jsx)(n.br,{}),"\n","\uc11c\ube44\uc2a4 \uacc4\uce35\uc5d0\uc11c\ub3c4 \uacc4\uce35\uc758 \ubd84\ub9ac\ub97c \uc704\ud574\uc11c \ub2e4\ub978 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uba74 20\uac1c\uc758 DTO\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud560\uae4c?",(0,t.jsx)(n.br,{}),"\n","\ub9ac\ubdf0\uc5b4\uac00 \uc54c\ub824\uc900 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud55c \ubc29\ubc95\uc744 \ud1b5\ud574 \uc774\ub97c \ud574\uacb0\ud574\ubcf4\uc790!"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc911\ubcf5-\uc81c\uac70-\uc804-\ucf54\ub4dc",children:"\uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc"}),"\n",(0,t.jsxs)(n.p,{children:["\ud604\uc7ac \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","Controller\uc640 Service\uc5d0\uc11c \uc800\uc7a5, \uc218\uc815\ud560 \ub54c \uac01\uac01\uc758 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.\n\ud604\uc7ac DTO\ub294 controller, service \ud328\ud0a4\uc9c0 \ub0b4\uc5d0 \uc788\ub294 \uac83\uc774 \uc544\ub2c8\ub77c dto\ub77c\ub294 \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\ud558\uace0 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductService\n\u251c\u2500\u2500 dto\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf52",src:r(12314).Z+"",width:"1528",height:"912"})}),"\n",(0,t.jsx)(n.h3,{id:"\uc778\ud130\ud398\uc774\uc2a4-\uc791\uc131\ud558\uae30",children:"\uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf53",src:r(56531).Z+"",width:"1518",height:"904"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc11c\ube44\uc2a4 \ub808\uc774\uc5b4\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uac12\ub4e4\uc744 \uc778\ud130\ud398\uc774\uc2a4\ub85c \uc815\uc758\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 service \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub85c \uc62e\uaca8\uc900\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public interface ProductSaveRequest {\n\n String getName();\n\n String getImage();\n\n Long getPrice();\n}\n\n// ProductService\npublic Long save(final ProductSaveRequest request) {\n final Product product = new Product(request.getName(), request.getImage(), request.getPrice());\n return productDao.saveAndGetId(product);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uad6c\ud604\uccb4-\uc791\uc131\ud558\uae30",children:"\uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"\uc911\ubcf54",src:r(82237).Z+"",width:"1508",height:"896"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c \uc791\uc131\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc791\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc694\uccad\uc740 ProductRequest \ud074\ub798\uc2a4\ub85c \ubc1b\uace0, \uc11c\ube44\uc2a4\uc5d0 \uc804\ub2ec\ud560 \ub550 \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\uc758 \uba85\uc138\ub9cc \ub9de\ucd94\uba74 \ubb38\uc81c\uc5c6\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"\u251c\u2500\u2500 controller\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductController\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductRequest\n\u251c\u2500\u2500 service\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'public class ProductRequest implements ProductSaveRequest, ProductUpdateRequest {\n\n @NotBlank(message = "\uc774\ub984\uc740 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.")\n @Size(min = 1, max = 100, message = "\uc774\ub984\uc740 \ucd5c\uc18c {min}\uc790 \uc774\uc0c1, {max}\uc790 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.")\n private final String name;\n\n @NotBlank(message = "\uc774\ubbf8\uc9c0\ub294 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.")\n private final String image;\n\n @Range(message = "\uac00\uaca9\uc740 \ucd5c\uc18c {min}\uc6d0 \uc774\uc0c1, {max}\uc6d0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.")\n private final long price;\n\n public ProductRequest(final String name, final String image, final long price) {\n this.name = name;\n this.image = image;\n this.price = price;\n }\n\n @Override\n public String getName() {\n return name;\n }\n\n @Override\n public String getImage() {\n return image;\n }\n\n @Override\n public long getPrice() {\n return price;\n }\n}\n\n// ProductController\n@PostMapping("/products")\npublic ResponseEntity save(@Valid @RequestBody final ProductRequest request) {\n final Long id = productService.save(request);\n return ResponseEntity.created(URI.create("/products/" + id)).build();\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\uc815\ub9ac",children:"\uc815\ub9ac"}),"\n",(0,t.jsx)(n.p,{children:"\uc704\uc640 \uac19\uc774 \uad6c\ud604\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Service\uc5d0\uc11c \ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc5d0 \ub300\ud55c DTO\ub97c \uc54c\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uacf5\ud1b5\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 DTO\ub97c \uc81c\uc678\ud558\uace0 DTO \ud328\ud0a4\uc9c0\uc5d0 \ub300\ud55c \uacb0\ud569\ub3c4\uac00 \ub0ae\uc544\uc9c0\uace0, \uac01 \ub808\uc774\uc5b4\uc758 \uc751\uc9d1\ub3c4\uac00 \uc99d\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc694\uccad \uac1d\uccb4\ub9cc \ub2e4\ub974\uace0 \uc11c\ube44\uc2a4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ud589\uc704\ub97c \uc218\ud589\ud558\ub294 \uacbd\uc6b0 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc704 \ubc29\ubc95\uc744 \uc9c0\uae08 \ubbf8\uc158\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560\uae4c \ud558\ub2e4\uac00, \ub098\uc911\uc5d0 \ud544\uc694\ud560 \ub54c \uc801\uc6a9\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\uc544\uc11c \ubbf8\uc158\uc5d0\ub294 \uc801\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0c1\ud669\uc5d0 \ub9de\ucdb0 \uc801\uc7ac\uc801\uc18c\uc5d0 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud574\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98 16\uc7a5 \ub3c5\ub9bd\uc131, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://techblog.woowahan.com/2647/",children:"https://techblog.woowahan.com/2647/"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/",children:"https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/"})]})]})}function u(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var t=r(67294);function c(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(c[r]=e[r]);return c}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var a=t.createContext({}),o=function(e){var n=t.useContext(a),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,c=e.mdxType,i=e.originalType,a=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=o(r),h=c,g=p["".concat(a,".").concat(h)]||p[h]||d[h]||i;return r?t.createElement(g,s(s({ref:n},u),{},{components:r})):t.createElement(g,s({ref:n},u))}));u.displayName="MDXCreateElement"},92725:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf51-ccd4f91674b224578f2b295b3fccaf2c.png"},12314:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf52-0b4f9f493909fc139f0e4579f7569a6b.png"},56531:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf53-1b6b93bc790ba29844083df5b70dbd2c.png"},82237:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/\uc911\ubcf54-15b381e0a024487f54608d438e5385f9.png"}}]); \ No newline at end of file diff --git a/assets/js/bb221eab.15e3f1c0.js b/assets/js/bb221eab.fe82a60c.js similarity index 97% rename from assets/js/bb221eab.15e3f1c0.js rename to assets/js/bb221eab.fe82a60c.js index 14ef885b4..26b24ae40 100644 --- a/assets/js/bb221eab.15e3f1c0.js +++ b/assets/js/bb221eab.fe82a60c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[711],{98886:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var r=n(85893),s=n(3905);const i={title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",slug:"test-double",tags:["Test","Mock"]},l=void 0,c={permalink:"/test-double",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",source:"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",description:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?",date:"2023-04-04T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 4\uc77c",tags:[{label:"Test",permalink:"/tags/test"},{label:"Mock",permalink:"/tags/mock"}],readingTime:4.52,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",slug:"test-double",tags:["Test","Mock"]},unlisted:!1,prevItem:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",permalink:"/transaction-and-isolation"},nextItem:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",permalink:"/java-class-file"}},d={authorsImageUrls:[]},o=[{value:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?",id:"\ud14c\uc2a4\ud2b8-\ub300\uc5ed\uc774\ub780",level:3},{value:"\ub354\ubbf8(Dummy)",id:"\ub354\ubbf8dummy",level:3},{value:"\uc2a4\ud141(Stub)",id:"\uc2a4\ud141stub",level:3},{value:"\uc2a4\ud30c\uc774(Spy)",id:"\uc2a4\ud30c\uc774spy",level:3},{value:"\ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)",id:"\ubaa9-\ubaa8\uc758-\uac1d\uccb4mock",level:3},{value:"\uac00\uc9dc(Fake)",id:"\uac00\uc9dcfake",level:3},{value:"\uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84",id:"\uc0c1\ud638\uc791\uc6a9\uc5d0-\ub530\ub978-\ubaa9\uacfc-\uc2a4\ud141-\uad6c\ubd84",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function a(e){const t={a:"a",admonition:"admonition",br:"br",h3:"h3",mermaid:"mermaid",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\ud14c\uc2a4\ud2b8-\ub300\uc5ed\uc774\ub780",children:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?"}),"\n",(0,r.jsxs)(t.p,{children:["\ubaa8\ub4e0 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \uac00\uc9dc \uc758\uc874\uc131\uc744 \uc758\ubbf8\ud558\uace0, \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud589\ub420 \ub54c \ub2e4\ub978 \uac1d\uccb4\ub97c \ub300\uc2e0\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Gerard Meszaros\uc758 xUnit Test Patterns\ub77c\ub294 \ucc45\uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ub2e4\uc12f \uac00\uc9c0(\ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774, \ubaa9, \ud398\uc774\ud06c)\ub85c \uad6c\ubd84\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \uae30\ubcf8 \uba54\ucee4\ub2c8\uc998\uc740 \ub2e4\ud615\uc131\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc678\ubd80 \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uacbd\uc6b0, \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uace0 \uc678\ubd80 \uc11c\ube44\uc2a4 \ub300\uc2e0 \ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\uc758 \uad6c\ud604\uccb4\ub97c \uc0dd\uc131\ud558\ub294 \uac83\uc774\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.strong,{children:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \ud0c0\uc785 \uacc4\uce35 \uad6c\uc870"})}),"\n",(0,r.jsx)(t.mermaid,{value:"flowchart LR\n Mock --\x3e Spy --\x3e Stub --\x3e Dummy --\x3e TestDouble\n Fake --\x3e TestDouble"}),"\n",(0,r.jsx)(t.h3,{id:"\ub354\ubbf8dummy",children:"\ub354\ubbf8(Dummy)"}),"\n",(0,r.jsxs)(t.p,{children:["\uac00\uc7a5 \ub2e8\uc21c\ud558\uace0, \uc6d0\uc2dc\uc801\uc778 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c \uc544\ubb34 \uc77c\ub3c4 \ud558\uc9c0 \uc54a\ub294 \uad6c\ud604\uccb4\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\uac00 \ud544\uc694\ud55c \uacbd\uc6b0 \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub9cc\uc57d \uba54\uc11c\ub4dc\uac00 \ubb34\uc5b8\uac00 \ubc18\ud658\uc744 \ud574\uc57c\ud558\ub294 \uacbd\uc6b0 0, null\uacfc \uac19\uc740 \uac12\uc744 \ubc18\ud658\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud141stub",children:"\uc2a4\ud141(Stub)"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2dc\ub098\ub9ac\uc624\ub9c8\ub2e4 \ub2e4\ub978 \uac12(\ubbf8\ub9ac \uc900\ube44 \ub41c \uacb0\uacfc)\uc744 \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub97c \ud1b5\ud574 \ud2b9\uc815 \uc870\uac74\uc5d0\uc11c \uba54\uc11c\ub4dc\uac00 \uc608\uc0c1\ud55c\ub300\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud30c\uc774spy",children:"\uc2a4\ud30c\uc774(Spy)"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2a4\ud141\uacfc \uc720\uc0ac\ud558\uc9c0\ub9cc \ud638\ucd9c \uc5ec\ubd80\ub97c \uae30\ub85d\ud558\uac70\ub098 \ud638\ucd9c\ud560 \ub54c \uc804\ub2ec\ud55c \uc778\uc790\uac12\uc744 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608) \uba54\uc77c \uc804\uc1a1 \uae30\ub2a5\uc744 \uac00\uc9c4 \uac1d\uccb4\ub97c \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc73c\ub85c \uad6c\ud604\ud588\uc744 \ub54c \uba54\uc77c \uc804\uc1a1 \ud69f\uc218\ub97c \uae30\ub85d\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ubaa9-\ubaa8\uc758-\uac1d\uccb4mock",children:"\ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)"}),"\n",(0,r.jsxs)(t.p,{children:["\ubaa9\uc740 \ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774\ub97c \ud3ec\ud568\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud638\ucd9c \uc2dc \uc0ac\uc804\uc5d0 \uc815\uc758\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud558\uace0, \uc608\uc0c1\uce58 \ubabb\ud55c \ud638\ucd9c\uc774 \uc788\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub610\ud55c \ud638\ucd9c\uc5d0 \ub300\ud55c \uac80\uc99d\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uac00\uc9dcfake",children:"\uac00\uc9dc(Fake)"}),"\n",(0,r.jsxs)(t.p,{children:["DOC\uc640 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc9c0\ub9cc, \ub354\uc6b1 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ub41c \uac83\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608) \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \ub3d9\uc791\ud558\ub294 \uac00\uc9dc \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"DOC(depended-on component)",type:"note",children:(0,r.jsxs)(t.p,{children:["\uc758\uc874 \uad6c\uc131 \uc694\uc18c, DOC\ub97c \ud14c\uc2a4\ud2b8 \ub354\ube14\ub85c \ub300\uccb4\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8 \ub354\ube14\uc740 DOC\uc640 \ub3d9\uc77c\ud55c API\ub97c \uc81c\uacf5\ud574\uc57c \ud55c\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"\uc0c1\ud638\uc791\uc6a9\uc5d0-\ub530\ub978-\ubaa9\uacfc-\uc2a4\ud141-\uad6c\ubd84",children:"\uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84"}),"\n",(0,r.jsxs)(t.p,{children:["\ub2e8\uc704 \ud14c\uc2a4\ud2b8 p.149 \uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ud06c\uac8c \ubaa9\uacfc \uc2a4\ud141\uc73c\ub85c \uad6c\ubd84\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ubaa9\uc740 SUT\uc640 \uad00\ub828\ub41c \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ubc18\uba74, \uc2a4\ud141\uc740 \ub2e8\uc21c \ubaa8\ubc29\ub9cc \ud55c\ub2e4."]}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"TestDouble"}),(0,r.jsx)(t.th,{children:"Mock"}),(0,r.jsx)(t.th,{children:"Stub"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\ud3ec\ud568 \uc720\ud615"}),(0,r.jsx)(t.td,{children:"\ubaa9, \uc2a4\ud30c\uc774"}),(0,r.jsx)(t.td,{children:"\uc2a4\ud141, \ub354\ubbf8, \ud398\uc774\ud06c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc6a9\ub3c4"}),(0,r.jsx)(t.td,{children:"\uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ub370 \uc0ac\uc6a9"}),(0,r.jsx)(t.td,{children:"\ub0b4\ubd80\ub85c \ub4e4\uc5b4\uc624\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\ub294 \ub370 \uc0ac\uc6a9"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc124\uba85"}),(0,r.jsx)(t.td,{children:"SUT\uac00 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9"}),(0,r.jsx)(t.td,{children:"SUT\uac00 \uc785\ub825 \ub370\uc774\ud130\ub97c \uc5bb\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc608\uc2dc"}),(0,r.jsx)(t.td,{children:"\uc774\uba54\uc77c \ubc1c\uc1a1"}),(0,r.jsx)(t.td,{children:"\ub370\uc774\ud130 \uac80\uc0c9"})]})]})]}),"\n",(0,r.jsx)(t.admonition,{title:"SUT(system under test)",type:"note",children:(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc0c1 \uc2dc\uc2a4\ud15c",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8\ub97c \ud558\ub824\ub294 \ub300\uc0c1"]})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:["\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30 - 3\uc7a5 \uace0\uae09 \ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4",(0,r.jsx)(t.br,{}),"\n","\ub2e8\uc704 \ud14c\uc2a4\ud2b8 - 5\uc7a5 \ubaa9\uacfc \ud14c\uc2a4\ud2b8 \ucde8\uc57d\uc131, \ube14\ub77c\ub514\ubbf8\ub974 \ucf54\ub9ac\ucf54\ud504",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uc2dc\uc791\ud558\uae30 - 7\uc7a5 \ub300\uc5ed, \ucd5c\ubc94\uade0",(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://www.martinfowler.com/bliki/TestDouble.html",children:"\ud14c\uc2a4\ud2b8 \ub354\ube14, Martin Fowler"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://johngrib.github.io/wiki/test-terms/",children:"\ud14c\uc2a4\ud2b8 \uad00\ub828 \uc6a9\uc5b4 \uc815\ub9ac, Johngrib"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"http://xunitpatterns.com/Test%20Double.html",children:"Test Double, Gerard Meszaros"})]})]})}function h(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>o});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var d=r.createContext({}),o=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},a={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,d=e.parentName,h=c(e,["components","mdxType","originalType","parentName"]),j=o(n),x=s,u=j["".concat(d,".").concat(x)]||j[x]||a[x]||i;return n?r.createElement(u,l(l({ref:t},h),{},{components:n})):r.createElement(u,l({ref:t},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[711],{98886:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var r=n(85893),s=n(3905);const i={title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",slug:"test-double",tags:["Test","Mock"]},l=void 0,c={permalink:"/test-double",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",source:"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",description:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?",date:"2023-04-04T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 4\uc77c",tags:[{label:"Test",permalink:"/tags/test"},{label:"Mock",permalink:"/tags/mock"}],readingTime:4.52,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",slug:"test-double",tags:["Test","Mock"]},unlisted:!1,prevItem:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",permalink:"/java-class-file"},nextItem:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",permalink:"/transaction-and-isolation"}},d={authorsImageUrls:[]},o=[{value:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?",id:"\ud14c\uc2a4\ud2b8-\ub300\uc5ed\uc774\ub780",level:3},{value:"\ub354\ubbf8(Dummy)",id:"\ub354\ubbf8dummy",level:3},{value:"\uc2a4\ud141(Stub)",id:"\uc2a4\ud141stub",level:3},{value:"\uc2a4\ud30c\uc774(Spy)",id:"\uc2a4\ud30c\uc774spy",level:3},{value:"\ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)",id:"\ubaa9-\ubaa8\uc758-\uac1d\uccb4mock",level:3},{value:"\uac00\uc9dc(Fake)",id:"\uac00\uc9dcfake",level:3},{value:"\uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84",id:"\uc0c1\ud638\uc791\uc6a9\uc5d0-\ub530\ub978-\ubaa9\uacfc-\uc2a4\ud141-\uad6c\ubd84",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function a(e){const t={a:"a",admonition:"admonition",br:"br",h3:"h3",mermaid:"mermaid",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\ud14c\uc2a4\ud2b8-\ub300\uc5ed\uc774\ub780",children:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?"}),"\n",(0,r.jsxs)(t.p,{children:["\ubaa8\ub4e0 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \uac00\uc9dc \uc758\uc874\uc131\uc744 \uc758\ubbf8\ud558\uace0, \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud589\ub420 \ub54c \ub2e4\ub978 \uac1d\uccb4\ub97c \ub300\uc2e0\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Gerard Meszaros\uc758 xUnit Test Patterns\ub77c\ub294 \ucc45\uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ub2e4\uc12f \uac00\uc9c0(\ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774, \ubaa9, \ud398\uc774\ud06c)\ub85c \uad6c\ubd84\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \uae30\ubcf8 \uba54\ucee4\ub2c8\uc998\uc740 \ub2e4\ud615\uc131\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc678\ubd80 \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uacbd\uc6b0, \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uace0 \uc678\ubd80 \uc11c\ube44\uc2a4 \ub300\uc2e0 \ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\uc758 \uad6c\ud604\uccb4\ub97c \uc0dd\uc131\ud558\ub294 \uac83\uc774\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.strong,{children:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \ud0c0\uc785 \uacc4\uce35 \uad6c\uc870"})}),"\n",(0,r.jsx)(t.mermaid,{value:"flowchart LR\n Mock --\x3e Spy --\x3e Stub --\x3e Dummy --\x3e TestDouble\n Fake --\x3e TestDouble"}),"\n",(0,r.jsx)(t.h3,{id:"\ub354\ubbf8dummy",children:"\ub354\ubbf8(Dummy)"}),"\n",(0,r.jsxs)(t.p,{children:["\uac00\uc7a5 \ub2e8\uc21c\ud558\uace0, \uc6d0\uc2dc\uc801\uc778 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uae30\ubcf8\uc801\uc73c\ub85c \uc544\ubb34 \uc77c\ub3c4 \ud558\uc9c0 \uc54a\ub294 \uad6c\ud604\uccb4\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\uac00 \ud544\uc694\ud55c \uacbd\uc6b0 \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub9cc\uc57d \uba54\uc11c\ub4dc\uac00 \ubb34\uc5b8\uac00 \ubc18\ud658\uc744 \ud574\uc57c\ud558\ub294 \uacbd\uc6b0 0, null\uacfc \uac19\uc740 \uac12\uc744 \ubc18\ud658\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud141stub",children:"\uc2a4\ud141(Stub)"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2dc\ub098\ub9ac\uc624\ub9c8\ub2e4 \ub2e4\ub978 \uac12(\ubbf8\ub9ac \uc900\ube44 \ub41c \uacb0\uacfc)\uc744 \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub97c \ud1b5\ud574 \ud2b9\uc815 \uc870\uac74\uc5d0\uc11c \uba54\uc11c\ub4dc\uac00 \uc608\uc0c1\ud55c\ub300\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uc2a4\ud30c\uc774spy",children:"\uc2a4\ud30c\uc774(Spy)"}),"\n",(0,r.jsxs)(t.p,{children:["\uc2a4\ud141\uacfc \uc720\uc0ac\ud558\uc9c0\ub9cc \ud638\ucd9c \uc5ec\ubd80\ub97c \uae30\ub85d\ud558\uac70\ub098 \ud638\ucd9c\ud560 \ub54c \uc804\ub2ec\ud55c \uc778\uc790\uac12\uc744 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608) \uba54\uc77c \uc804\uc1a1 \uae30\ub2a5\uc744 \uac00\uc9c4 \uac1d\uccb4\ub97c \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc73c\ub85c \uad6c\ud604\ud588\uc744 \ub54c \uba54\uc77c \uc804\uc1a1 \ud69f\uc218\ub97c \uae30\ub85d\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ubaa9-\ubaa8\uc758-\uac1d\uccb4mock",children:"\ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)"}),"\n",(0,r.jsxs)(t.p,{children:["\ubaa9\uc740 \ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774\ub97c \ud3ec\ud568\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud638\ucd9c \uc2dc \uc0ac\uc804\uc5d0 \uc815\uc758\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud558\uace0, \uc608\uc0c1\uce58 \ubabb\ud55c \ud638\ucd9c\uc774 \uc788\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub610\ud55c \ud638\ucd9c\uc5d0 \ub300\ud55c \uac80\uc99d\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\uac00\uc9dcfake",children:"\uac00\uc9dc(Fake)"}),"\n",(0,r.jsxs)(t.p,{children:["DOC\uc640 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc9c0\ub9cc, \ub354\uc6b1 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ub41c \uac83\uc774\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc608) \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \ub3d9\uc791\ud558\ub294 \uac00\uc9dc \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.admonition,{title:"DOC(depended-on component)",type:"note",children:(0,r.jsxs)(t.p,{children:["\uc758\uc874 \uad6c\uc131 \uc694\uc18c, DOC\ub97c \ud14c\uc2a4\ud2b8 \ub354\ube14\ub85c \ub300\uccb4\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8 \ub354\ube14\uc740 DOC\uc640 \ub3d9\uc77c\ud55c API\ub97c \uc81c\uacf5\ud574\uc57c \ud55c\ub2e4."]})}),"\n",(0,r.jsx)(t.h3,{id:"\uc0c1\ud638\uc791\uc6a9\uc5d0-\ub530\ub978-\ubaa9\uacfc-\uc2a4\ud141-\uad6c\ubd84",children:"\uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84"}),"\n",(0,r.jsxs)(t.p,{children:["\ub2e8\uc704 \ud14c\uc2a4\ud2b8 p.149 \uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ud06c\uac8c \ubaa9\uacfc \uc2a4\ud141\uc73c\ub85c \uad6c\ubd84\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ubaa9\uc740 SUT\uc640 \uad00\ub828\ub41c \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ubc18\uba74, \uc2a4\ud141\uc740 \ub2e8\uc21c \ubaa8\ubc29\ub9cc \ud55c\ub2e4."]}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"TestDouble"}),(0,r.jsx)(t.th,{children:"Mock"}),(0,r.jsx)(t.th,{children:"Stub"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\ud3ec\ud568 \uc720\ud615"}),(0,r.jsx)(t.td,{children:"\ubaa9, \uc2a4\ud30c\uc774"}),(0,r.jsx)(t.td,{children:"\uc2a4\ud141, \ub354\ubbf8, \ud398\uc774\ud06c"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc6a9\ub3c4"}),(0,r.jsx)(t.td,{children:"\uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ub370 \uc0ac\uc6a9"}),(0,r.jsx)(t.td,{children:"\ub0b4\ubd80\ub85c \ub4e4\uc5b4\uc624\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\ub294 \ub370 \uc0ac\uc6a9"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc124\uba85"}),(0,r.jsx)(t.td,{children:"SUT\uac00 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9"}),(0,r.jsx)(t.td,{children:"SUT\uac00 \uc785\ub825 \ub370\uc774\ud130\ub97c \uc5bb\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"\uc608\uc2dc"}),(0,r.jsx)(t.td,{children:"\uc774\uba54\uc77c \ubc1c\uc1a1"}),(0,r.jsx)(t.td,{children:"\ub370\uc774\ud130 \uac80\uc0c9"})]})]})]}),"\n",(0,r.jsx)(t.admonition,{title:"SUT(system under test)",type:"note",children:(0,r.jsxs)(t.p,{children:["\ud14c\uc2a4\ud2b8 \ub300\uc0c1 \uc2dc\uc2a4\ud15c",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8\ub97c \ud558\ub824\ub294 \ub300\uc0c1"]})}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:["\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30 - 3\uc7a5 \uace0\uae09 \ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4",(0,r.jsx)(t.br,{}),"\n","\ub2e8\uc704 \ud14c\uc2a4\ud2b8 - 5\uc7a5 \ubaa9\uacfc \ud14c\uc2a4\ud2b8 \ucde8\uc57d\uc131, \ube14\ub77c\ub514\ubbf8\ub974 \ucf54\ub9ac\ucf54\ud504",(0,r.jsx)(t.br,{}),"\n","\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uc2dc\uc791\ud558\uae30 - 7\uc7a5 \ub300\uc5ed, \ucd5c\ubc94\uade0",(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://www.martinfowler.com/bliki/TestDouble.html",children:"\ud14c\uc2a4\ud2b8 \ub354\ube14, Martin Fowler"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://johngrib.github.io/wiki/test-terms/",children:"\ud14c\uc2a4\ud2b8 \uad00\ub828 \uc6a9\uc5b4 \uc815\ub9ac, Johngrib"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"http://xunitpatterns.com/Test%20Double.html",children:"Test Double, Gerard Meszaros"})]})]})}function h(e={}){const{wrapper:t}={...(0,s.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>o});var r=n(67294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var d=r.createContext({}),o=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},a={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,i=e.originalType,d=e.parentName,h=c(e,["components","mdxType","originalType","parentName"]),j=o(n),x=s,u=j["".concat(d,".").concat(x)]||j[x]||a[x]||i;return n?r.createElement(u,l(l({ref:t},h),{},{components:n})):r.createElement(u,l({ref:t},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/bbdd7e52.3be218d1.js b/assets/js/bbdd7e52.dcdab03d.js similarity index 97% rename from assets/js/bbdd7e52.3be218d1.js rename to assets/js/bbdd7e52.dcdab03d.js index 711750f79..559fe2a01 100644 --- a/assets/js/bbdd7e52.3be218d1.js +++ b/assets/js/bbdd7e52.dcdab03d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3396],{49725:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>o,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var n=r(85893),c=r(3905);const s={title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",slug:"tecochat-retrospective-3",tags:["TecoChat","Retrospective"]},i=void 0,a={permalink:"/tecochat-retrospective-3",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",source:"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",description:"\uac1c\uc694",date:"2023-06-01T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 1\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.005,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",slug:"tecochat-retrospective-3",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",permalink:"/order-retrospective"},nextItem:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",permalink:"/composite"}},o={authorsImageUrls:[]},l=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5",id:"\ub098\uc758-\ucc44\ud305-\ud655\uc778\ud558\uace0-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",level:3},{value:"\uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5",id:"\uc88b\uc544\uc694\uc640-\ub313\uae00-\uae30\ub2a5",level:3},{value:"\ud0a4\uc6cc\ub4dc \ucd94\ucd9c",id:"\ud0a4\uc6cc\ub4dc-\ucd94\ucd9c",level:3},{value:"\ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5",id:"\ub2e4\ub978-\ud06c\ub8e8\uc758-\ucc44\ud305-\ubcf5\uc0ac\ud574\uc11c-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",level:3},{value:"\uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30",id:"\uc0ac\uc6a9\uc131-\uace0\ub824\ud558\uae30",level:3},{value:"\ud5a5\ud6c4 \uacc4\ud68d",id:"\ud5a5\ud6c4-\uacc4\ud68d",level:3}];function p(e){const t={br:"br",code:"code",h3:"h3",img:"img",p:"p",...(0,c.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,n.jsxs)(t.p,{children:["\uc6d0\ub798 \ubaa9\uc801\uc778 ",(0,n.jsx)(t.code,{children:"\ud06c\ub8e8\ub4e4\uc758 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0"}),"\uc744 \uc8fc\uae30 \uc704\ud574 \uc5b4\ub5a4 \uae30\ub2a5\uc744 \ucd94\uac00\ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub808\ubca8 2\uac00 \uac70\uc758 \ub05d\ub098\uac00\ub294 \uc2dc\uc810, \uadf8\ub3d9\uc548 \ud588\ub358 \uac83\uc744 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ub098\uc758-\ucc44\ud305-\ud655\uc778\ud558\uace0-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",children:"\ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["GPT\uc5d0\ub3c4 \uc788\ub294 \uae30\ub2a5\uc778\ub370, \ub0b4\uac00 \uc774\uc804\uc5d0 \ud588\ub358 \ucc44\ud305\uc744 \uc774\uc5b4\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc608\uc804\uc5d0 \uc5b4\ub5a4 \uc9c8\ubb38\uc744 \ub0a8\uacbc\ub294\uc9c0, \ub610\ud55c \ud574\ub2f9 \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat1",src:r(49483).Z+"",width:"2878",height:"1316"})}),"\n",(0,n.jsx)(t.h3,{id:"\uc88b\uc544\uc694\uc640-\ub313\uae00-\uae30\ub2a5",children:"\uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc5d0 \ubc18\uc751\ud560 \uc218 \uc788\ub294 \ubb34\uc5b8\uac00\uac00 \uc788\uc5c8\uc73c\uba74 \uc88b\uaca0\ub2e4\ub294 \uc758\uacac\ub4e4\uc774 \ub9ce\uc558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub204\uac00 \uc88b\uc544\uc694\ub97c \ub20c\ub800\ub294\uc9c0, \uc5b4\ub5a4 \ucc44\ud305\uc774 \uc88b\uc544\uc694\ub97c \uac00\uc7a5 \ub9ce\uc774 \ubc1b\uc558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub610\ud55c \ub313\uae00 \ucd94\uac00 \ubc0f \uc0ad\uc81c \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ud0a4\uc6cc\ub4dc-\ucd94\ucd9c",children:"\ud0a4\uc6cc\ub4dc \ucd94\ucd9c"}),"\n",(0,n.jsxs)(t.p,{children:["\uc5b4\ub5bb\uac8c \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\uc744 \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub294\ub370, \uc77c\ub2e8 GPT\ub97c \uc774\uc6a9\ud574\uc11c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\uae30\ub85c \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud574\ub2f9 \ubd80\ubd84\uc740 \uccab \uc9c8\ubb38\uc5d0 \ub300\ud55c \ud0a4\uc6cc\ub4dc\ub9cc \ucd94\ucd9c\ud558\ub3c4\ub85d \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ubc31\uc5d4\ub4dc\uc5d0\uc120 \ub9d0\ub791\uc774 \uc774\ubca4\ud2b8 \uc774\uc6a9\ud574\uc11c \uccab \ucc44\ud305 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74, \ube44\ub3d9\uae30\ub85c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\ub294 \uc9c8\ubb38\uc744 \ucd94\uac00\ub85c \ub0a0\ub9ac\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4.",(0,n.jsx)(t.br,{}),"\n","CSV \ud615\uc2dd\uc73c\ub85c GPT\uc5d0\uac8c \ub2f5\ubcc0\uc744 \uc785\ub825\ud574\ub2ec\ub77c\uace0 \uc694\uccad\ubc1b\ub294\ub370, \uc774 \ubd80\ubd84\uc774 \ubb38\uc81c(\ud504\ub86c\ud504\ud2b8 \uc5d4\uc9c0\ub2c8\uc5b4\ub9c1 \ubd80\ubd84\uc774 \ubc18\ud658\ub41c\ub2e4.)\uac00 \uc880 \uc788\ub294 \uac83 \uac19\uc544\uc11c \uac1c\uc120\uc774 \ud544\uc694\ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat2",src:r(50885).Z+"",width:"2394",height:"1048"})}),"\n",(0,n.jsx)(t.h3,{id:"\ub2e4\ub978-\ud06c\ub8e8\uc758-\ucc44\ud305-\ubcf5\uc0ac\ud574\uc11c-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",children:"\ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["\ub2e4\ub978 \ud06c\ub8e8\ub4e4\uc758 \ucc44\ud305\uc744 \uc77d\ub2e4\uac00 \uad81\uae08\ud55c \uc810\uc774 \uc788\ub2e4\uba74 \ubcf5\uc0ac\ud574\uc11c \ubc14\ub85c \uc9c8\ubb38\uc744 \ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ucc44\ud305\uc774 \ubcf5\uc0ac\ub41c \ud6c4 \ubc14\ub85c GPT\uc640 \ub300\ud654\ub97c \ud560 \uc218 \uc788\ub294 \uba54\uc778 \ud654\uba74\uc73c\ub85c \uc774\ub3d9\ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\uc0ac\uc6a9\uc131-\uace0\ub824\ud558\uae30",children:"\uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat3",src:r(15153).Z+"",width:"1668",height:"718"})}),"\n",(0,n.jsxs)(t.p,{children:["\uc704 \ud654\uba74\uc740 \ud68c\uc6d0\uac00\uc785 \ucc3d\uc774\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc0ac\uc2e4 \uac00\uc7a5 \ub9c8\uc74c\uc5d0 \ub4dc\ub294 \ubd80\ubd84\uc774\uace0, \ud68c\uc6d0\uac00\uc785(\ub2c9\ub124\uc784\ub9cc \uc785\ub825\ud558\uc9c0\ub9cc)\ud560 \ub54c \uc775\uba85\uc744 \uc6d0\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uace0\ubbfc\uc744 \ub3c4\uc640\uc8fc\uac8c \ub054 \uc74c\uc2dd, \uacfc\uc77c, \uacfc\uc790 \ub4f1\uc758 \uc694\uc18c\ub4e4\uc744 \uc785\ub825\ud558\ub3c4\ub85d \uc720\ub3c4\ud588\ub2e4!\n\ucd94\uac00\ub85c GPT\uc758 \ub2f5\ubcc0\uc774 \uc624\uba74 \uc790\ub3d9\uc73c\ub85c \ud654\uba74\uc744 \uc2a4\ud06c\ub864 \ud574\uc8fc\ub294 \uac83\uacfc \uac19\uc774 \uc0ac\uc6a9\uc131\uc744 \uac1c\uc120\ud574 \ubcf4\ub824\uace0 \ub178\ub825\ud588\uc9c0\ub9cc \uc27d\uc9c0 \uc54a\uc558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc81c\uc77c \ud558\uace0 \uc2f6\uc740 \uac83\uc740 \uc2e4\uc81c GPT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ucc98\ub7fc stream/text \uac12\uc744 \ucc98\ub9ac\ud558\uace0 \uc2f6\uc740\ub370 \uc774 \ubd80\ubd84\uc740 \ubc29\ud559 \ub54c \uae30\ud68c\uac00 \ub418\uba74 \ub3c4\uc804\ud574 \ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ud5a5\ud6c4-\uacc4\ud68d",children:"\ud5a5\ud6c4 \uacc4\ud68d"}),"\n",(0,n.jsxs)(t.p,{children:["\uc2e4\uc81c \ud06c\ub8e8\ub4e4\uc774 \uc0ac\uc6a9\ud574 \uc8fc\ub294 \uc11c\ube44\uc2a4\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\ubcf4\uba74\uc11c \uc0ac\uc6a9\uc790\uc758 \uc785\uc7a5\uc5d0\uc11c \uace0\ubbfc\ub3c4 \ud558\uac8c \ub418\ub294 \uac83 \uac19\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud06c\ub8e8\ub4e4\uc774 \uc9c1\uc811 \uc0ac\uc6a9\ud574 \uc8fc\ub2c8\uae4c \ub108\ubb34 \uace0\ub9d9\uace0, \ud55c\ud3b8\uc73c\ub85c\ub294 \uc2e0\uae30\ud558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc77c\ub2e8 \ubc29\ud559 \ub54c stream/text \uad00\ub828\ub41c \ubd80\ubd84 \ub3d9\uc791\ub418\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\ub824\uace0 \ud558\uace0, \uadf8 \uc678\uc758 \ubd80\ubd84\uc740 \uc870\uae08 \ub354 \uace0\ubbfc\ud574\uc57c\ub420 \uac83 \uac19\ub2e4."]})]})}function d(e={}){const{wrapper:t}={...(0,c.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function c(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function s(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(c[r]=e[r]);return c}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var o=n.createContext({}),l=function(e){var t=n.useContext(o),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,c=e.mdxType,s=e.originalType,o=e.parentName,d=a(e,["components","mdxType","originalType","parentName"]),h=l(r),b=c,u=h["".concat(o,".").concat(b)]||h[b]||p[b]||s;return r?n.createElement(u,i(i({ref:t},d),{},{components:r})):n.createElement(u,i({ref:t},d))}));d.displayName="MDXCreateElement"},49483:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat1-e9408e2e2f13bb192541de194ffccc6a.png"},50885:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat2-4b3b653eb2b23b88f19e8cb4177a786c.png"},15153:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat3-12a510067e4d210c13e46b7b99313307.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3396],{49725:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>o,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var n=r(85893),c=r(3905);const s={title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",slug:"tecochat-retrospective-3",tags:["TecoChat","Retrospective"]},i=void 0,a={permalink:"/tecochat-retrospective-3",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",source:"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",description:"\uac1c\uc694",date:"2023-06-01T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 1\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.005,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",slug:"tecochat-retrospective-3",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",permalink:"/composite"},nextItem:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",permalink:"/order-retrospective"}},o={authorsImageUrls:[]},l=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5",id:"\ub098\uc758-\ucc44\ud305-\ud655\uc778\ud558\uace0-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",level:3},{value:"\uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5",id:"\uc88b\uc544\uc694\uc640-\ub313\uae00-\uae30\ub2a5",level:3},{value:"\ud0a4\uc6cc\ub4dc \ucd94\ucd9c",id:"\ud0a4\uc6cc\ub4dc-\ucd94\ucd9c",level:3},{value:"\ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5",id:"\ub2e4\ub978-\ud06c\ub8e8\uc758-\ucc44\ud305-\ubcf5\uc0ac\ud574\uc11c-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",level:3},{value:"\uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30",id:"\uc0ac\uc6a9\uc131-\uace0\ub824\ud558\uae30",level:3},{value:"\ud5a5\ud6c4 \uacc4\ud68d",id:"\ud5a5\ud6c4-\uacc4\ud68d",level:3}];function p(e){const t={br:"br",code:"code",h3:"h3",img:"img",p:"p",...(0,c.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,n.jsxs)(t.p,{children:["\uc6d0\ub798 \ubaa9\uc801\uc778 ",(0,n.jsx)(t.code,{children:"\ud06c\ub8e8\ub4e4\uc758 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0"}),"\uc744 \uc8fc\uae30 \uc704\ud574 \uc5b4\ub5a4 \uae30\ub2a5\uc744 \ucd94\uac00\ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub808\ubca8 2\uac00 \uac70\uc758 \ub05d\ub098\uac00\ub294 \uc2dc\uc810, \uadf8\ub3d9\uc548 \ud588\ub358 \uac83\uc744 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ub098\uc758-\ucc44\ud305-\ud655\uc778\ud558\uace0-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",children:"\ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["GPT\uc5d0\ub3c4 \uc788\ub294 \uae30\ub2a5\uc778\ub370, \ub0b4\uac00 \uc774\uc804\uc5d0 \ud588\ub358 \ucc44\ud305\uc744 \uc774\uc5b4\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc608\uc804\uc5d0 \uc5b4\ub5a4 \uc9c8\ubb38\uc744 \ub0a8\uacbc\ub294\uc9c0, \ub610\ud55c \ud574\ub2f9 \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat1",src:r(49483).Z+"",width:"2878",height:"1316"})}),"\n",(0,n.jsx)(t.h3,{id:"\uc88b\uc544\uc694\uc640-\ub313\uae00-\uae30\ub2a5",children:"\uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc5d0 \ubc18\uc751\ud560 \uc218 \uc788\ub294 \ubb34\uc5b8\uac00\uac00 \uc788\uc5c8\uc73c\uba74 \uc88b\uaca0\ub2e4\ub294 \uc758\uacac\ub4e4\uc774 \ub9ce\uc558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub204\uac00 \uc88b\uc544\uc694\ub97c \ub20c\ub800\ub294\uc9c0, \uc5b4\ub5a4 \ucc44\ud305\uc774 \uc88b\uc544\uc694\ub97c \uac00\uc7a5 \ub9ce\uc774 \ubc1b\uc558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ub610\ud55c \ub313\uae00 \ucd94\uac00 \ubc0f \uc0ad\uc81c \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ud0a4\uc6cc\ub4dc-\ucd94\ucd9c",children:"\ud0a4\uc6cc\ub4dc \ucd94\ucd9c"}),"\n",(0,n.jsxs)(t.p,{children:["\uc5b4\ub5bb\uac8c \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\uc744 \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub294\ub370, \uc77c\ub2e8 GPT\ub97c \uc774\uc6a9\ud574\uc11c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\uae30\ub85c \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud574\ub2f9 \ubd80\ubd84\uc740 \uccab \uc9c8\ubb38\uc5d0 \ub300\ud55c \ud0a4\uc6cc\ub4dc\ub9cc \ucd94\ucd9c\ud558\ub3c4\ub85d \ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ubc31\uc5d4\ub4dc\uc5d0\uc120 \ub9d0\ub791\uc774 \uc774\ubca4\ud2b8 \uc774\uc6a9\ud574\uc11c \uccab \ucc44\ud305 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74, \ube44\ub3d9\uae30\ub85c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\ub294 \uc9c8\ubb38\uc744 \ucd94\uac00\ub85c \ub0a0\ub9ac\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4.",(0,n.jsx)(t.br,{}),"\n","CSV \ud615\uc2dd\uc73c\ub85c GPT\uc5d0\uac8c \ub2f5\ubcc0\uc744 \uc785\ub825\ud574\ub2ec\ub77c\uace0 \uc694\uccad\ubc1b\ub294\ub370, \uc774 \ubd80\ubd84\uc774 \ubb38\uc81c(\ud504\ub86c\ud504\ud2b8 \uc5d4\uc9c0\ub2c8\uc5b4\ub9c1 \ubd80\ubd84\uc774 \ubc18\ud658\ub41c\ub2e4.)\uac00 \uc880 \uc788\ub294 \uac83 \uac19\uc544\uc11c \uac1c\uc120\uc774 \ud544\uc694\ud55c \uac83 \uac19\ub2e4."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat2",src:r(50885).Z+"",width:"2394",height:"1048"})}),"\n",(0,n.jsx)(t.h3,{id:"\ub2e4\ub978-\ud06c\ub8e8\uc758-\ucc44\ud305-\ubcf5\uc0ac\ud574\uc11c-\uc774\uc5b4\ud558\ub294-\uae30\ub2a5",children:"\ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5"}),"\n",(0,n.jsxs)(t.p,{children:["\ub2e4\ub978 \ud06c\ub8e8\ub4e4\uc758 \ucc44\ud305\uc744 \uc77d\ub2e4\uac00 \uad81\uae08\ud55c \uc810\uc774 \uc788\ub2e4\uba74 \ubcf5\uc0ac\ud574\uc11c \ubc14\ub85c \uc9c8\ubb38\uc744 \ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ucc44\ud305\uc774 \ubcf5\uc0ac\ub41c \ud6c4 \ubc14\ub85c GPT\uc640 \ub300\ud654\ub97c \ud560 \uc218 \uc788\ub294 \uba54\uc778 \ud654\uba74\uc73c\ub85c \uc774\ub3d9\ud55c\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\uc0ac\uc6a9\uc131-\uace0\ub824\ud558\uae30",children:"\uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"chat3",src:r(15153).Z+"",width:"1668",height:"718"})}),"\n",(0,n.jsxs)(t.p,{children:["\uc704 \ud654\uba74\uc740 \ud68c\uc6d0\uac00\uc785 \ucc3d\uc774\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc0ac\uc2e4 \uac00\uc7a5 \ub9c8\uc74c\uc5d0 \ub4dc\ub294 \ubd80\ubd84\uc774\uace0, \ud68c\uc6d0\uac00\uc785(\ub2c9\ub124\uc784\ub9cc \uc785\ub825\ud558\uc9c0\ub9cc)\ud560 \ub54c \uc775\uba85\uc744 \uc6d0\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uace0\ubbfc\uc744 \ub3c4\uc640\uc8fc\uac8c \ub054 \uc74c\uc2dd, \uacfc\uc77c, \uacfc\uc790 \ub4f1\uc758 \uc694\uc18c\ub4e4\uc744 \uc785\ub825\ud558\ub3c4\ub85d \uc720\ub3c4\ud588\ub2e4!\n\ucd94\uac00\ub85c GPT\uc758 \ub2f5\ubcc0\uc774 \uc624\uba74 \uc790\ub3d9\uc73c\ub85c \ud654\uba74\uc744 \uc2a4\ud06c\ub864 \ud574\uc8fc\ub294 \uac83\uacfc \uac19\uc774 \uc0ac\uc6a9\uc131\uc744 \uac1c\uc120\ud574 \ubcf4\ub824\uace0 \ub178\ub825\ud588\uc9c0\ub9cc \uc27d\uc9c0 \uc54a\uc558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc81c\uc77c \ud558\uace0 \uc2f6\uc740 \uac83\uc740 \uc2e4\uc81c GPT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ucc98\ub7fc stream/text \uac12\uc744 \ucc98\ub9ac\ud558\uace0 \uc2f6\uc740\ub370 \uc774 \ubd80\ubd84\uc740 \ubc29\ud559 \ub54c \uae30\ud68c\uac00 \ub418\uba74 \ub3c4\uc804\ud574 \ubd10\uc57c\uaca0\ub2e4."]}),"\n",(0,n.jsx)(t.h3,{id:"\ud5a5\ud6c4-\uacc4\ud68d",children:"\ud5a5\ud6c4 \uacc4\ud68d"}),"\n",(0,n.jsxs)(t.p,{children:["\uc2e4\uc81c \ud06c\ub8e8\ub4e4\uc774 \uc0ac\uc6a9\ud574 \uc8fc\ub294 \uc11c\ube44\uc2a4\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\ubcf4\uba74\uc11c \uc0ac\uc6a9\uc790\uc758 \uc785\uc7a5\uc5d0\uc11c \uace0\ubbfc\ub3c4 \ud558\uac8c \ub418\ub294 \uac83 \uac19\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\ud06c\ub8e8\ub4e4\uc774 \uc9c1\uc811 \uc0ac\uc6a9\ud574 \uc8fc\ub2c8\uae4c \ub108\ubb34 \uace0\ub9d9\uace0, \ud55c\ud3b8\uc73c\ub85c\ub294 \uc2e0\uae30\ud558\ub2e4.",(0,n.jsx)(t.br,{}),"\n","\uc77c\ub2e8 \ubc29\ud559 \ub54c stream/text \uad00\ub828\ub41c \ubd80\ubd84 \ub3d9\uc791\ub418\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\ub824\uace0 \ud558\uace0, \uadf8 \uc678\uc758 \ubd80\ubd84\uc740 \uc870\uae08 \ub354 \uace0\ubbfc\ud574\uc57c\ub420 \uac83 \uac19\ub2e4."]})]})}function d(e={}){const{wrapper:t}={...(0,c.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function c(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function s(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(c[r]=e[r]);return c}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var o=n.createContext({}),l=function(e){var t=n.useContext(o),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,c=e.mdxType,s=e.originalType,o=e.parentName,d=a(e,["components","mdxType","originalType","parentName"]),h=l(r),b=c,u=h["".concat(o,".").concat(b)]||h[b]||p[b]||s;return r?n.createElement(u,i(i({ref:t},d),{},{components:r})):n.createElement(u,i({ref:t},d))}));d.displayName="MDXCreateElement"},49483:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat1-e9408e2e2f13bb192541de194ffccc6a.png"},50885:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat2-4b3b653eb2b23b88f19e8cb4177a786c.png"},15153:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/chat3-12a510067e4d210c13e46b7b99313307.png"}}]); \ No newline at end of file diff --git a/assets/js/bd4db8ee.65f63b9c.js b/assets/js/bd4db8ee.912a9bad.js similarity index 99% rename from assets/js/bd4db8ee.65f63b9c.js rename to assets/js/bd4db8ee.912a9bad.js index 853675cf6..cdb482ee2 100644 --- a/assets/js/bd4db8ee.65f63b9c.js +++ b/assets/js/bd4db8ee.912a9bad.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6883],{64855:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>b,frontMatter:()=>i,metadata:()=>s,toc:()=>o});var t=a(85893),r=a(3905);const i={title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",slug:"transaction-and-isolation",tags:["DataBase","Transaction","Isolation"]},l=void 0,s={permalink:"/transaction-and-isolation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",source:"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",description:"\ud2b8\ub79c\uc7ad\uc158(Transaction)",date:"2023-04-05T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 5\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Transaction",permalink:"/tags/transaction"},{label:"Isolation",permalink:"/tags/isolation"}],readingTime:9.57,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",slug:"transaction-and-isolation",tags:["DataBase","Transaction","Isolation"]},unlisted:!1,prevItem:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/mysql-lock"},nextItem:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",permalink:"/test-double"}},c={authorsImageUrls:[]},o=[{value:"\ud2b8\ub79c\uc7ad\uc158(Transaction)",id:"\ud2b8\ub79c\uc7ad\uc158transaction",level:2},{value:"\ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)",id:"\ud2b8\ub79c\uc7ad\uc158\uc758-\uc18d\uc131acid",level:3},{value:"\ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d",id:"\ud2b8\ub79c\uc7ad\uc158-\uc8fc\uc758\uc0ac\ud56d",level:3},{value:"\uaca9\ub9ac \uc218\uc900(Isolation level)",id:"\uaca9\ub9ac-\uc218\uc900isolation-level",level:2},{value:"READ UNCOMMITTED",id:"read-uncommitted",level:3},{value:"READ COMMITTED",id:"read-committed",level:3},{value:"REPEATABLE READ",id:"repeatable-read",level:3},{value:"SERIALIZABLE",id:"serializable",level:3},{value:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c",id:"\uaca9\ub9ac-\uc218\uc900\uc5d0-\ub530\ub978-\ubd80\uc815\ud569-\ubb38\uc81c",level:2},{value:"\ub354\ud2f0 \ub9ac\ub4dc(Dirty read)",id:"\ub354\ud2f0-\ub9ac\ub4dcdirty-read",level:3},{value:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)",id:"\ubc18\ubcf5-\uac00\ub2a5\ud558\uc9c0-\uc54a\uc740-\uc870\ud68cnon-repeatable-read",level:3},{value:"\ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)",id:"\ud32c\ud140-\ub9ac\ub4dcphantom-read-phantom-row",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"\ud2b8\ub79c\uc7ad\uc158transaction",children:"\ud2b8\ub79c\uc7ad\uc158(Transaction)"}),"\n",(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub17c\ub9ac\uc801 \uae30\ub2a5\uc744 \uc218\ud589\ud558\uae30 \uc704\ud55c \uc791\uc5c5\uc758 \ub2e8\uc704\ub97c \ub9d0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc740 \uc791\uc5c5\uc758 \uc644\uc804\uc131\uacfc \ub370\uc774\ud130\uc758 \uc815\ud569\uc131\uc744 \ubcf4\uc7a5\ud574 \uc900\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub17c\ub9ac\uc801\uc778 \uc791\uc5c5 \uc14b\uc744 \uc644\ubcbd\ud558\uac8c \ucc98\ub9ac\ud558\uac70\ub098, \uc624\ub958 \uc2dc \uc791\uc5c5\uc758 \uc77c\ubd80\ub9cc \uc801\uc6a9\ub418\ub294 \ud604\uc0c1\uc744 \ub9c9\uc544\uc900\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud2b8\ub79c\uc7ad\uc158\uc758-\uc18d\uc131acid",children:"\ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc6d0\uc790\uc131(Atomicity): \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \uc2e4\ud589\ub41c \uc791\uc5c5\ub4e4\uc740 \ubaa8\ub450 \uc131\uacf5\ud558\uac70\ub098, \uc2e4\ud328\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc77c\uad00\uc131(Consistency): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc218\ud589\ub418\uae30 \uc804\uacfc \ud6c4\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc77c\uad00\ub41c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uaca9\ub9ac\uc131(Isolation): \uac01\uac01\uc758 \ud2b8\ub79c\uc7ad\uc158\uc740 \ub3c5\ub9bd\uc801\uc774\ub77c \uc11c\ub85c\uc5d0\uac8c \uc601\ud5a5\uc744 \uc8fc\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc9c0\uc18d\uc131(Durability): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c\ub2e4\uba74 \uc601\uad6c\uc801\uc73c\ub85c \uacb0\uacfc\uc5d0 \ubc18\uc601\ub418\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud2b8\ub79c\uc7ad\uc158-\uc8fc\uc758\uc0ac\ud56d",children:"\ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc740 \uaf2d \ud544\uc694\ud55c \ucd5c\uc18c\uc758 \ucf54\ub4dc\uc5d0\ub9cc \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.(\ud2b8\ub79c\uc7ad\uc158\uc758 \ubc94\uc704\ub97c \ucd5c\uc18c\ud654\ud558\ub77c)",(0,t.jsx)(n.br,{}),"\n","\uad6c\ud604\ud574\uc57c \ud558\ub294 \uc5c5\ubb34\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158\uc744 \ubb36\uac70\ub098 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\ub294 \uacbd\uc6b0 \ubc18\ub4dc\uc2dc \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsxs)(n.admonition,{title:"\uc65c \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\uc744 \ub54c \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud560\uae4c? \ud83e\udd14",type:"info",children:[(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\uc758 \uc77c\uad00\uc131\uacfc \uc548\uc804\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc744 \ud2b8\ub79c\uc7ad\uc158 \ub0b4\ubd80\uc5d0 \ud3ec\ud568\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4."]}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc911\uac04\uc5d0 \uc2e4\ud328\ud560 \uac00\ub2a5\uc131(\uc548\uc804\uc131 X)"}),"\n",(0,t.jsx)(n.li,{children:"\ud1b5\uc2e0\uc73c\ub85c \uc778\ud574 \ub370\uc774\ud130\uac00 \ubcc0\uacbd\ub420 \uc218 \uc788\ub294 \ubd80\ubd84(\uc77c\uad00\uc131 X)"}),"\n"]})]}),"\n",(0,t.jsx)(n.h2,{id:"\uaca9\ub9ac-\uc218\uc900isolation-level",children:"\uaca9\ub9ac \uc218\uc900(Isolation level)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc5ec\ub7ec \ud2b8\ub79c\uc7ad\uc158\uc774 \ub3d9\uc2dc\uc5d0 \ucc98\ub9ac\ub420 \ub54c \ud2b9\uc815 \ud2b8\ub79c\uc7ad\uc158\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\uc758 \uc870\ud68c \ubc0f \ubcc0\uacbd\uc744 \ud5c8\uc6a9\ud560\uc9c0 \uacb0\uc815\ud558\ub294 \uac83\uc744 \ub9d0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uaca9\ub9ac \uc218\uc900\uc774 \ub192\uc544\uc9c8 \uc218\ub85d \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\uc774 \ub5a8\uc5b4\uc9c0\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\uc9c0\ub9cc, ",(0,t.jsx)(n.code,{children:"SERIALIZABLE"}),"\uc774 \uc544\ub2c8\ub77c\uba74 \ud06c\uac8c \uc131\ub2a5\uc758 \uc800\ud558\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"read-uncommitted",children:"READ UNCOMMITTED"}),"\n",(0,t.jsxs)(n.p,{children:["\uac01 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\uc758 \ubcc0\uacbd \ub0b4\uc6a9\uc774 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774\ub098 ",(0,t.jsx)(n.code,{children:"ROLLBACK"})," \uc5ec\ubd80\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcf4\uc778\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub354\ud2f0 \ub9ac\ub4dc \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud558\uae30 \ub54c\ubb38\uc5d0 \uc815\ud569\uc131\uc758 \ubb38\uc81c\uac00 \ub9ce\uc740 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL \uc0ac\uc6a9\uc2dc \ucd5c\uc18c ",(0,t.jsx)(n.code,{children:"READ COMMITTED"})," \uc774\uc0c1\uc758 \uaca9\ub9ac \uc218\uc900 \uc0ac\uc6a9\uc744 \uad8c\uc7a5\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: READ UNCOMMITTED\n---\nsequenceDiagram\n Alice->>Database: BEGIN\n Alice->>Database: INSERT(Alice)\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: COMMIT(Alice)"}),"\n",(0,t.jsx)(n.h3,{id:"read-committed",children:"READ COMMITTED"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774 \uc644\ub8cc\ub41c \ub370\uc774\ud130\ub9cc \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc870\ud68c\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub77c\ud074 DBMS\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.code,{children:"REPEATABLE READ"}),"\uac00 \ubcf4\uc7a5\ub418\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 ",(0,t.jsx)(n.code,{children:"NON-REPEATABLE READ"})," \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: READ COMMITTED\n---\nsequenceDiagram\n Alice->>Database: BEGIN\n Alice->>Database: UPDATE(Alice to Bob)\n Bob->>Database: SELECT\n Database->>+Bob: Alice(Undo log)\n Alice->>Database: COMMIT"}),"\n",(0,t.jsx)(n.h3,{id:"repeatable-read",children:"REPEATABLE READ"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc774 \uc2dc\uc791\ub418\uae30 \uc804\uc5d0 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774 \uc644\ub8cc\ub41c \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub9cc \uc870\ud68c\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL\uc758 InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MVCC\ub97c \uc774\uc6a9\ud574 \uc5b8\ub450(Undo) \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \uc774\uc804 \ub370\uc774\ud130\ub97c \uc774\uc6a9\ud574 \ub3d9\uc77c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc5ec\uc904 \uc218 \uc788\uac8c \ubcf4\uc7a5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc7a5\ud558\ub294 \ubc29\ubc95\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ubaa8\ub4e0 InnoDB \ud2b8\ub79c\uc7ad\uc158\uc740 \uc21c\ucc28\uc801\uc73c\ub85c \uc99d\uac00\ud558\ub294 \uace0\uc720\ud55c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ub97c \uac00\uc9c4\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Undo \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \ub808\ucf54\ub4dc\uc5d0\ub294 \ubcc0\uacbd\uc744 \ubc1c\uc0dd\uc2dc\ud0a8 \ud2b8\ub79c\uc7ad\uc158\uc758 \ubc88\ud638\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Undo \uc601\uc5ed\uc758 \ubc31\uc5c5\ub41c \ub370\uc774\ud130\ub294 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774 \ubd88\ud544\uc694\ud558\ub2e4\uace0 \ud310\ub2e8\ud558\ub294 \uacbd\uc6b0 \uc0ad\uc81c\ub41c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c\ub294 MVCC\ub97c \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \uac00\uc7a5 \uc624\ub798\ub41c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ubcf4\ub2e4 \uc55e\uc120 Undo \uc601\uc5ed\uc758 \ub370\uc774\ud130\ub294 \uc0ad\uc81c\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"InnoDB\uc5d0\uc11c\ub294 \uac2d \ub77d\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc744 \uc774\uc6a9\ud558\uc5ec \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc744 \ubc29\uc9c0\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: REPEATABLE READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN(TRX-ID: 1)\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: BEGIN(TRX-ID: 2)\n Alice->>Database: UPDATE(Alice to Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT\n Database->>+Bob: Alice(Undo log)"}),"\n",(0,t.jsx)(n.admonition,{title:"\uac2d \ub78d(Gap lock)\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d(Next-key lock)",type:"note",children:(0,t.jsxs)(n.p,{children:["\uac2d \ub77d: \ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub125\uc2a4\ud2b8 \ud0a4 \ub77d: \ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4."]})}),"\n",(0,t.jsxs)(n.admonition,{title:"MVCC(Multi Version Concurrency Control)",type:"note",children:[(0,t.jsx)(n.p,{children:"\ub3d9\uc2dc\uc131\uc744 \uc81c\uc5b4\ud558\ub294 \ubc29\ubc95 \uc911 \ud558\ub098\ub85c \ud558\ub098\uc758 \ub808\ucf54\ub4dc\uc5d0 \ub300\ud574 \uc5ec\ub7ec \uac1c\uc758 \ubc84\uc804\uc774 \ub3d9\uc2dc\uc5d0 \uad00\ub9ac\ub418\ub294 \uac83\uc774\ub2e4."}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"PostgreSQL\uc740 \ub2e4\uc911 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uac83\uc73c\ub85c MVCC\ub97c \uad6c\ud604\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:["Oracle, InnoDB\ub294 ",(0,t.jsx)(n.code,{children:"Undo log"}),"\ub97c \uc774\uc6a9\ud574 \uc774 \uae30\ub2a5\uc744 \uad6c\ud604\ud55c\ub2e4.(\ucd5c\uc2e0 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub9cc DB\uc5d0 \uc800\uc7a5)"]}),"\n"]}),(0,t.jsx)(n.p,{children:"\uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc77d\uad00\ub41c \uc77d\uae30\ub97c \uc81c\uacf5\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4."})]}),"\n",(0,t.jsx)(n.h3,{id:"serializable",children:"SERIALIZABLE"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc9c4\ud589\uc2dc\ud0a4\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uace0 \ub530\ub77c\uc11c \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\ub3c4 \ub2e4\ub978 \uaca9\ub9ac \uc218\uc900\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c4\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uace0 \uc4f0\ub294 \ub808\ucf54\ub4dc\ub97c \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\ub294 \uc811\uadfc\ud560 \uc218 \uc5c6\uace0 \ub2e8\uc21c\ud55c \uc77d\uae30 \uc791\uc5c5\ub3c4 \uacf5\uc720 \uc7a0\uae08(\uc77d\uae30 \uc7a0\uae08)\uc744 \ud68d\ub4dd\ud574\uc57c\ub9cc \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB\uc5d0\uc11c\ub294 \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc774 ",(0,t.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uad73\uc774 \uc0ac\uc6a9\ud560 \ud544\uc694\ub294 \uc5c6\ub2e4."]}),"\n",(0,t.jsx)(n.h2,{id:"\uaca9\ub9ac-\uc218\uc900\uc5d0-\ub530\ub978-\ubd80\uc815\ud569-\ubb38\uc81c",children:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c"}),"\n",(0,t.jsx)(n.p,{children:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ub354\ud2f0 \ub9ac\ub4dc, \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c, \ud32c\ud140 \ub9ac\ub4dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"\uaca9\ub9ac \uc218\uc900 / \ubd80\uc815\ud569 \ubb38\uc81c"}),(0,t.jsx)(n.th,{children:"\ub354\ud2f0 \ub9ac\ub4dc"}),(0,t.jsx)(n.th,{children:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c"}),(0,t.jsx)(n.th,{children:"\ud32c\ud140 \ub9ac\ub4dc"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"READ UNCOMMITTED"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"READ COMMITTED"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"REPEATABLE READ"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"O(InnoDB\ub294 X)"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SERIALIZABLE"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"\ub354\ud2f0-\ub9ac\ub4dcdirty-read",children:"\ub354\ud2f0 \ub9ac\ub4dc(Dirty read)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc5b4\ub5a4 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c \uc791\uc5c5\uc774 \uc644\ub8cc\ub418\uc9c0 \uc54a\uc558\uc5b4\ub3c4 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcfc \uc218 \uc788\ub294 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \uc218\uc900\uc774 READ UNCOMMITTED\uc77c \ub54c \ubc1c\uc0dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc608) B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uace0 \ucee4\ubc0b\uc744 \ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, A\uac00 \ud574\ub2f9 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud560 \uc218 \uc788\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc18\ubcf5-\uac00\ub2a5\ud558\uc9c0-\uc54a\uc740-\uc870\ud68cnon-repeatable-read",children:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)"}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc758 \uac19\uc740 \ud589\uc5d0 \ub450 \ubc88 \uc774\uc0c1 \uc870\ud68c\uac00 \ubc1c\uc0dd\ud588\ub294\ub370, \uadf8 \uac12\uc774 \ub2e4\ub978 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc5ec\ub7ec \ubc88 \uc870\ud68c\ud558\ub358 \uc911 B\uac00 \ub808\ucf54\ub4dc\ub97c \ubcc0\uacbd\ud558\uc5ec A\uac00 \uc870\ud68c\ud55c \uac12\uc774 \ub2ec\ub77c\uc9c0\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: NON REPEATABLE READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: BEGIN\n Alice->>Database: UPDATE(Alice to Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT\n Database->>+Bob: Bob"}),"\n",(0,t.jsx)(n.h3,{id:"\ud32c\ud140-\ub9ac\ub4dcphantom-read-phantom-row",children:"\ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)"}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ucffc\ub9ac \uc218\ud589\uc2dc, \uc218\ud589 \uacb0\uacfc\uac00 \ub2e4\ub978 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud558\uace0 B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uc5ec A\uac00 \ub2e4\uc2dc \uc870\ud68c\ud560 \ub54c \uc874\uc7ac\ud558\uc9c0 \uc54a\uc740 \ub808\ucf54\ub4dc\uac00 \uc870\ud68c\ub418\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: PHANTOM READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN(TRX-ID: 1)\n Bob->>Database: SELECT COUNT\n Database->>+Bob: 1\n Alice->>Database: BEGIN(TRX-ID: 2)\n Alice->>Database: INSERT(Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT COUNT\n Database->>+Bob: 2"}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html",children:"Isolation Level, MySQL"})]})]})}function b(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,a)=>{a.d(n,{ah:()=>o});var t=a(67294);function r(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function i(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),a.push.apply(a,t)}return a}function l(e){for(var n=1;n=0||(r[a]=e[a]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var c=t.createContext({}),o=function(e){var n=t.useContext(c),a=n;return e&&(a="function"==typeof e?e(n):l(l({},n),e)),a},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},b=t.forwardRef((function(e,n){var a=e.components,r=e.mdxType,i=e.originalType,c=e.parentName,b=s(e,["components","mdxType","originalType","parentName"]),h=o(a),j=r,x=h["".concat(c,".").concat(j)]||h[j]||d[j]||i;return a?t.createElement(x,l(l({ref:n},b),{},{components:a})):t.createElement(x,l({ref:n},b))}));b.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6883],{64855:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>b,frontMatter:()=>i,metadata:()=>s,toc:()=>o});var t=a(85893),r=a(3905);const i={title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",slug:"transaction-and-isolation",tags:["DataBase","Transaction","Isolation"]},l=void 0,s={permalink:"/transaction-and-isolation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",source:"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",description:"\ud2b8\ub79c\uc7ad\uc158(Transaction)",date:"2023-04-05T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 5\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Transaction",permalink:"/tags/transaction"},{label:"Isolation",permalink:"/tags/isolation"}],readingTime:9.57,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",slug:"transaction-and-isolation",tags:["DataBase","Transaction","Isolation"]},unlisted:!1,prevItem:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",permalink:"/test-double"},nextItem:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/mysql-lock"}},c={authorsImageUrls:[]},o=[{value:"\ud2b8\ub79c\uc7ad\uc158(Transaction)",id:"\ud2b8\ub79c\uc7ad\uc158transaction",level:2},{value:"\ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)",id:"\ud2b8\ub79c\uc7ad\uc158\uc758-\uc18d\uc131acid",level:3},{value:"\ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d",id:"\ud2b8\ub79c\uc7ad\uc158-\uc8fc\uc758\uc0ac\ud56d",level:3},{value:"\uaca9\ub9ac \uc218\uc900(Isolation level)",id:"\uaca9\ub9ac-\uc218\uc900isolation-level",level:2},{value:"READ UNCOMMITTED",id:"read-uncommitted",level:3},{value:"READ COMMITTED",id:"read-committed",level:3},{value:"REPEATABLE READ",id:"repeatable-read",level:3},{value:"SERIALIZABLE",id:"serializable",level:3},{value:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c",id:"\uaca9\ub9ac-\uc218\uc900\uc5d0-\ub530\ub978-\ubd80\uc815\ud569-\ubb38\uc81c",level:2},{value:"\ub354\ud2f0 \ub9ac\ub4dc(Dirty read)",id:"\ub354\ud2f0-\ub9ac\ub4dcdirty-read",level:3},{value:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)",id:"\ubc18\ubcf5-\uac00\ub2a5\ud558\uc9c0-\uc54a\uc740-\uc870\ud68cnon-repeatable-read",level:3},{value:"\ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)",id:"\ud32c\ud140-\ub9ac\ub4dcphantom-read-phantom-row",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"\ud2b8\ub79c\uc7ad\uc158transaction",children:"\ud2b8\ub79c\uc7ad\uc158(Transaction)"}),"\n",(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub17c\ub9ac\uc801 \uae30\ub2a5\uc744 \uc218\ud589\ud558\uae30 \uc704\ud55c \uc791\uc5c5\uc758 \ub2e8\uc704\ub97c \ub9d0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc740 \uc791\uc5c5\uc758 \uc644\uc804\uc131\uacfc \ub370\uc774\ud130\uc758 \uc815\ud569\uc131\uc744 \ubcf4\uc7a5\ud574 \uc900\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub17c\ub9ac\uc801\uc778 \uc791\uc5c5 \uc14b\uc744 \uc644\ubcbd\ud558\uac8c \ucc98\ub9ac\ud558\uac70\ub098, \uc624\ub958 \uc2dc \uc791\uc5c5\uc758 \uc77c\ubd80\ub9cc \uc801\uc6a9\ub418\ub294 \ud604\uc0c1\uc744 \ub9c9\uc544\uc900\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud2b8\ub79c\uc7ad\uc158\uc758-\uc18d\uc131acid",children:"\ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc6d0\uc790\uc131(Atomicity): \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \uc2e4\ud589\ub41c \uc791\uc5c5\ub4e4\uc740 \ubaa8\ub450 \uc131\uacf5\ud558\uac70\ub098, \uc2e4\ud328\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc77c\uad00\uc131(Consistency): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc218\ud589\ub418\uae30 \uc804\uacfc \ud6c4\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc77c\uad00\ub41c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uaca9\ub9ac\uc131(Isolation): \uac01\uac01\uc758 \ud2b8\ub79c\uc7ad\uc158\uc740 \ub3c5\ub9bd\uc801\uc774\ub77c \uc11c\ub85c\uc5d0\uac8c \uc601\ud5a5\uc744 \uc8fc\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc9c0\uc18d\uc131(Durability): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c\ub2e4\uba74 \uc601\uad6c\uc801\uc73c\ub85c \uacb0\uacfc\uc5d0 \ubc18\uc601\ub418\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud2b8\ub79c\uc7ad\uc158-\uc8fc\uc758\uc0ac\ud56d",children:"\ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc740 \uaf2d \ud544\uc694\ud55c \ucd5c\uc18c\uc758 \ucf54\ub4dc\uc5d0\ub9cc \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.(\ud2b8\ub79c\uc7ad\uc158\uc758 \ubc94\uc704\ub97c \ucd5c\uc18c\ud654\ud558\ub77c)",(0,t.jsx)(n.br,{}),"\n","\uad6c\ud604\ud574\uc57c \ud558\ub294 \uc5c5\ubb34\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158\uc744 \ubb36\uac70\ub098 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\ub294 \uacbd\uc6b0 \ubc18\ub4dc\uc2dc \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsxs)(n.admonition,{title:"\uc65c \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\uc744 \ub54c \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud560\uae4c? \ud83e\udd14",type:"info",children:[(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\uc758 \uc77c\uad00\uc131\uacfc \uc548\uc804\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc744 \ud2b8\ub79c\uc7ad\uc158 \ub0b4\ubd80\uc5d0 \ud3ec\ud568\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4."]}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc911\uac04\uc5d0 \uc2e4\ud328\ud560 \uac00\ub2a5\uc131(\uc548\uc804\uc131 X)"}),"\n",(0,t.jsx)(n.li,{children:"\ud1b5\uc2e0\uc73c\ub85c \uc778\ud574 \ub370\uc774\ud130\uac00 \ubcc0\uacbd\ub420 \uc218 \uc788\ub294 \ubd80\ubd84(\uc77c\uad00\uc131 X)"}),"\n"]})]}),"\n",(0,t.jsx)(n.h2,{id:"\uaca9\ub9ac-\uc218\uc900isolation-level",children:"\uaca9\ub9ac \uc218\uc900(Isolation level)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc5ec\ub7ec \ud2b8\ub79c\uc7ad\uc158\uc774 \ub3d9\uc2dc\uc5d0 \ucc98\ub9ac\ub420 \ub54c \ud2b9\uc815 \ud2b8\ub79c\uc7ad\uc158\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\uc758 \uc870\ud68c \ubc0f \ubcc0\uacbd\uc744 \ud5c8\uc6a9\ud560\uc9c0 \uacb0\uc815\ud558\ub294 \uac83\uc744 \ub9d0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uaca9\ub9ac \uc218\uc900\uc774 \ub192\uc544\uc9c8 \uc218\ub85d \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\uc774 \ub5a8\uc5b4\uc9c0\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\uc9c0\ub9cc, ",(0,t.jsx)(n.code,{children:"SERIALIZABLE"}),"\uc774 \uc544\ub2c8\ub77c\uba74 \ud06c\uac8c \uc131\ub2a5\uc758 \uc800\ud558\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"read-uncommitted",children:"READ UNCOMMITTED"}),"\n",(0,t.jsxs)(n.p,{children:["\uac01 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\uc758 \ubcc0\uacbd \ub0b4\uc6a9\uc774 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774\ub098 ",(0,t.jsx)(n.code,{children:"ROLLBACK"})," \uc5ec\ubd80\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcf4\uc778\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub354\ud2f0 \ub9ac\ub4dc \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud558\uae30 \ub54c\ubb38\uc5d0 \uc815\ud569\uc131\uc758 \ubb38\uc81c\uac00 \ub9ce\uc740 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL \uc0ac\uc6a9\uc2dc \ucd5c\uc18c ",(0,t.jsx)(n.code,{children:"READ COMMITTED"})," \uc774\uc0c1\uc758 \uaca9\ub9ac \uc218\uc900 \uc0ac\uc6a9\uc744 \uad8c\uc7a5\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: READ UNCOMMITTED\n---\nsequenceDiagram\n Alice->>Database: BEGIN\n Alice->>Database: INSERT(Alice)\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: COMMIT(Alice)"}),"\n",(0,t.jsx)(n.h3,{id:"read-committed",children:"READ COMMITTED"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774 \uc644\ub8cc\ub41c \ub370\uc774\ud130\ub9cc \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc870\ud68c\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub77c\ud074 DBMS\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.code,{children:"REPEATABLE READ"}),"\uac00 \ubcf4\uc7a5\ub418\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 ",(0,t.jsx)(n.code,{children:"NON-REPEATABLE READ"})," \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: READ COMMITTED\n---\nsequenceDiagram\n Alice->>Database: BEGIN\n Alice->>Database: UPDATE(Alice to Bob)\n Bob->>Database: SELECT\n Database->>+Bob: Alice(Undo log)\n Alice->>Database: COMMIT"}),"\n",(0,t.jsx)(n.h3,{id:"repeatable-read",children:"REPEATABLE READ"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc774 \uc2dc\uc791\ub418\uae30 \uc804\uc5d0 ",(0,t.jsx)(n.code,{children:"COMMIT"}),"\uc774 \uc644\ub8cc\ub41c \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub9cc \uc870\ud68c\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL\uc758 InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MVCC\ub97c \uc774\uc6a9\ud574 \uc5b8\ub450(Undo) \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \uc774\uc804 \ub370\uc774\ud130\ub97c \uc774\uc6a9\ud574 \ub3d9\uc77c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc5ec\uc904 \uc218 \uc788\uac8c \ubcf4\uc7a5\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc7a5\ud558\ub294 \ubc29\ubc95\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ubaa8\ub4e0 InnoDB \ud2b8\ub79c\uc7ad\uc158\uc740 \uc21c\ucc28\uc801\uc73c\ub85c \uc99d\uac00\ud558\ub294 \uace0\uc720\ud55c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ub97c \uac00\uc9c4\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Undo \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \ub808\ucf54\ub4dc\uc5d0\ub294 \ubcc0\uacbd\uc744 \ubc1c\uc0dd\uc2dc\ud0a8 \ud2b8\ub79c\uc7ad\uc158\uc758 \ubc88\ud638\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Undo \uc601\uc5ed\uc758 \ubc31\uc5c5\ub41c \ub370\uc774\ud130\ub294 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774 \ubd88\ud544\uc694\ud558\ub2e4\uace0 \ud310\ub2e8\ud558\ub294 \uacbd\uc6b0 \uc0ad\uc81c\ub41c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c\ub294 MVCC\ub97c \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \uac00\uc7a5 \uc624\ub798\ub41c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ubcf4\ub2e4 \uc55e\uc120 Undo \uc601\uc5ed\uc758 \ub370\uc774\ud130\ub294 \uc0ad\uc81c\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"InnoDB\uc5d0\uc11c\ub294 \uac2d \ub77d\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc744 \uc774\uc6a9\ud558\uc5ec \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc744 \ubc29\uc9c0\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: REPEATABLE READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN(TRX-ID: 1)\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: BEGIN(TRX-ID: 2)\n Alice->>Database: UPDATE(Alice to Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT\n Database->>+Bob: Alice(Undo log)"}),"\n",(0,t.jsx)(n.admonition,{title:"\uac2d \ub78d(Gap lock)\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d(Next-key lock)",type:"note",children:(0,t.jsxs)(n.p,{children:["\uac2d \ub77d: \ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub125\uc2a4\ud2b8 \ud0a4 \ub77d: \ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4."]})}),"\n",(0,t.jsxs)(n.admonition,{title:"MVCC(Multi Version Concurrency Control)",type:"note",children:[(0,t.jsx)(n.p,{children:"\ub3d9\uc2dc\uc131\uc744 \uc81c\uc5b4\ud558\ub294 \ubc29\ubc95 \uc911 \ud558\ub098\ub85c \ud558\ub098\uc758 \ub808\ucf54\ub4dc\uc5d0 \ub300\ud574 \uc5ec\ub7ec \uac1c\uc758 \ubc84\uc804\uc774 \ub3d9\uc2dc\uc5d0 \uad00\ub9ac\ub418\ub294 \uac83\uc774\ub2e4."}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"PostgreSQL\uc740 \ub2e4\uc911 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uac83\uc73c\ub85c MVCC\ub97c \uad6c\ud604\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.li,{children:["Oracle, InnoDB\ub294 ",(0,t.jsx)(n.code,{children:"Undo log"}),"\ub97c \uc774\uc6a9\ud574 \uc774 \uae30\ub2a5\uc744 \uad6c\ud604\ud55c\ub2e4.(\ucd5c\uc2e0 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub9cc DB\uc5d0 \uc800\uc7a5)"]}),"\n"]}),(0,t.jsx)(n.p,{children:"\uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc77d\uad00\ub41c \uc77d\uae30\ub97c \uc81c\uacf5\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4."})]}),"\n",(0,t.jsx)(n.h3,{id:"serializable",children:"SERIALIZABLE"}),"\n",(0,t.jsxs)(n.p,{children:["\ud2b8\ub79c\uc7ad\uc158\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc9c4\ud589\uc2dc\ud0a4\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uace0 \ub530\ub77c\uc11c \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\ub3c4 \ub2e4\ub978 \uaca9\ub9ac \uc218\uc900\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c4\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uace0 \uc4f0\ub294 \ub808\ucf54\ub4dc\ub97c \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\ub294 \uc811\uadfc\ud560 \uc218 \uc5c6\uace0 \ub2e8\uc21c\ud55c \uc77d\uae30 \uc791\uc5c5\ub3c4 \uacf5\uc720 \uc7a0\uae08(\uc77d\uae30 \uc7a0\uae08)\uc744 \ud68d\ub4dd\ud574\uc57c\ub9cc \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB\uc5d0\uc11c\ub294 \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc774 ",(0,t.jsx)(n.code,{children:"REPEATABLE READ"})," \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uad73\uc774 \uc0ac\uc6a9\ud560 \ud544\uc694\ub294 \uc5c6\ub2e4."]}),"\n",(0,t.jsx)(n.h2,{id:"\uaca9\ub9ac-\uc218\uc900\uc5d0-\ub530\ub978-\ubd80\uc815\ud569-\ubb38\uc81c",children:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c"}),"\n",(0,t.jsx)(n.p,{children:"\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ub354\ud2f0 \ub9ac\ub4dc, \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c, \ud32c\ud140 \ub9ac\ub4dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"\uaca9\ub9ac \uc218\uc900 / \ubd80\uc815\ud569 \ubb38\uc81c"}),(0,t.jsx)(n.th,{children:"\ub354\ud2f0 \ub9ac\ub4dc"}),(0,t.jsx)(n.th,{children:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c"}),(0,t.jsx)(n.th,{children:"\ud32c\ud140 \ub9ac\ub4dc"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"READ UNCOMMITTED"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"READ COMMITTED"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"O"}),(0,t.jsx)(n.td,{children:"O"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"REPEATABLE READ"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"O(InnoDB\ub294 X)"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SERIALIZABLE"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"}),(0,t.jsx)(n.td,{children:"X"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"\ub354\ud2f0-\ub9ac\ub4dcdirty-read",children:"\ub354\ud2f0 \ub9ac\ub4dc(Dirty read)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc5b4\ub5a4 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c \uc791\uc5c5\uc774 \uc644\ub8cc\ub418\uc9c0 \uc54a\uc558\uc5b4\ub3c4 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcfc \uc218 \uc788\ub294 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \uc218\uc900\uc774 READ UNCOMMITTED\uc77c \ub54c \ubc1c\uc0dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc608) B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uace0 \ucee4\ubc0b\uc744 \ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, A\uac00 \ud574\ub2f9 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud560 \uc218 \uc788\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc18\ubcf5-\uac00\ub2a5\ud558\uc9c0-\uc54a\uc740-\uc870\ud68cnon-repeatable-read",children:"\ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)"}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc758 \uac19\uc740 \ud589\uc5d0 \ub450 \ubc88 \uc774\uc0c1 \uc870\ud68c\uac00 \ubc1c\uc0dd\ud588\ub294\ub370, \uadf8 \uac12\uc774 \ub2e4\ub978 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc5ec\ub7ec \ubc88 \uc870\ud68c\ud558\ub358 \uc911 B\uac00 \ub808\ucf54\ub4dc\ub97c \ubcc0\uacbd\ud558\uc5ec A\uac00 \uc870\ud68c\ud55c \uac12\uc774 \ub2ec\ub77c\uc9c0\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: NON REPEATABLE READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN\n Bob->>Database: SELECT\n Database->>+Bob: Alice\n Alice->>Database: BEGIN\n Alice->>Database: UPDATE(Alice to Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT\n Database->>+Bob: Bob"}),"\n",(0,t.jsx)(n.h3,{id:"\ud32c\ud140-\ub9ac\ub4dcphantom-read-phantom-row",children:"\ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)"}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ucffc\ub9ac \uc218\ud589\uc2dc, \uc218\ud589 \uacb0\uacfc\uac00 \ub2e4\ub978 \ud604\uc0c1",(0,t.jsx)(n.br,{}),"\n","\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud558\uace0 B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uc5ec A\uac00 \ub2e4\uc2dc \uc870\ud68c\ud560 \ub54c \uc874\uc7ac\ud558\uc9c0 \uc54a\uc740 \ub808\ucf54\ub4dc\uac00 \uc870\ud68c\ub418\ub294 \uacbd\uc6b0"]}),"\n",(0,t.jsx)(n.mermaid,{value:"---\ntitle: PHANTOM READ\n---\nsequenceDiagram\n participant Alice\n participant Database\n participant Bob\n Bob->>Database: BEGIN(TRX-ID: 1)\n Bob->>Database: SELECT COUNT\n Database->>+Bob: 1\n Alice->>Database: BEGIN(TRX-ID: 2)\n Alice->>Database: INSERT(Bob)\n Alice->>Database: COMMIT\n Bob->>Database: SELECT COUNT\n Database->>+Bob: 2"}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html",children:"Isolation Level, MySQL"})]})]})}function b(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,a)=>{a.d(n,{ah:()=>o});var t=a(67294);function r(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function i(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),a.push.apply(a,t)}return a}function l(e){for(var n=1;n=0||(r[a]=e[a]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var c=t.createContext({}),o=function(e){var n=t.useContext(c),a=n;return e&&(a="function"==typeof e?e(n):l(l({},n),e)),a},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},b=t.forwardRef((function(e,n){var a=e.components,r=e.mdxType,i=e.originalType,c=e.parentName,b=s(e,["components","mdxType","originalType","parentName"]),h=o(a),j=r,x=h["".concat(c,".").concat(j)]||h[j]||d[j]||i;return a?t.createElement(x,l(l({ref:n},b),{},{components:a})):t.createElement(x,l({ref:n},b))}));b.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/be497a8d.ef83736d.js b/assets/js/be497a8d.330d47db.js similarity index 99% rename from assets/js/be497a8d.ef83736d.js rename to assets/js/be497a8d.330d47db.js index ff24d203f..4f21cf75c 100644 --- a/assets/js/be497a8d.ef83736d.js +++ b/assets/js/be497a8d.330d47db.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6172],{92971:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var t=s(85893),r=s(3905);const i={title:"Docusaurus",slug:"docusaurus",tags:["Documentation"]},a=void 0,c={permalink:"/docusaurus",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",source:"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",title:"Docusaurus",description:"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4.",date:"2023-06-18T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 18\uc77c",tags:[{label:"Documentation",permalink:"/tags/documentation"}],readingTime:10.095,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Docusaurus",slug:"docusaurus",tags:["Documentation"]},unlisted:!1,prevItem:{title:"\uc6f9\uc18c\ucf13",permalink:"/websocket"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",permalink:"/woowacourse-level2-retrospective"}},l={authorsImageUrls:[]},o=[{value:"\uc124\uce58",id:"\uc124\uce58",level:2},{value:"\ubc30\ud3ec",id:"\ubc30\ud3ec",level:2},{value:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131",id:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac-\uc0dd\uc131",level:3},{value:"\uc124\uc815 \ud30c\uc77c \uc218\uc815",id:"\uc124\uc815-\ud30c\uc77c-\uc218\uc815",level:3},{value:"\ud1a0\ud070 \uc124\uc815",id:"\ud1a0\ud070-\uc124\uc815",level:3},{value:"\ube0c\ub79c\uce58 \uc0dd\uc131",id:"\ube0c\ub79c\uce58-\uc0dd\uc131",level:3},{value:"\uc6cc\ud06c\ud50c\ub85c \uc791\uc131",id:"\uc6cc\ud06c\ud50c\ub85c-\uc791\uc131",level:3},{value:"\ub313\uae00 \uae30\ub2a5",id:"\ub313\uae00-\uae30\ub2a5",level:2},{value:"giscus \uc124\uc815",id:"giscus-\uc124\uc815",level:3},{value:"docusaurus \uc124\uc815",id:"docusaurus-\uc124\uc815",level:3},{value:"\uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30",id:"\uc54c\uace0\ub9ac\uc544-\uc124\uc815-\ubc0f-\uc9c1\uc811-\uad00\ub9ac\ud558\uae30",level:2},{value:"\uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778",id:"\uc54c\uace0\ub9ac\uc544-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\uc0dd\uc131-\ubc0f-\ud0a4-\ud655\uc778",level:3},{value:"\ud0a4 \uc0dd\uc131",id:"\ud0a4-\uc0dd\uc131",level:3},{value:".env \ud30c\uc77c \uc0dd\uc131",id:"env-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"config \ud30c\uc77c \uc0dd\uc131",id:"config-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1",id:"docker-\uc774\uc6a9\ud558\uc5ec-\ud06c\ub864\ub9c1",level:3},{value:"docusaurus \uc124\uc815",id:"docusaurus-\uc124\uc815-1",level:3},{value:"\ubd80\uac00 \uc124\uc815",id:"\ubd80\uac00-\uc124\uc815",level:2},{value:"\ud654\uba74 \uc0c1\ub2e8 Github Icon",id:"\ud654\uba74-\uc0c1\ub2e8-github-icon",level:3},{value:"\ucf54\ub4dc\ube14\ub7ed",id:"\ucf54\ub4dc\ube14\ub7ed",level:3},{value:"mermaid",id:"mermaid",level:3},{value:"\uad6d\uc81c\ud654 \uc124\uc815",id:"\uad6d\uc81c\ud654-\uc124\uc815",level:3},{value:"\ube14\ub85c\uadf8 \uae00 author",id:"\ube14\ub85c\uadf8-\uae00-author",level:3}];function u(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,r.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h2,{id:"\uc124\uce58",children:"\uc124\uce58"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/docs/installation",children:"\uacf5\uc2dd \ud648\ud398\uc774\uc9c0"}),"\uc5d0 \ub4e4\uc5b4\uac00\uc11c \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn create docusaurus\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ubc30\ud3ec",children:"\ubc30\ud3ec"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/docs/next/deployment#deploying-to-github-pages",children:"\ubc30\ud3ec \uc548\ub0b4 \ubb38\uc11c"}),(0,t.jsx)(n.br,{}),"\n","netlify\ub098 vercel \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ud50c\ub7ab\ud3fc\uc744 \ucd94\ucc9c\ud558\uace0 \uc788\uace0, \uac04\ub2e8\ud558\uace0, \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \ubc30\ud3ec\ub97c \ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 github pages\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac-\uc0dd\uc131",children:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["github pages\ub97c \uc774\uc6a9\ud558\ub824\uba74 ",(0,t.jsx)(n.a,{href:"https://github.com/greeng00se/greeng00se.github.io",children:"\uc608\uc2dc"}),"\uc640 \uac19\uc774 ",(0,t.jsx)(n.code,{children:"username.github.io"})," \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c organization\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ",(0,t.jsx)(n.code,{children:"organization.github.io"})," \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc124\uc815-\ud30c\uc77c-\uc218\uc815",children:"\uc124\uc815 \ud30c\uc77c \uc218\uc815"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"module.exports = {\n // ...\n url: 'https://greeng00se.github.io',\n baseUrl: '/',\n projectName: 'greeng00se.github.io',\n organizationName: 'greeng00se',\n trailingSlash: false,\n // ...\n};\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ud1a0\ud070-\uc124\uc815",children:"\ud1a0\ud070 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["github action\uc744 \uc704\ud574 \ubc30\ud3ec\uc6a9 \ud1a0\ud070\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uc5ec \uc0dd\uc131\ud55c \ub808\ud3ec\uc9c0\ud1a0\ub9ac\uc5d0 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 \ud1a0\ud070\uc744 \ud074\ub798\uc2dd \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ud588\uace0 \uc2a4\ucf54\ud504\ub294 [repo, user, workflow] \uc744 \uc124\uc815\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"github",src:s(29094).Z+"",width:"1598",height:"1670"})}),"\n",(0,t.jsx)(n.h3,{id:"\ube0c\ub79c\uce58-\uc0dd\uc131",children:"\ube0c\ub79c\uce58 \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["github\uc5d0\uc11c gh-pages \ube0c\ub79c\uce58\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","repository -> settings -> pages -> branch\uc5d0\uc11c \uc0dd\uc131\ud55c gh-pages\ub85c \ube0c\ub79c\uce58\ub97c \ubcc0\uacbd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc124\uc815\ud55c \ube0c\ub79c\uce58\uac00 \ubc30\ud3ec \ube0c\ub79c\uce58\uac00 \ub418\uba70, \ud574\ub2f9 \ube0c\ub79c\uce58\uc5d0 \uc788\ub294 \ud30c\uc77c\ub4e4\uc744 \uc774\uc6a9\ud574\uc11c \uc815\uc801 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc6cc\ud06c\ud50c\ub85c-\uc791\uc131",children:"\uc6cc\ud06c\ud50c\ub85c \uc791\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["Docusaurus 2.0 \uae30\uc900 Node.js 16.14 \uc774\uc0c1\uc758 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec\uc2dc\uc5d0\ub294 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c DEPLOY_TOKEN \uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yml",metastring:'title=".github/workflows/deploy.yml"',children:"name: blog\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n name: Deploy to GitHub Pages\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v2\n - uses: actions/setup-node@v3\n with:\n node-version: 18\n cache: yarn\n\n - name: Install dependencies\n run: yarn install --frozen-lockfile\n - name: Build website\n run: yarn build\n\n - name: Deploy to GitHub Pages\n uses: peaceiris/actions-gh-pages@v3\n with:\n github_token: ${{ secrets.DEPLOY_TOKEN }}\n publish_dir: ./build\n user_name: github-actions[bot]\n user_email: 41898282+github-actions[bot]@users.noreply.github.com\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ub313\uae00-\uae30\ub2a5",children:"\ub313\uae00 \uae30\ub2a5"}),"\n",(0,t.jsx)(n.p,{children:"giscus\ub97c \uc774\uc6a9\ud558\uc5ec \ub313\uae00 \uae30\ub2a5\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"giscus-\uc124\uc815",children:"giscus \uc124\uc815"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"\uacf5\uac1c \uc800\uc7a5\uc18c\uc5ec\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"giscus \uc571\uc774 \uc124\uce58\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Discussions \uae30\ub2a5\uc774 \ud574\ub2f9 \uc800\uc7a5\uc18c\uc5d0\uc11c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ",(0,t.jsx)(n.a,{href:"https://giscus.app/ko",children:"giscus"}),"\ub97c \ud655\uc778\ud558\uc790."]}),"\n",(0,t.jsx)(n.h3,{id:"docusaurus-\uc124\uc815",children:"docusaurus \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/ko/docs/next/swizzling",children:"swizzling"}),"\uc744 \uc774\uc6a9\ud558\uc5ec \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac10\uc2fc\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc5d0 \uac8c\uc2dc\ubb3c\uc744 giscus\uac00 \ud3ec\ud568\ub41c \ub9ac\uc561\ud2b8 \ucef4\ud3ec\ub10c\ud2b8\ub85c \uac10\uc2f8\ub294 \ud615\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec BlogPostItem\uc744 \ucd94\ucd9c\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap\n"})}),"\n",(0,t.jsxs)(n.p,{children:["\uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uba74 ",(0,t.jsx)(n.code,{children:"/src/theme/BlogPostItem/index.js"})," \uc704\uce58\uc5d0 \ud30c\uc77c\uc774 \uc0dd\uc131\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud30c\uc77c\uc758 \ub0b4\uc6a9\uc744 \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud558\uace0, \uc774\ub54c setAttribute \ubd80\ubd84\uc740 \uc801\uc808\ud558\uac8c \uc790\uc2e0\uc758 giscus \uc124\uc815\uc744 \uc774\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="/src/theme/BlogPostItem/index.js"',children:'import OriginalBlogPostItem from "@theme-original/BlogPostItem";\nimport React, { useEffect, useRef } from "react";\n// @ts-expect-error internal code\nimport { useColorMode } from "@docusaurus/theme-common";\nimport { useBlogPost } from "@docusaurus/theme-common/internal";\n\nconst giscusSelector = "iframe.giscus-frame";\n\nfunction BlogPostItem(props) {\n const { colorMode } = useColorMode();\n const { isBlogPostPage } = useBlogPost();\n const giscusTheme = colorMode === "dark" ? "dark" : "light";\n const containerRef = useRef(null);\n\n useEffect(() => {\n if (!isBlogPostPage) return;\n\n const giscusEl = containerRef.current.querySelector(giscusSelector);\n\n const createGiscusEl = () => {\n const script = document.createElement("script");\n\n script.src = "https://giscus.app/client.js";\n script.setAttribute("data-repo", "teco-chat/teco-chat.github.io");\n script.setAttribute("data-repo-id", "R_kgDOJZ5j0Q");\n script.setAttribute("data-category", "Announcements");\n script.setAttribute("data-category-id", "DIC_kwDOJZ5j0c4CXS_Q");\n script.setAttribute("data-mapping", "pathname");\n script.setAttribute("data-strict", "0");\n script.setAttribute("data-reactions-enabled", "1");\n script.setAttribute("data-emit-metadata", "0");\n script.setAttribute("data-input-position", "bottom");\n script.setAttribute("data-theme", giscusTheme);\n script.setAttribute("data-lang", "ko");\n script.crossOrigin = "anonymous";\n script.async = true;\n \n containerRef.current.appendChild(script);\n };\n\n const postThemeMessage = () => {\n const message = {\n setConfig: {\n theme: giscusTheme,\n }\n };\n\n giscusEl.contentWindow.postMessage({ giscus: message }, "https://giscus.app");\n };\n\n giscusEl ? postThemeMessage() : createGiscusEl();\n }, [giscusTheme]);\n\n return (\n <>\n \n {isBlogPostPage &&
}\n \n );\n}\n\nexport default BlogPostItem;\n'})}),"\n",(0,t.jsx)(n.h2,{id:"\uc54c\uace0\ub9ac\uc544-\uc124\uc815-\ubc0f-\uc9c1\uc811-\uad00\ub9ac\ud558\uae30",children:"\uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uc54c\uace0\ub9ac\uc544\ub97c \uc0ac\uc6a9\ud558\uba74 \uac80\uc0c9 \uae30\ub2a5\uc744 \ucd94\uac00\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc720\ub8cc \ud50c\ub79c\uc774\ub098 netlify\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ud06c\ub864\ub7ec\ub97c \ub530\ub85c \uc81c\uacf5\ud574 \uc8fc\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ubb34\ub8cc \ud50c\ub79c\uc740 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uacfc, ",(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/",children:"docsearch"}),"\ub97c \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","docsearch\uc5d0 \ub4f1\ub85d\ud55c\ub2e4\uba74 \uc77c\uc8fc\uc77c\uc5d0 \ud55c \ubc88\uc529 \ud06c\ub864\ub9c1\uc774 \uc9c4\ud589\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/run-your-own/",children:"\uc9c1\uc811 \uc778\ub371\uc2a4 \uc218\uc9d1"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/config-file",children:"\uc124\uc815 \ud30c\uc77c"})}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc54c\uace0\ub9ac\uc544-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\uc0dd\uc131-\ubc0f-\ud0a4-\ud655\uc778",children:"\uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778"}),"\n",(0,t.jsxs)(n.p,{children:["\ud68c\uc6d0\uac00\uc785\uc744 \ud558\uace0 \uc0c8\ub85c\uc6b4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131\uc744 \ub204\ub978\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0dd\uc131\uc744 \ub2e4 \ub9c8\uce58\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 api \ud0a4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"algolia",src:s(41785).Z+"",width:"3194",height:"1520"})}),"\n",(0,t.jsx)(n.h3,{id:"\ud0a4-\uc0dd\uc131",children:"\ud0a4 \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\uae30 \uc704\ud55c \ud0a4\ub97c \uc0dd\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","addObject, editSettings, deleteIndex acl(\uc811\uadfc \uc81c\uc5b4 \ubaa9\ub85d)\uc774 \uc788\uc73c\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"key",src:s(4730).Z+"",width:"2496",height:"832"})}),"\n",(0,t.jsx)(n.h3,{id:"env-\ud30c\uc77c-\uc0dd\uc131",children:".env \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,t.jsx)(n.p,{children:"\ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0c1\ub2e8\uc5d0 .env \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:"APPLICATION_ID=MVIU5UEMOM\nAPI_KEY=\uc778\ub371\uc2a4_\uc0dd\uc131\uc6a9_\ud0a4\n"})}),"\n",(0,t.jsx)(n.h3,{id:"config-\ud30c\uc77c-\uc0dd\uc131",children:"config \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["\ub9c8\ucc2c\uac00\uc9c0\ub85c \ucd5c\uc0c1\ub2e8\uc5d0 config.json \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4.\n\uc124\uc815 \ud30c\uc77c\uc740 \ud574\ub2f9 ",(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/config-file",children:"\ub9c1\ud06c"}),"\ub97c \ucc38\uace0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ub294 Docusaurus\uc758 ",(0,t.jsx)(n.a,{href:"https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json",children:"\uc124\uc815 \ud30c\uc77c"}),"\uc744 \ucc38\uace0\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",metastring:'title="config.json"',children:'{\n "index_name": "teco",\n "start_urls": [\n "https://teco-chat.github.io/"\n ],\n "sitemap_urls": [\n "https://teco-chat.github.io/sitemap.xml"\n ],\n "sitemap_alternate_links": true,\n "stop_urls": [\n "/tests"\n ],\n "selectors": {\n "lvl0": {\n "selector": "(//ul[contains(@class,\'menu__list\')]//a[contains(@class, \'menu__link menu__link--sublist menu__link--active\')]/text() | //nav[contains(@class, \'navbar\')]//a[contains(@class, \'navbar__link--active\')]/text())[last()]",\n "type": "xpath",\n "global": true,\n "default_value": "Documentation"\n },\n "lvl1": "header h1",\n "lvl2": "article h2",\n "lvl3": "article h3",\n "lvl4": "article h4",\n "lvl5": "article h5, article td:first-child",\n "lvl6": "article h6",\n "text": "article p, article li, article td:last-child"\n },\n "strip_chars": " .,;:#",\n "custom_settings": {\n "separatorsToIndex": "_",\n "attributesForFaceting": [\n "language",\n "version",\n "type",\n "docusaurus_tag"\n ],\n "attributesToRetrieve": [\n "hierarchy",\n "content",\n "anchor",\n "url",\n "url_without_anchor",\n "type"\n ]\n },\n "conversation_id": [\n "833762294"\n ],\n "nb_hits": 46250\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"docker-\uc774\uc6a9\ud558\uc5ec-\ud06c\ub864\ub9c1",children:"docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1"}),"\n",(0,t.jsxs)(n.p,{children:["docker\uc640 jq\uac00 \ud544\uc694\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","jq\uac00 \uc124\uce58\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74 mac \uae30\uc900 brew\ub97c \uc774\uc6a9\ud574\uc11c \uc124\uce58\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"brew install jq\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec .env\uc640 config.json\uc744 \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\uc744 \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper\n'})}),"\n",(0,t.jsx)(n.h3,{id:"docusaurus-\uc124\uc815-1",children:"docusaurus \uc124\uc815"}),"\n",(0,t.jsx)(n.p,{children:"\uc804\uc5d0 \ud655\uc778\ud55c APP ID, Search-Only API KEY, IndexName\uc744 \uc774\uc6a9\ud558\uc5ec docusaurus.config \ud30c\uc77c\uc5d0 \uc124\uc815\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"themeConfig:\n /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n ({\n ...\n algolia: {\n appId: 'MVIU5UEMOM', // Application ID\n apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key\n indexName: 'teco', // config.json\uc5d0 \uc124\uc815\ud55c \uc778\ub371\uc2a4\uba85\n contextualSearch: true,\n },\n })\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ubd80\uac00-\uc124\uc815",children:"\ubd80\uac00 \uc124\uc815"}),"\n",(0,t.jsx)(n.h3,{id:"\ud654\uba74-\uc0c1\ub2e8-github-icon",children:"\ud654\uba74 \uc0c1\ub2e8 Github Icon"}),"\n",(0,t.jsx)(n.p,{children:"\ud30c\uc77c \ucd5c\ud558\ub2e8\uc5d0 \uc544\ub798 css \uad6c\ubb38\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-css",metastring:'title="/src/css/custom.css"',children:".header-github-link:hover {\n opacity: 0.6;\n}\n\n.header-github-link:before {\n content: '';\n width: 24px;\n height: 24px;\n display: flex;\n background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\")\n no-repeat;\n}\n\nhtml[data-theme='dark'] .header-github-link:before {\n background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\")\n no-repeat;\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"themeconfig -> navbar\uc5d0 github link\ub97c \uc124\uc815\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"navbar: {\n title: 'HELLO',\n items: [\n {\n href: 'https://github.com/greeng00se',\n position: 'right',\n className: 'header-github-link',\n 'aria-label': 'GitHub repository',\n },\n ],\n},\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ucf54\ub4dc\ube14\ub7ed",children:"\ucf54\ub4dc\ube14\ub7ed"}),"\n",(0,t.jsxs)(n.p,{children:["java\ub098 kotlin\uc758 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ub77c\uc774\ud305\uc744 \uc9c0\uc6d0\ud574 \uc8fc\uc9c0 \uc54a\ub294\ub2e4.",(0,t.jsx)(n.br,{}),"\n","prism \uc124\uc815\uc744 \uc544\ub798\uc640 \uac19\uc774 \ubcc0\uacbd\ud574 \uc900\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"prism: {\n theme: lightCodeTheme,\n darkTheme: darkCodeTheme,\n additionalLanguages: ['java', 'kotlin'],\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"mermaid",children:"mermaid"}),"\n",(0,t.jsxs)(n.p,{children:["mermaid\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 ",(0,t.jsx)(n.code,{children:"@docusaurus/theme-mermaid"})," \ub97c \uc124\uce58\ud574\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn add @docusaurus/theme-mermaid\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc124\uce58 \ud6c4 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"const config = {\n ...\n markdown: {\n mermaid: true,\n },\n themes: [\n '@docusaurus/theme-mermaid'\n ],\n};\n"})}),"\n",(0,t.jsx)(n.p,{children:"themeConfig\uc5d0\uc11c mermaid\uc758 \ud14c\ub9c8\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"themeConfig:\n /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n ({\n ...\n mermaid: {\n theme: {\n light: 'neutral', \n dark: 'dark'\n },\n },\n }),\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uad6d\uc81c\ud654-\uc124\uc815",children:"\uad6d\uc81c\ud654 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uad6d\uc81c\ud654 \uc124\uc815\uc744 \ud55c\ub2e4\uba74 ",(0,t.jsx)(n.code,{children:"Older Entries"})," \ud615\ud0dc\uc758 \uc124\uba85\uc774 ",(0,t.jsx)(n.code,{children:"\ub2e4\uc74c \ud398\uc774\uc9c0"})," \ub85c \ubcc0\uacbd\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc124\uc815\ud30c\uc77c\uc5d0\uc11c i18n\uc5d0 \uc788\ub294 \ub85c\ucf00\uc77c \uc124\uc815\uc744 ko\ub85c \ubcc0\uacbd\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:'i18n: {\n defaultLocale: "ko",\n locales: ["ko"],\n},\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ube14\ub85c\uadf8-\uae00-author",children:"\ube14\ub85c\uadf8 \uae00 author"}),"\n",(0,t.jsx)(n.p,{children:"\ud300\uc6d0 \ubcc4\ub85c \ubb38\uc11c\ub97c \uad00\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc5b4\ub5a4 \ud300\uc6d0\uc774 \uae00\uc744 \uc791\uc131\ud588\ub294\uc9c0 \uc124\uc815\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"author",src:s(31897).Z+"",width:"2362",height:"1076"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"authors.yml"})," \ud30c\uc77c\uc744 \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \uae30\ubcf8 \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yml",metastring:'title="/blog/authors.yml"',children:"herb:\n name: \ud5c8\ube0c\n title: Backend\n url: https://github.com/greeng00se\n image_url: https://github.com/greeng00se.png\n\nmallang:\n name: \ub9d0\ub791\n title: Backend\n url: https://github.com/shin-mallang\n image_url: https://github.com/shin-mallang.png\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ube14\ub85c\uadf8 \uae00\uc744 \uc791\uc131\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc774 authors\uc5d0 \ub123\uc5b4\uc8fc\uae30\ub9cc \ud558\uba74 \ub41c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-mdx",children:"---\nslug: 1\ntitle: Hello World\nauthors: [herb, mallang]\ntags: [hello, docusaurus]\n---\n\n\uccab \ubc88\uc9f8 \ubb38\uc11c \ub0b4\uc6a9\n"})})]})}function d(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},3905:(e,n,s)=>{s.d(n,{ah:()=>o});var t=s(67294);function r(e,n,s){return n in e?Object.defineProperty(e,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[n]=s,e}function i(e,n){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),s.push.apply(s,t)}return s}function a(e){for(var n=1;n=0||(r[s]=e[s]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,s)&&(r[s]=e[s])}return r}var l=t.createContext({}),o=function(e){var n=t.useContext(l),s=n;return e&&(s="function"==typeof e?e(n):a(a({},n),e)),s},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var s=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=o(s),g=r,p=h["".concat(l,".").concat(g)]||h[g]||u[g]||i;return s?t.createElement(p,a(a({ref:n},d),{},{components:s})):t.createElement(p,a({ref:n},d))}));d.displayName="MDXCreateElement"},41785:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/algolia-3dbac5c1606f7f0daed9cb27a429db50.png"},31897:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/author-1bd517bb7763257e2139e1063fd92492.png"},29094:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/github-d866f69755a1e17d4f17a262bd30d56d.png"},4730:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/key-2d0b59e69e9ca0b21c49b76159266e74.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6172],{92971:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var t=s(85893),r=s(3905);const i={title:"Docusaurus",slug:"docusaurus",tags:["Documentation"]},a=void 0,c={permalink:"/docusaurus",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",source:"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",title:"Docusaurus",description:"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4.",date:"2023-06-18T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 18\uc77c",tags:[{label:"Documentation",permalink:"/tags/documentation"}],readingTime:10.095,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Docusaurus",slug:"docusaurus",tags:["Documentation"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",permalink:"/woowacourse-level2-retrospective"},nextItem:{title:"\uc6f9\uc18c\ucf13",permalink:"/websocket"}},l={authorsImageUrls:[]},o=[{value:"\uc124\uce58",id:"\uc124\uce58",level:2},{value:"\ubc30\ud3ec",id:"\ubc30\ud3ec",level:2},{value:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131",id:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac-\uc0dd\uc131",level:3},{value:"\uc124\uc815 \ud30c\uc77c \uc218\uc815",id:"\uc124\uc815-\ud30c\uc77c-\uc218\uc815",level:3},{value:"\ud1a0\ud070 \uc124\uc815",id:"\ud1a0\ud070-\uc124\uc815",level:3},{value:"\ube0c\ub79c\uce58 \uc0dd\uc131",id:"\ube0c\ub79c\uce58-\uc0dd\uc131",level:3},{value:"\uc6cc\ud06c\ud50c\ub85c \uc791\uc131",id:"\uc6cc\ud06c\ud50c\ub85c-\uc791\uc131",level:3},{value:"\ub313\uae00 \uae30\ub2a5",id:"\ub313\uae00-\uae30\ub2a5",level:2},{value:"giscus \uc124\uc815",id:"giscus-\uc124\uc815",level:3},{value:"docusaurus \uc124\uc815",id:"docusaurus-\uc124\uc815",level:3},{value:"\uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30",id:"\uc54c\uace0\ub9ac\uc544-\uc124\uc815-\ubc0f-\uc9c1\uc811-\uad00\ub9ac\ud558\uae30",level:2},{value:"\uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778",id:"\uc54c\uace0\ub9ac\uc544-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\uc0dd\uc131-\ubc0f-\ud0a4-\ud655\uc778",level:3},{value:"\ud0a4 \uc0dd\uc131",id:"\ud0a4-\uc0dd\uc131",level:3},{value:".env \ud30c\uc77c \uc0dd\uc131",id:"env-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"config \ud30c\uc77c \uc0dd\uc131",id:"config-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1",id:"docker-\uc774\uc6a9\ud558\uc5ec-\ud06c\ub864\ub9c1",level:3},{value:"docusaurus \uc124\uc815",id:"docusaurus-\uc124\uc815-1",level:3},{value:"\ubd80\uac00 \uc124\uc815",id:"\ubd80\uac00-\uc124\uc815",level:2},{value:"\ud654\uba74 \uc0c1\ub2e8 Github Icon",id:"\ud654\uba74-\uc0c1\ub2e8-github-icon",level:3},{value:"\ucf54\ub4dc\ube14\ub7ed",id:"\ucf54\ub4dc\ube14\ub7ed",level:3},{value:"mermaid",id:"mermaid",level:3},{value:"\uad6d\uc81c\ud654 \uc124\uc815",id:"\uad6d\uc81c\ud654-\uc124\uc815",level:3},{value:"\ube14\ub85c\uadf8 \uae00 author",id:"\ube14\ub85c\uadf8-\uae00-author",level:3}];function u(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,r.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h2,{id:"\uc124\uce58",children:"\uc124\uce58"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/docs/installation",children:"\uacf5\uc2dd \ud648\ud398\uc774\uc9c0"}),"\uc5d0 \ub4e4\uc5b4\uac00\uc11c \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn create docusaurus\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ubc30\ud3ec",children:"\ubc30\ud3ec"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/docs/next/deployment#deploying-to-github-pages",children:"\ubc30\ud3ec \uc548\ub0b4 \ubb38\uc11c"}),(0,t.jsx)(n.br,{}),"\n","netlify\ub098 vercel \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ud50c\ub7ab\ud3fc\uc744 \ucd94\ucc9c\ud558\uace0 \uc788\uace0, \uac04\ub2e8\ud558\uace0, \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \ubc30\ud3ec\ub97c \ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 github pages\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac-\uc0dd\uc131",children:"\ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["github pages\ub97c \uc774\uc6a9\ud558\ub824\uba74 ",(0,t.jsx)(n.a,{href:"https://github.com/greeng00se/greeng00se.github.io",children:"\uc608\uc2dc"}),"\uc640 \uac19\uc774 ",(0,t.jsx)(n.code,{children:"username.github.io"})," \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub54c organization\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ",(0,t.jsx)(n.code,{children:"organization.github.io"})," \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc124\uc815-\ud30c\uc77c-\uc218\uc815",children:"\uc124\uc815 \ud30c\uc77c \uc218\uc815"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"module.exports = {\n // ...\n url: 'https://greeng00se.github.io',\n baseUrl: '/',\n projectName: 'greeng00se.github.io',\n organizationName: 'greeng00se',\n trailingSlash: false,\n // ...\n};\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ud1a0\ud070-\uc124\uc815",children:"\ud1a0\ud070 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["github action\uc744 \uc704\ud574 \ubc30\ud3ec\uc6a9 \ud1a0\ud070\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uc5ec \uc0dd\uc131\ud55c \ub808\ud3ec\uc9c0\ud1a0\ub9ac\uc5d0 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 \ud1a0\ud070\uc744 \ud074\ub798\uc2dd \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ud588\uace0 \uc2a4\ucf54\ud504\ub294 [repo, user, workflow] \uc744 \uc124\uc815\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"github",src:s(29094).Z+"",width:"1598",height:"1670"})}),"\n",(0,t.jsx)(n.h3,{id:"\ube0c\ub79c\uce58-\uc0dd\uc131",children:"\ube0c\ub79c\uce58 \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["github\uc5d0\uc11c gh-pages \ube0c\ub79c\uce58\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","repository -> settings -> pages -> branch\uc5d0\uc11c \uc0dd\uc131\ud55c gh-pages\ub85c \ube0c\ub79c\uce58\ub97c \ubcc0\uacbd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc124\uc815\ud55c \ube0c\ub79c\uce58\uac00 \ubc30\ud3ec \ube0c\ub79c\uce58\uac00 \ub418\uba70, \ud574\ub2f9 \ube0c\ub79c\uce58\uc5d0 \uc788\ub294 \ud30c\uc77c\ub4e4\uc744 \uc774\uc6a9\ud574\uc11c \uc815\uc801 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc6cc\ud06c\ud50c\ub85c-\uc791\uc131",children:"\uc6cc\ud06c\ud50c\ub85c \uc791\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["Docusaurus 2.0 \uae30\uc900 Node.js 16.14 \uc774\uc0c1\uc758 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc30\ud3ec\uc2dc\uc5d0\ub294 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c DEPLOY_TOKEN \uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yml",metastring:'title=".github/workflows/deploy.yml"',children:"name: blog\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n name: Deploy to GitHub Pages\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v2\n - uses: actions/setup-node@v3\n with:\n node-version: 18\n cache: yarn\n\n - name: Install dependencies\n run: yarn install --frozen-lockfile\n - name: Build website\n run: yarn build\n\n - name: Deploy to GitHub Pages\n uses: peaceiris/actions-gh-pages@v3\n with:\n github_token: ${{ secrets.DEPLOY_TOKEN }}\n publish_dir: ./build\n user_name: github-actions[bot]\n user_email: 41898282+github-actions[bot]@users.noreply.github.com\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ub313\uae00-\uae30\ub2a5",children:"\ub313\uae00 \uae30\ub2a5"}),"\n",(0,t.jsx)(n.p,{children:"giscus\ub97c \uc774\uc6a9\ud558\uc5ec \ub313\uae00 \uae30\ub2a5\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"giscus-\uc124\uc815",children:"giscus \uc124\uc815"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"\uacf5\uac1c \uc800\uc7a5\uc18c\uc5ec\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"giscus \uc571\uc774 \uc124\uce58\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"Discussions \uae30\ub2a5\uc774 \ud574\ub2f9 \uc800\uc7a5\uc18c\uc5d0\uc11c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ",(0,t.jsx)(n.a,{href:"https://giscus.app/ko",children:"giscus"}),"\ub97c \ud655\uc778\ud558\uc790."]}),"\n",(0,t.jsx)(n.h3,{id:"docusaurus-\uc124\uc815",children:"docusaurus \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docusaurus.io/ko/docs/next/swizzling",children:"swizzling"}),"\uc744 \uc774\uc6a9\ud558\uc5ec \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac10\uc2fc\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc5d0 \uac8c\uc2dc\ubb3c\uc744 giscus\uac00 \ud3ec\ud568\ub41c \ub9ac\uc561\ud2b8 \ucef4\ud3ec\ub10c\ud2b8\ub85c \uac10\uc2f8\ub294 \ud615\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec BlogPostItem\uc744 \ucd94\ucd9c\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap\n"})}),"\n",(0,t.jsxs)(n.p,{children:["\uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uba74 ",(0,t.jsx)(n.code,{children:"/src/theme/BlogPostItem/index.js"})," \uc704\uce58\uc5d0 \ud30c\uc77c\uc774 \uc0dd\uc131\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud30c\uc77c\uc758 \ub0b4\uc6a9\uc744 \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud558\uace0, \uc774\ub54c setAttribute \ubd80\ubd84\uc740 \uc801\uc808\ud558\uac8c \uc790\uc2e0\uc758 giscus \uc124\uc815\uc744 \uc774\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="/src/theme/BlogPostItem/index.js"',children:'import OriginalBlogPostItem from "@theme-original/BlogPostItem";\nimport React, { useEffect, useRef } from "react";\n// @ts-expect-error internal code\nimport { useColorMode } from "@docusaurus/theme-common";\nimport { useBlogPost } from "@docusaurus/theme-common/internal";\n\nconst giscusSelector = "iframe.giscus-frame";\n\nfunction BlogPostItem(props) {\n const { colorMode } = useColorMode();\n const { isBlogPostPage } = useBlogPost();\n const giscusTheme = colorMode === "dark" ? "dark" : "light";\n const containerRef = useRef(null);\n\n useEffect(() => {\n if (!isBlogPostPage) return;\n\n const giscusEl = containerRef.current.querySelector(giscusSelector);\n\n const createGiscusEl = () => {\n const script = document.createElement("script");\n\n script.src = "https://giscus.app/client.js";\n script.setAttribute("data-repo", "teco-chat/teco-chat.github.io");\n script.setAttribute("data-repo-id", "R_kgDOJZ5j0Q");\n script.setAttribute("data-category", "Announcements");\n script.setAttribute("data-category-id", "DIC_kwDOJZ5j0c4CXS_Q");\n script.setAttribute("data-mapping", "pathname");\n script.setAttribute("data-strict", "0");\n script.setAttribute("data-reactions-enabled", "1");\n script.setAttribute("data-emit-metadata", "0");\n script.setAttribute("data-input-position", "bottom");\n script.setAttribute("data-theme", giscusTheme);\n script.setAttribute("data-lang", "ko");\n script.crossOrigin = "anonymous";\n script.async = true;\n \n containerRef.current.appendChild(script);\n };\n\n const postThemeMessage = () => {\n const message = {\n setConfig: {\n theme: giscusTheme,\n }\n };\n\n giscusEl.contentWindow.postMessage({ giscus: message }, "https://giscus.app");\n };\n\n giscusEl ? postThemeMessage() : createGiscusEl();\n }, [giscusTheme]);\n\n return (\n <>\n \n {isBlogPostPage &&
}\n \n );\n}\n\nexport default BlogPostItem;\n'})}),"\n",(0,t.jsx)(n.h2,{id:"\uc54c\uace0\ub9ac\uc544-\uc124\uc815-\ubc0f-\uc9c1\uc811-\uad00\ub9ac\ud558\uae30",children:"\uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uc54c\uace0\ub9ac\uc544\ub97c \uc0ac\uc6a9\ud558\uba74 \uac80\uc0c9 \uae30\ub2a5\uc744 \ucd94\uac00\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc720\ub8cc \ud50c\ub79c\uc774\ub098 netlify\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ud06c\ub864\ub7ec\ub97c \ub530\ub85c \uc81c\uacf5\ud574 \uc8fc\ub294 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ubb34\ub8cc \ud50c\ub79c\uc740 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uacfc, ",(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/",children:"docsearch"}),"\ub97c \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","docsearch\uc5d0 \ub4f1\ub85d\ud55c\ub2e4\uba74 \uc77c\uc8fc\uc77c\uc5d0 \ud55c \ubc88\uc529 \ud06c\ub864\ub9c1\uc774 \uc9c4\ud589\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \uae00\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/run-your-own/",children:"\uc9c1\uc811 \uc778\ub371\uc2a4 \uc218\uc9d1"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/config-file",children:"\uc124\uc815 \ud30c\uc77c"})}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc54c\uace0\ub9ac\uc544-\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\uc0dd\uc131-\ubc0f-\ud0a4-\ud655\uc778",children:"\uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778"}),"\n",(0,t.jsxs)(n.p,{children:["\ud68c\uc6d0\uac00\uc785\uc744 \ud558\uace0 \uc0c8\ub85c\uc6b4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131\uc744 \ub204\ub978\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0dd\uc131\uc744 \ub2e4 \ub9c8\uce58\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 api \ud0a4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"algolia",src:s(41785).Z+"",width:"3194",height:"1520"})}),"\n",(0,t.jsx)(n.h3,{id:"\ud0a4-\uc0dd\uc131",children:"\ud0a4 \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["\uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\uae30 \uc704\ud55c \ud0a4\ub97c \uc0dd\uc131\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","addObject, editSettings, deleteIndex acl(\uc811\uadfc \uc81c\uc5b4 \ubaa9\ub85d)\uc774 \uc788\uc73c\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"key",src:s(4730).Z+"",width:"2496",height:"832"})}),"\n",(0,t.jsx)(n.h3,{id:"env-\ud30c\uc77c-\uc0dd\uc131",children:".env \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,t.jsx)(n.p,{children:"\ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0c1\ub2e8\uc5d0 .env \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:"APPLICATION_ID=MVIU5UEMOM\nAPI_KEY=\uc778\ub371\uc2a4_\uc0dd\uc131\uc6a9_\ud0a4\n"})}),"\n",(0,t.jsx)(n.h3,{id:"config-\ud30c\uc77c-\uc0dd\uc131",children:"config \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,t.jsxs)(n.p,{children:["\ub9c8\ucc2c\uac00\uc9c0\ub85c \ucd5c\uc0c1\ub2e8\uc5d0 config.json \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4.\n\uc124\uc815 \ud30c\uc77c\uc740 \ud574\ub2f9 ",(0,t.jsx)(n.a,{href:"https://docsearch.algolia.com/docs/legacy/config-file",children:"\ub9c1\ud06c"}),"\ub97c \ucc38\uace0\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ub294 Docusaurus\uc758 ",(0,t.jsx)(n.a,{href:"https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json",children:"\uc124\uc815 \ud30c\uc77c"}),"\uc744 \ucc38\uace0\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",metastring:'title="config.json"',children:'{\n "index_name": "teco",\n "start_urls": [\n "https://teco-chat.github.io/"\n ],\n "sitemap_urls": [\n "https://teco-chat.github.io/sitemap.xml"\n ],\n "sitemap_alternate_links": true,\n "stop_urls": [\n "/tests"\n ],\n "selectors": {\n "lvl0": {\n "selector": "(//ul[contains(@class,\'menu__list\')]//a[contains(@class, \'menu__link menu__link--sublist menu__link--active\')]/text() | //nav[contains(@class, \'navbar\')]//a[contains(@class, \'navbar__link--active\')]/text())[last()]",\n "type": "xpath",\n "global": true,\n "default_value": "Documentation"\n },\n "lvl1": "header h1",\n "lvl2": "article h2",\n "lvl3": "article h3",\n "lvl4": "article h4",\n "lvl5": "article h5, article td:first-child",\n "lvl6": "article h6",\n "text": "article p, article li, article td:last-child"\n },\n "strip_chars": " .,;:#",\n "custom_settings": {\n "separatorsToIndex": "_",\n "attributesForFaceting": [\n "language",\n "version",\n "type",\n "docusaurus_tag"\n ],\n "attributesToRetrieve": [\n "hierarchy",\n "content",\n "anchor",\n "url",\n "url_without_anchor",\n "type"\n ]\n },\n "conversation_id": [\n "833762294"\n ],\n "nb_hits": 46250\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"docker-\uc774\uc6a9\ud558\uc5ec-\ud06c\ub864\ub9c1",children:"docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1"}),"\n",(0,t.jsxs)(n.p,{children:["docker\uc640 jq\uac00 \ud544\uc694\ud558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","jq\uac00 \uc124\uce58\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74 mac \uae30\uc900 brew\ub97c \uc774\uc6a9\ud574\uc11c \uc124\uce58\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"brew install jq\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec .env\uc640 config.json\uc744 \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\uc744 \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper\n'})}),"\n",(0,t.jsx)(n.h3,{id:"docusaurus-\uc124\uc815-1",children:"docusaurus \uc124\uc815"}),"\n",(0,t.jsx)(n.p,{children:"\uc804\uc5d0 \ud655\uc778\ud55c APP ID, Search-Only API KEY, IndexName\uc744 \uc774\uc6a9\ud558\uc5ec docusaurus.config \ud30c\uc77c\uc5d0 \uc124\uc815\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"themeConfig:\n /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n ({\n ...\n algolia: {\n appId: 'MVIU5UEMOM', // Application ID\n apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key\n indexName: 'teco', // config.json\uc5d0 \uc124\uc815\ud55c \uc778\ub371\uc2a4\uba85\n contextualSearch: true,\n },\n })\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ubd80\uac00-\uc124\uc815",children:"\ubd80\uac00 \uc124\uc815"}),"\n",(0,t.jsx)(n.h3,{id:"\ud654\uba74-\uc0c1\ub2e8-github-icon",children:"\ud654\uba74 \uc0c1\ub2e8 Github Icon"}),"\n",(0,t.jsx)(n.p,{children:"\ud30c\uc77c \ucd5c\ud558\ub2e8\uc5d0 \uc544\ub798 css \uad6c\ubb38\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-css",metastring:'title="/src/css/custom.css"',children:".header-github-link:hover {\n opacity: 0.6;\n}\n\n.header-github-link:before {\n content: '';\n width: 24px;\n height: 24px;\n display: flex;\n background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\")\n no-repeat;\n}\n\nhtml[data-theme='dark'] .header-github-link:before {\n background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\")\n no-repeat;\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"themeconfig -> navbar\uc5d0 github link\ub97c \uc124\uc815\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"navbar: {\n title: 'HELLO',\n items: [\n {\n href: 'https://github.com/greeng00se',\n position: 'right',\n className: 'header-github-link',\n 'aria-label': 'GitHub repository',\n },\n ],\n},\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ucf54\ub4dc\ube14\ub7ed",children:"\ucf54\ub4dc\ube14\ub7ed"}),"\n",(0,t.jsxs)(n.p,{children:["java\ub098 kotlin\uc758 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ub77c\uc774\ud305\uc744 \uc9c0\uc6d0\ud574 \uc8fc\uc9c0 \uc54a\ub294\ub2e4.",(0,t.jsx)(n.br,{}),"\n","prism \uc124\uc815\uc744 \uc544\ub798\uc640 \uac19\uc774 \ubcc0\uacbd\ud574 \uc900\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"prism: {\n theme: lightCodeTheme,\n darkTheme: darkCodeTheme,\n additionalLanguages: ['java', 'kotlin'],\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"mermaid",children:"mermaid"}),"\n",(0,t.jsxs)(n.p,{children:["mermaid\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 ",(0,t.jsx)(n.code,{children:"@docusaurus/theme-mermaid"})," \ub97c \uc124\uce58\ud574\uc57c \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn add @docusaurus/theme-mermaid\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc124\uce58 \ud6c4 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\uc744 \ucd94\uac00\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"const config = {\n ...\n markdown: {\n mermaid: true,\n },\n themes: [\n '@docusaurus/theme-mermaid'\n ],\n};\n"})}),"\n",(0,t.jsx)(n.p,{children:"themeConfig\uc5d0\uc11c mermaid\uc758 \ud14c\ub9c8\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:"themeConfig:\n /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n ({\n ...\n mermaid: {\n theme: {\n light: 'neutral', \n dark: 'dark'\n },\n },\n }),\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uad6d\uc81c\ud654-\uc124\uc815",children:"\uad6d\uc81c\ud654 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uad6d\uc81c\ud654 \uc124\uc815\uc744 \ud55c\ub2e4\uba74 ",(0,t.jsx)(n.code,{children:"Older Entries"})," \ud615\ud0dc\uc758 \uc124\uba85\uc774 ",(0,t.jsx)(n.code,{children:"\ub2e4\uc74c \ud398\uc774\uc9c0"})," \ub85c \ubcc0\uacbd\ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc124\uc815\ud30c\uc77c\uc5d0\uc11c i18n\uc5d0 \uc788\ub294 \ub85c\ucf00\uc77c \uc124\uc815\uc744 ko\ub85c \ubcc0\uacbd\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config"',children:'i18n: {\n defaultLocale: "ko",\n locales: ["ko"],\n},\n'})}),"\n",(0,t.jsx)(n.h3,{id:"\ube14\ub85c\uadf8-\uae00-author",children:"\ube14\ub85c\uadf8 \uae00 author"}),"\n",(0,t.jsx)(n.p,{children:"\ud300\uc6d0 \ubcc4\ub85c \ubb38\uc11c\ub97c \uad00\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc5b4\ub5a4 \ud300\uc6d0\uc774 \uae00\uc744 \uc791\uc131\ud588\ub294\uc9c0 \uc124\uc815\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"author",src:s(31897).Z+"",width:"2362",height:"1076"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"authors.yml"})," \ud30c\uc77c\uc744 \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \uae30\ubcf8 \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yml",metastring:'title="/blog/authors.yml"',children:"herb:\n name: \ud5c8\ube0c\n title: Backend\n url: https://github.com/greeng00se\n image_url: https://github.com/greeng00se.png\n\nmallang:\n name: \ub9d0\ub791\n title: Backend\n url: https://github.com/shin-mallang\n image_url: https://github.com/shin-mallang.png\n"})}),"\n",(0,t.jsx)(n.p,{children:"\ube14\ub85c\uadf8 \uae00\uc744 \uc791\uc131\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc774 authors\uc5d0 \ub123\uc5b4\uc8fc\uae30\ub9cc \ud558\uba74 \ub41c\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-mdx",children:"---\nslug: 1\ntitle: Hello World\nauthors: [herb, mallang]\ntags: [hello, docusaurus]\n---\n\n\uccab \ubc88\uc9f8 \ubb38\uc11c \ub0b4\uc6a9\n"})})]})}function d(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},3905:(e,n,s)=>{s.d(n,{ah:()=>o});var t=s(67294);function r(e,n,s){return n in e?Object.defineProperty(e,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[n]=s,e}function i(e,n){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),s.push.apply(s,t)}return s}function a(e){for(var n=1;n=0||(r[s]=e[s]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,s)&&(r[s]=e[s])}return r}var l=t.createContext({}),o=function(e){var n=t.useContext(l),s=n;return e&&(s="function"==typeof e?e(n):a(a({},n),e)),s},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var s=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=o(s),g=r,p=h["".concat(l,".").concat(g)]||h[g]||u[g]||i;return s?t.createElement(p,a(a({ref:n},d),{},{components:s})):t.createElement(p,a({ref:n},d))}));d.displayName="MDXCreateElement"},41785:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/algolia-3dbac5c1606f7f0daed9cb27a429db50.png"},31897:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/author-1bd517bb7763257e2139e1063fd92492.png"},29094:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/github-d866f69755a1e17d4f17a262bd30d56d.png"},4730:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/key-2d0b59e69e9ca0b21c49b76159266e74.png"}}]); \ No newline at end of file diff --git a/assets/js/c1b17b3f.e63c57c6.js b/assets/js/c1b17b3f.ba398bfc.js similarity index 98% rename from assets/js/c1b17b3f.e63c57c6.js rename to assets/js/c1b17b3f.ba398bfc.js index 8f275cd7d..cf47385d4 100644 --- a/assets/js/c1b17b3f.e63c57c6.js +++ b/assets/js/c1b17b3f.ba398bfc.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8927],{46681:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var a=n(85893),c=n(3905);const r={title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"cloudwatch",tags:["cloudwatch","log","monitoring"]},s=void 0,l={permalink:"/cloudwatch",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",source:"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",description:"CloudWatch",date:"2023-08-17T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 17\uc77c",tags:[{label:"cloudwatch",permalink:"/tags/cloudwatch"},{label:"log",permalink:"/tags/log"},{label:"monitoring",permalink:"/tags/monitoring"}],readingTime:5.35,hasTruncateMarker:!1,authors:[],frontMatter:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"cloudwatch",tags:["cloudwatch","log","monitoring"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",permalink:"/woowacourse-level3-retrospective"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",permalink:"/route-image-async-with-event"}},o={authorsImageUrls:[]},d=[{value:"CloudWatch",id:"cloudwatch",level:2},{value:"CloudWatch Metrics",id:"cloudwatch-metrics",level:2},{value:"CloudWatch Agent \uc124\uce58",id:"cloudwatch-agent-\uc124\uce58",level:2},{value:"IAM \uc5ed\ud560 \uc124\uc815",id:"iam-\uc5ed\ud560-\uc124\uc815",level:3},{value:"\uc124\uce58",id:"\uc124\uce58",level:3},{value:"Wizard",id:"wizard",level:3},{value:"\uc124\uc815 \ud30c\uc77c \uc801\uc6a9",id:"\uc124\uc815-\ud30c\uc77c-\uc801\uc6a9",level:3},{value:"types.db: no such file or directory \uc5d0\ub7ec",id:"typesdb-no-such-file-or-directory-\uc5d0\ub7ec",level:3},{value:"\uc9c0\ud45c \ud655\uc778",id:"\uc9c0\ud45c-\ud655\uc778",level:3},{value:"\ub85c\uadf8",id:"\ub85c\uadf8",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function i(e){const t={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h2,{id:"cloudwatch",children:"CloudWatch"}),"\n",(0,a.jsxs)(t.p,{children:["AWS \ub9ac\uc18c\uc2a4\uc640 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc9c0\ud45c\uc640 \ub85c\uadf8\uc5d0 \ub300\ud55c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc81c\uacf5\ud558\ub294 \uc11c\ube44\uc2a4\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc9c0\ud45c\ub97c \uac10\uc2dc\ud558\uc5ec \uc54c\ub9bc\uc744 \ubcf4\ub0b4\ub294 \uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ud504\ub9ac\ud2f0\uc5b4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \ub300\uc2dc\ubcf4\ub4dc\ub2f9 3$/M \uc758 \ube44\uc6a9\uc774 \uccad\uad6c\ub418\uace0, \uc9c0\ud45c\ub098 \ub85c\uadf8\uc758 \uc591\uc5d0 \ub530\ub77c \ube44\uc6a9\uc774 \ucd94\uac00\uc801\uc73c\ub85c \uccad\uad6c\ub41c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc694\uae08 \uc815\ubcf4\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \uc815\ubcf4\ub294 ",(0,a.jsx)(t.a,{href:"https://aws.amazon.com/ko/cloudwatch/pricing/",children:"\ub2e4\uc74c \ub9c1\ud06c"}),"\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.h2,{id:"cloudwatch-metrics",children:"CloudWatch Metrics"}),"\n",(0,a.jsxs)(t.p,{children:["\uae30\ubcf8\uc801\uc73c\ub85c 5\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc218\uc9d1\ub41c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc138\ubd80 \ubaa8\ub2c8\ud130\ub9c1(Detailed Monitoring)\uc744 \ud65c\uc131\ud654\ud558\uba74 1\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\ub97c \uc218\uc9d1\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub300\uc2dc\ubcf4\ub4dc\uc5d0\uc11c InstanceId\ub85c \uac80\uc0c9\ud558\uc5ec \uc218\uc9d1\ub41c \uc9c0\ud45c\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch1.png",src:n(86344).Z+"",width:"3214",height:"1636"})}),"\n",(0,a.jsx)(t.p,{children:"CPUUtilization, NetworkIn, NetworkOut\uacfc \uac19\uc740 \uae30\ubcf8\uc801\uc778 \uc9c0\ud45c\ub97c \uc81c\uacf5\ud558\uace0, \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud06c \uacf5\uac04\uacfc \uac19\uc740 \uc9c0\ud45c\ub97c \ud655\uc778\ud558\ub824\uba74 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\ub97c \uc124\uc815\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,a.jsx)(t.h2,{id:"cloudwatch-agent-\uc124\uce58",children:"CloudWatch Agent \uc124\uce58"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch Agent \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\uc640 \ub85c\uadf8\ub97c \uc218\uc9d1\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.h3,{id:"iam-\uc5ed\ud560-\uc124\uc815",children:"IAM \uc5ed\ud560 \uc124\uc815"}),"\n",(0,a.jsxs)(t.p,{children:["\uae30\ubcf8\uc801\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4\uac00 CloudWatchAgentServerPolicy\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","IAM \u2192 \uc5ed\ud560\uc5d0\uc11c \uc5ed\ud560 \uc0dd\uc131\uc744 \ud074\ub9ad\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch2.png",src:n(35939).Z+"",width:"2614",height:"1602"})}),"\n",(0,a.jsx)(t.p,{children:"CloudWatchAgentServerPolicy \uad8c\ud55c \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uace0, \uc801\ub2f9\ud55c \uc5ed\ud560 \uc774\ub984\uc744 \uc785\ub825\ud574\uc11c \uc5ed\ud560\uc744 \uc0dd\uc131\ud55c\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch3.png",src:n(5001).Z+"",width:"2650",height:"1616"})}),"\n",(0,a.jsxs)(t.p,{children:["EC2 \uc778\uc2a4\ud134\uc2a4 \ubaa9\ub85d\uc73c\ub85c \ub4e4\uc5b4\uac00\uc11c, CloudWatch Agent\ub97c \uc124\uce58\ud560 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud074\ub9ad\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc5d0\uc11c \uc774\uc804\uc5d0 \uc0dd\uc131\ud55c \uc5ed\ud560\uc744 \uc9c0\uc815\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch4.png",src:n(55693).Z+"",width:"1764",height:"800"})}),"\n",(0,a.jsx)(t.h3,{id:"\uc124\uce58",children:"\uc124\uce58"}),"\n",(0,a.jsx)(t.p,{children:"\ud658\uacbd\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,a.jsxs)(t.p,{children:["OS: ubuntu 22.04",(0,a.jsx)(t.br,{}),"\n","\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small (ARM64)"]}),"\n",(0,a.jsx)(t.p,{children:"\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uce58\ud55c\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb\nsudo dpkg -i -E ./amazon-cloudwatch-agent.deb\n"})}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html",children:"\uc0ac\uc6a9 \uc124\uba85\uc11c"}),"\uc5d0 \uac01 \uc778\uc2a4\ud134\uc2a4 \uc720\ud615\ub9c8\ub2e4 \ub2e4\uc6b4\ub85c\ub4dc \ub9c1\ud06c\uac00 \uc790\uc138\ud558\uac8c \uc548\ub0b4\ub418\uc5b4 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.h3,{id:"wizard",children:"Wizard"}),"\n",(0,a.jsxs)(t.p,{children:["CloudWatch Wizard\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uc124\uc815 \ud30c\uc77c \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub85c\uadf8\ub97c \uc218\uc9d1\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub294 \uacbd\uc6b0 Wizard \uc2e4\ud589 \uba85\ub839\uc5b4 \uc785\ub825 \uc804 log \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \ubcf5\uc0ac\ud574\ub450\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec Wizard\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard\n"})}),"\n",(0,a.jsxs)(t.p,{children:["\uc124\uc815\uc744 \uc9c4\ud589\ud558\ub2e4 \ubcf4\uba74 \uc124\uc815 \ud30c\uc77c\uc774 \uc5b4\ub5bb\uac8c \uad6c\uc131\ub420\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub85c\uadf8\ub97c \ucd94\uac00\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \uc785\ub825\ucc3d\uc774 \ub098\uc624\uba74 \uc900\ube44\ud574\ub480\ub358 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \uc785\ub825\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch5.png",src:n(41733).Z+"",width:"2320",height:"1328"})}),"\n",(0,a.jsx)(t.p,{children:"\uc911\uac04\uc5d0 SSM parameter store\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"Do you want to store the config in the SSM parameter store?\n1. yes\n2. no\n"})}),"\n",(0,a.jsxs)(t.p,{children:["\ucd94\uac00\uc801\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 2\ubc88\uc744 \uc120\ud0dd\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","Parameter Store \uad00\ub9ac\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc758 ",(0,a.jsx)(t.a,{href:"https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/",children:"\ubb38\uc11c"}),"\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac70 \uac19\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 ",(0,a.jsx)(t.code,{children:"/opt/aws/amazon-cloudwatch-agent/bin/config.json"})," \uc5d0 \uc124\uc815\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774 \uc800\uc7a5\ub41c\ub2e4."]}),"\n",(0,a.jsx)(t.h3,{id:"\uc124\uc815-\ud30c\uc77c-\uc801\uc6a9",children:"\uc124\uc815 \ud30c\uc77c \uc801\uc6a9"}),"\n",(0,a.jsxs)(t.p,{children:["\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uc815\ud30c\uc77c\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","file \ub4a4\uc5d0\ub294 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \uc808\ub300\uacbd\ub85c(\uc544\ub798 \uba85\ub839\uc5b4 \uae30\uc900 \uae30\ubcf8 \uc0dd\uc131 \uc704\uce58)\ub97c \uc785\ub825\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json\n"})}),"\n",(0,a.jsx)(t.h3,{id:"typesdb-no-such-file-or-directory-\uc5d0\ub7ec",children:"types.db: no such file or directory \uc5d0\ub7ec"}),"\n",(0,a.jsx)(t.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc740 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 types.db \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"Error running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory\n"})}),"\n",(0,a.jsx)(t.p,{children:"types.db \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo mkdir /usr/share/collectd\nsudo touch /usr/share/collectd/types.db\n"})}),"\n",(0,a.jsx)(t.h3,{id:"\uc9c0\ud45c-\ud655\uc778",children:"\uc9c0\ud45c \ud655\uc778"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch Metrics\uc5d0 \uac00\ubcf4\uba74 CWAgent\ub77c\ub294 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uac00 \ucd94\uac00\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch6.png",src:n(40721).Z+"",width:"2638",height:"708"})}),"\n",(0,a.jsx)(t.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ucd94\uac00\ud558\uc5ec \uc9c0\ud45c\uc5d0 \ub300\ud55c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-json",children:'{\n "metrics": {\n "namespace": "2023-hello-world",\n ......\n },\n} \n'})}),"\n",(0,a.jsx)(t.h3,{id:"\ub85c\uadf8",children:"\ub85c\uadf8"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch \u2192 \ub85c\uadf8 \uadf8\ub8f9\uc73c\ub85c \uac00\uba74 Wizard\ub85c \ucd94\uac00\ud55c \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch7.png",src:n(95994).Z+"",width:"2792",height:"1652"})}),"\n",(0,a.jsx)(t.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html",children:"CloudWatch\ub780 \ubb34\uc5c7\uc785\ub2c8\uae4c?"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://aws.amazon.com/ko/cloudwatch/pricing/",children:"Amazon CloudWatch \uc694\uae08"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html",children:"Linux \uc778\uc2a4\ud134\uc2a4 \uc9c0\ud45c"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html",children:"\uc11c\ubc84\uc5d0 CloudWatch \uc5d0\uc774\uc804\ud2b8 \uc124\uce58 \ubc0f \uc2e4\ud589"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/",children:"CloudWatch Agent\ub97c Parameter Store\uc5d0\uc11c \uad00\ub9ac\ud574 \ubcf4\uae30"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html",children:"CloudWatch\uc5d0\uc774\uc804\ud2b8 \uad6c\uc131 \ud30c\uc77c"})]})]})}function h(e={}){const{wrapper:t}={...(0,c.ah)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(i,{...e})}):i(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>d});var a=n(67294);function c(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(c[n]=e[n]);return c}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(c[n]=e[n])}return c}var o=a.createContext({}),d=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},i={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,c=e.mdxType,r=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),u=d(n),p=c,g=u["".concat(o,".").concat(p)]||u[p]||i[p]||r;return n?a.createElement(g,s(s({ref:t},h),{},{components:n})):a.createElement(g,s({ref:t},h))}));h.displayName="MDXCreateElement"},86344:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch1-859296155df6c20d0846f1388022a86c.png"},35939:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch2-ca9c26868dec08ea7133e2774f49798a.png"},5001:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch3-da10422b87e1901286b6d3e85e2c01cc.png"},55693:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch4-1e7eddc7e8dd890ac18352e900df8e07.png"},41733:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch5-67d1bd59d4552f4fe481452eddc78a5e.png"},40721:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch6-06ead809f7510938baee41505bc72b97.png"},95994:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch7-a86dfc0db307ddf7d1660d2b9e419c96.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8927],{46681:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var a=n(85893),c=n(3905);const r={title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"cloudwatch",tags:["cloudwatch","log","monitoring"]},s=void 0,l={permalink:"/cloudwatch",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",source:"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",description:"CloudWatch",date:"2023-08-17T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 17\uc77c",tags:[{label:"cloudwatch",permalink:"/tags/cloudwatch"},{label:"log",permalink:"/tags/log"},{label:"monitoring",permalink:"/tags/monitoring"}],readingTime:5.35,hasTruncateMarker:!1,authors:[],frontMatter:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"cloudwatch",tags:["cloudwatch","log","monitoring"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",permalink:"/route-image-async-with-event"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",permalink:"/woowacourse-level3-retrospective"}},o={authorsImageUrls:[]},d=[{value:"CloudWatch",id:"cloudwatch",level:2},{value:"CloudWatch Metrics",id:"cloudwatch-metrics",level:2},{value:"CloudWatch Agent \uc124\uce58",id:"cloudwatch-agent-\uc124\uce58",level:2},{value:"IAM \uc5ed\ud560 \uc124\uc815",id:"iam-\uc5ed\ud560-\uc124\uc815",level:3},{value:"\uc124\uce58",id:"\uc124\uce58",level:3},{value:"Wizard",id:"wizard",level:3},{value:"\uc124\uc815 \ud30c\uc77c \uc801\uc6a9",id:"\uc124\uc815-\ud30c\uc77c-\uc801\uc6a9",level:3},{value:"types.db: no such file or directory \uc5d0\ub7ec",id:"typesdb-no-such-file-or-directory-\uc5d0\ub7ec",level:3},{value:"\uc9c0\ud45c \ud655\uc778",id:"\uc9c0\ud45c-\ud655\uc778",level:3},{value:"\ub85c\uadf8",id:"\ub85c\uadf8",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function i(e){const t={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h2,{id:"cloudwatch",children:"CloudWatch"}),"\n",(0,a.jsxs)(t.p,{children:["AWS \ub9ac\uc18c\uc2a4\uc640 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc9c0\ud45c\uc640 \ub85c\uadf8\uc5d0 \ub300\ud55c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc81c\uacf5\ud558\ub294 \uc11c\ube44\uc2a4\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc9c0\ud45c\ub97c \uac10\uc2dc\ud558\uc5ec \uc54c\ub9bc\uc744 \ubcf4\ub0b4\ub294 \uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ud504\ub9ac\ud2f0\uc5b4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \ub300\uc2dc\ubcf4\ub4dc\ub2f9 3$/M \uc758 \ube44\uc6a9\uc774 \uccad\uad6c\ub418\uace0, \uc9c0\ud45c\ub098 \ub85c\uadf8\uc758 \uc591\uc5d0 \ub530\ub77c \ube44\uc6a9\uc774 \ucd94\uac00\uc801\uc73c\ub85c \uccad\uad6c\ub41c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc694\uae08 \uc815\ubcf4\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \uc815\ubcf4\ub294 ",(0,a.jsx)(t.a,{href:"https://aws.amazon.com/ko/cloudwatch/pricing/",children:"\ub2e4\uc74c \ub9c1\ud06c"}),"\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.h2,{id:"cloudwatch-metrics",children:"CloudWatch Metrics"}),"\n",(0,a.jsxs)(t.p,{children:["\uae30\ubcf8\uc801\uc73c\ub85c 5\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc218\uc9d1\ub41c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc138\ubd80 \ubaa8\ub2c8\ud130\ub9c1(Detailed Monitoring)\uc744 \ud65c\uc131\ud654\ud558\uba74 1\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\ub97c \uc218\uc9d1\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub300\uc2dc\ubcf4\ub4dc\uc5d0\uc11c InstanceId\ub85c \uac80\uc0c9\ud558\uc5ec \uc218\uc9d1\ub41c \uc9c0\ud45c\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch1.png",src:n(86344).Z+"",width:"3214",height:"1636"})}),"\n",(0,a.jsx)(t.p,{children:"CPUUtilization, NetworkIn, NetworkOut\uacfc \uac19\uc740 \uae30\ubcf8\uc801\uc778 \uc9c0\ud45c\ub97c \uc81c\uacf5\ud558\uace0, \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud06c \uacf5\uac04\uacfc \uac19\uc740 \uc9c0\ud45c\ub97c \ud655\uc778\ud558\ub824\uba74 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\ub97c \uc124\uc815\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,a.jsx)(t.h2,{id:"cloudwatch-agent-\uc124\uce58",children:"CloudWatch Agent \uc124\uce58"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch Agent \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\uc640 \ub85c\uadf8\ub97c \uc218\uc9d1\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.h3,{id:"iam-\uc5ed\ud560-\uc124\uc815",children:"IAM \uc5ed\ud560 \uc124\uc815"}),"\n",(0,a.jsxs)(t.p,{children:["\uae30\ubcf8\uc801\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4\uac00 CloudWatchAgentServerPolicy\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","IAM \u2192 \uc5ed\ud560\uc5d0\uc11c \uc5ed\ud560 \uc0dd\uc131\uc744 \ud074\ub9ad\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch2.png",src:n(35939).Z+"",width:"2614",height:"1602"})}),"\n",(0,a.jsx)(t.p,{children:"CloudWatchAgentServerPolicy \uad8c\ud55c \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uace0, \uc801\ub2f9\ud55c \uc5ed\ud560 \uc774\ub984\uc744 \uc785\ub825\ud574\uc11c \uc5ed\ud560\uc744 \uc0dd\uc131\ud55c\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch3.png",src:n(5001).Z+"",width:"2650",height:"1616"})}),"\n",(0,a.jsxs)(t.p,{children:["EC2 \uc778\uc2a4\ud134\uc2a4 \ubaa9\ub85d\uc73c\ub85c \ub4e4\uc5b4\uac00\uc11c, CloudWatch Agent\ub97c \uc124\uce58\ud560 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud074\ub9ad\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc5d0\uc11c \uc774\uc804\uc5d0 \uc0dd\uc131\ud55c \uc5ed\ud560\uc744 \uc9c0\uc815\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch4.png",src:n(55693).Z+"",width:"1764",height:"800"})}),"\n",(0,a.jsx)(t.h3,{id:"\uc124\uce58",children:"\uc124\uce58"}),"\n",(0,a.jsx)(t.p,{children:"\ud658\uacbd\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,a.jsxs)(t.p,{children:["OS: ubuntu 22.04",(0,a.jsx)(t.br,{}),"\n","\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small (ARM64)"]}),"\n",(0,a.jsx)(t.p,{children:"\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uce58\ud55c\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb\nsudo dpkg -i -E ./amazon-cloudwatch-agent.deb\n"})}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html",children:"\uc0ac\uc6a9 \uc124\uba85\uc11c"}),"\uc5d0 \uac01 \uc778\uc2a4\ud134\uc2a4 \uc720\ud615\ub9c8\ub2e4 \ub2e4\uc6b4\ub85c\ub4dc \ub9c1\ud06c\uac00 \uc790\uc138\ud558\uac8c \uc548\ub0b4\ub418\uc5b4 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.h3,{id:"wizard",children:"Wizard"}),"\n",(0,a.jsxs)(t.p,{children:["CloudWatch Wizard\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uc124\uc815 \ud30c\uc77c \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub85c\uadf8\ub97c \uc218\uc9d1\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub294 \uacbd\uc6b0 Wizard \uc2e4\ud589 \uba85\ub839\uc5b4 \uc785\ub825 \uc804 log \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \ubcf5\uc0ac\ud574\ub450\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec Wizard\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard\n"})}),"\n",(0,a.jsxs)(t.p,{children:["\uc124\uc815\uc744 \uc9c4\ud589\ud558\ub2e4 \ubcf4\uba74 \uc124\uc815 \ud30c\uc77c\uc774 \uc5b4\ub5bb\uac8c \uad6c\uc131\ub420\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub85c\uadf8\ub97c \ucd94\uac00\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \uc785\ub825\ucc3d\uc774 \ub098\uc624\uba74 \uc900\ube44\ud574\ub480\ub358 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \uc785\ub825\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch5.png",src:n(41733).Z+"",width:"2320",height:"1328"})}),"\n",(0,a.jsx)(t.p,{children:"\uc911\uac04\uc5d0 SSM parameter store\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"Do you want to store the config in the SSM parameter store?\n1. yes\n2. no\n"})}),"\n",(0,a.jsxs)(t.p,{children:["\ucd94\uac00\uc801\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 2\ubc88\uc744 \uc120\ud0dd\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","Parameter Store \uad00\ub9ac\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc758 ",(0,a.jsx)(t.a,{href:"https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/",children:"\ubb38\uc11c"}),"\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac70 \uac19\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 ",(0,a.jsx)(t.code,{children:"/opt/aws/amazon-cloudwatch-agent/bin/config.json"})," \uc5d0 \uc124\uc815\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774 \uc800\uc7a5\ub41c\ub2e4."]}),"\n",(0,a.jsx)(t.h3,{id:"\uc124\uc815-\ud30c\uc77c-\uc801\uc6a9",children:"\uc124\uc815 \ud30c\uc77c \uc801\uc6a9"}),"\n",(0,a.jsxs)(t.p,{children:["\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uc815\ud30c\uc77c\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","file \ub4a4\uc5d0\ub294 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \uc808\ub300\uacbd\ub85c(\uc544\ub798 \uba85\ub839\uc5b4 \uae30\uc900 \uae30\ubcf8 \uc0dd\uc131 \uc704\uce58)\ub97c \uc785\ub825\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json\n"})}),"\n",(0,a.jsx)(t.h3,{id:"typesdb-no-such-file-or-directory-\uc5d0\ub7ec",children:"types.db: no such file or directory \uc5d0\ub7ec"}),"\n",(0,a.jsx)(t.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc740 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 types.db \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"Error running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory\n"})}),"\n",(0,a.jsx)(t.p,{children:"types.db \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo mkdir /usr/share/collectd\nsudo touch /usr/share/collectd/types.db\n"})}),"\n",(0,a.jsx)(t.h3,{id:"\uc9c0\ud45c-\ud655\uc778",children:"\uc9c0\ud45c \ud655\uc778"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch Metrics\uc5d0 \uac00\ubcf4\uba74 CWAgent\ub77c\ub294 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uac00 \ucd94\uac00\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch6.png",src:n(40721).Z+"",width:"2638",height:"708"})}),"\n",(0,a.jsx)(t.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ucd94\uac00\ud558\uc5ec \uc9c0\ud45c\uc5d0 \ub300\ud55c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-json",children:'{\n "metrics": {\n "namespace": "2023-hello-world",\n ......\n },\n} \n'})}),"\n",(0,a.jsx)(t.h3,{id:"\ub85c\uadf8",children:"\ub85c\uadf8"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch \u2192 \ub85c\uadf8 \uadf8\ub8f9\uc73c\ub85c \uac00\uba74 Wizard\ub85c \ucd94\uac00\ud55c \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch7.png",src:n(95994).Z+"",width:"2792",height:"1652"})}),"\n",(0,a.jsx)(t.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html",children:"CloudWatch\ub780 \ubb34\uc5c7\uc785\ub2c8\uae4c?"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://aws.amazon.com/ko/cloudwatch/pricing/",children:"Amazon CloudWatch \uc694\uae08"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html",children:"Linux \uc778\uc2a4\ud134\uc2a4 \uc9c0\ud45c"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html",children:"\uc11c\ubc84\uc5d0 CloudWatch \uc5d0\uc774\uc804\ud2b8 \uc124\uce58 \ubc0f \uc2e4\ud589"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/",children:"CloudWatch Agent\ub97c Parameter Store\uc5d0\uc11c \uad00\ub9ac\ud574 \ubcf4\uae30"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html",children:"CloudWatch\uc5d0\uc774\uc804\ud2b8 \uad6c\uc131 \ud30c\uc77c"})]})]})}function h(e={}){const{wrapper:t}={...(0,c.ah)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(i,{...e})}):i(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>d});var a=n(67294);function c(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(c[n]=e[n]);return c}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(c[n]=e[n])}return c}var o=a.createContext({}),d=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},i={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,c=e.mdxType,r=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),u=d(n),p=c,g=u["".concat(o,".").concat(p)]||u[p]||i[p]||r;return n?a.createElement(g,s(s({ref:t},h),{},{components:n})):a.createElement(g,s({ref:t},h))}));h.displayName="MDXCreateElement"},86344:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch1-859296155df6c20d0846f1388022a86c.png"},35939:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch2-ca9c26868dec08ea7133e2774f49798a.png"},5001:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch3-da10422b87e1901286b6d3e85e2c01cc.png"},55693:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch4-1e7eddc7e8dd890ac18352e900df8e07.png"},41733:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch5-67d1bd59d4552f4fe481452eddc78a5e.png"},40721:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch6-06ead809f7510938baee41505bc72b97.png"},95994:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch7-a86dfc0db307ddf7d1660d2b9e419c96.png"}}]); \ No newline at end of file diff --git a/assets/js/c573638f.0c33f138.js b/assets/js/c573638f.0c33f138.js deleted file mode 100644 index c2928b5ee..000000000 --- a/assets/js/c573638f.0c33f138.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[964],{28866:a=>{a.exports=JSON.parse('[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse","count":16},{"label":"Retrospective","permalink":"/tags/retrospective","count":20},{"label":"test","permalink":"/tags/test","count":2},{"label":"web application","permalink":"/tags/web-application","count":1},{"label":"async","permalink":"/tags/async","count":2},{"label":"exception","permalink":"/tags/exception","count":1},{"label":"performance test","permalink":"/tags/performance-test","count":1},{"label":"mysql","permalink":"/tags/mysql","count":1},{"label":"replication","permalink":"/tags/replication","count":1},{"label":"cloudwatch","permalink":"/tags/cloudwatch","count":1},{"label":"log","permalink":"/tags/log","count":1},{"label":"monitoring","permalink":"/tags/monitoring","count":1},{"label":"event","permalink":"/tags/event","count":1},{"label":"image","permalink":"/tags/image","count":3},{"label":"awt","permalink":"/tags/awt","count":2},{"label":"Python","permalink":"/tags/python","count":1},{"label":"Mockito","permalink":"/tags/mockito","count":1},{"label":"static","permalink":"/tags/static","count":1},{"label":"Java","permalink":"/tags/java","count":5},{"label":"Spring Boot","permalink":"/tags/spring-boot","count":1},{"label":"Spring","permalink":"/tags/spring","count":1},{"label":"WebSocket","permalink":"/tags/web-socket","count":1},{"label":"Documentation","permalink":"/tags/documentation","count":1},{"label":"TecoChat","permalink":"/tags/teco-chat","count":3},{"label":"Pattern","permalink":"/tags/pattern","count":1},{"label":"Composite","permalink":"/tags/composite","count":1},{"label":"DTO","permalink":"/tags/dto","count":1},{"label":"Jenkins","permalink":"/tags/jenkins","count":1},{"label":"Elastic Beanstalk","permalink":"/tags/elastic-beanstalk","count":1},{"label":"Book","permalink":"/tags/book","count":3},{"label":"DataBase","permalink":"/tags/data-base","count":3},{"label":"Lock","permalink":"/tags/lock","count":2},{"label":"InnoDB","permalink":"/tags/inno-db","count":1},{"label":"MySQL","permalink":"/tags/my-sql","count":1},{"label":"Transaction","permalink":"/tags/transaction","count":1},{"label":"Isolation","permalink":"/tags/isolation","count":1},{"label":"Mock","permalink":"/tags/mock","count":1},{"label":"Class","permalink":"/tags/class","count":1},{"label":"JDBC","permalink":"/tags/jdbc","count":1},{"label":"GRASP","permalink":"/tags/grasp","count":1},{"label":"OOP","permalink":"/tags/oop","count":1},{"label":"IntelliJ","permalink":"/tags/intelli-j","count":1},{"label":"Kotlin","permalink":"/tags/kotlin","count":1},{"label":"Time","permalink":"/tags/time","count":1}]')}}]); \ No newline at end of file diff --git a/assets/js/c573638f.208f0fb2.js b/assets/js/c573638f.208f0fb2.js new file mode 100644 index 000000000..29585b4ce --- /dev/null +++ b/assets/js/c573638f.208f0fb2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[964],{28866:a=>{a.exports=JSON.parse('[{"label":"Book","permalink":"/tags/book","count":3},{"label":"Retrospective","permalink":"/tags/retrospective","count":20},{"label":"Java","permalink":"/tags/java","count":5},{"label":"Time","permalink":"/tags/time","count":1},{"label":"Kotlin","permalink":"/tags/kotlin","count":1},{"label":"IntelliJ","permalink":"/tags/intelli-j","count":1},{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse","count":16},{"label":"GRASP","permalink":"/tags/grasp","count":1},{"label":"OOP","permalink":"/tags/oop","count":1},{"label":"JDBC","permalink":"/tags/jdbc","count":1},{"label":"Class","permalink":"/tags/class","count":1},{"label":"Test","permalink":"/tags/test","count":2},{"label":"Mock","permalink":"/tags/mock","count":1},{"label":"DataBase","permalink":"/tags/data-base","count":3},{"label":"Transaction","permalink":"/tags/transaction","count":1},{"label":"Isolation","permalink":"/tags/isolation","count":1},{"label":"Lock","permalink":"/tags/lock","count":2},{"label":"MySQL","permalink":"/tags/my-sql","count":1},{"label":"InnoDB","permalink":"/tags/inno-db","count":1},{"label":"TecoChat","permalink":"/tags/teco-chat","count":3},{"label":"Jenkins","permalink":"/tags/jenkins","count":1},{"label":"Elastic Beanstalk","permalink":"/tags/elastic-beanstalk","count":1},{"label":"DTO","permalink":"/tags/dto","count":1},{"label":"Pattern","permalink":"/tags/pattern","count":1},{"label":"Composite","permalink":"/tags/composite","count":1},{"label":"Documentation","permalink":"/tags/documentation","count":1},{"label":"WebSocket","permalink":"/tags/web-socket","count":1},{"label":"Spring Boot","permalink":"/tags/spring-boot","count":1},{"label":"Spring","permalink":"/tags/spring","count":1},{"label":"image","permalink":"/tags/image","count":3},{"label":"awt","permalink":"/tags/awt","count":2},{"label":"Mockito","permalink":"/tags/mockito","count":1},{"label":"static","permalink":"/tags/static","count":1},{"label":"Python","permalink":"/tags/python","count":1},{"label":"async","permalink":"/tags/async","count":2},{"label":"event","permalink":"/tags/event","count":1},{"label":"cloudwatch","permalink":"/tags/cloudwatch","count":1},{"label":"log","permalink":"/tags/log","count":1},{"label":"monitoring","permalink":"/tags/monitoring","count":1},{"label":"mysql","permalink":"/tags/mysql","count":1},{"label":"replication","permalink":"/tags/replication","count":1},{"label":"performance test","permalink":"/tags/performance-test","count":1},{"label":"exception","permalink":"/tags/exception","count":1},{"label":"web application","permalink":"/tags/web-application","count":1}]')}}]); \ No newline at end of file diff --git a/assets/js/c6d04683.2f21610f.js b/assets/js/c6d04683.c9a2f336.js similarity index 98% rename from assets/js/c6d04683.2f21610f.js rename to assets/js/c6d04683.c9a2f336.js index 6c572fdee..0d4ac220e 100644 --- a/assets/js/c6d04683.2f21610f.js +++ b/assets/js/c6d04683.c9a2f336.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5436],{29316:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>d,frontMatter:()=>l,metadata:()=>c,toc:()=>o});var i=r(85893),t=r(3905);const l={title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",slug:"composite",tags:["Pattern","Composite"]},s=void 0,c={permalink:"/composite",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",source:"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",description:"\uc694\uad6c\uc0ac\ud56d",date:"2023-05-26T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 26\uc77c",tags:[{label:"Pattern",permalink:"/tags/pattern"},{label:"Composite",permalink:"/tags/composite"}],readingTime:4.74,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",slug:"composite",tags:["Pattern","Composite"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",permalink:"/tecochat-retrospective-3"},nextItem:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",permalink:"/subway-retrospective"}},a={authorsImageUrls:[]},o=[{value:"\uc694\uad6c\uc0ac\ud56d",id:"\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9",id:"\uc778\ud130\ud398\uc774\uc2a4-\uc0ac\uc6a9",level:3},{value:"\ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30",id:"\ubaa8\ub4e0-\uc694\uae08-\uc815\ucc45\uc744-\ud3ec\ud568\ud558\ub294-\uc0c8\ub85c\uc6b4-\uc694\uae08-\uc815\ucc45-\ub9cc\ub4e4\uae30",level:3},{value:"\uc815\ucc45\uc758 \uc21c\uc11c",id:"\uc815\ucc45\uc758-\uc21c\uc11c",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc774\ub780",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uad6c\uc131\uc694\uc18c",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uc0ac\uc6a9\uacfc-\uc8fc\uc694-\ubaa9\ud45c",level:3},{value:"\ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84",id:"\ud328\ud134-\uc0ac\uc6a9\uc2dc-\uc8fc\uc758\ud574\uc57c\ud560-\ubd80\ubd84",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={blockquote:"blockquote",br:"br",code:"code",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"\uc694\uad6c\uc0ac\ud56d",children:"\uc694\uad6c\uc0ac\ud56d"}),"\n",(0,i.jsx)(n.p,{children:"\uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uac70\ub9ac\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45"}),"\n",(0,i.jsx)(n.li,{children:"\ub178\uc120\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45"}),"\n",(0,i.jsx)(n.li,{children:"\uc5f0\ub839\ubcc4 \uc694\uae08 \ud560\uc778 \uc815\ucc45"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\uc778\ud130\ud398\uc774\uc2a4-\uc0ac\uc6a9",children:"\uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9"}),"\n",(0,i.jsxs)(n.p,{children:["\uc694\uae08 \uc815\ucc45\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud45c\ud604\ud560 \uc218 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc694\uae08\uc744 \uacc4\uc0b0\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ucd5c\ub2e8 \uacbd\ub85c \uacc4\uc0b0\uc758 \uacb0\uacfc, \uc0ac\uc6a9\uc790\uc758 \uc815\ubcf4, \uc694\uae08\uc744 \ubc1b\uc544 \uc694\uae08\uc744 \uacc4\uc0b0\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public interface FarePolicy {\n int calculate(Path path, Passenger passenger, int fare);\n}\n\npublic class BaseFarePolicy implements FarePolicy { ... }\npublic class DistanceFarePolicy implements FarePolicy { ... }\npublic class AgeDiscountFarePolicy implements FarePolicy { ... }\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite1",src:r(28629).Z+"",width:"1768",height:"554"})}),"\n",(0,i.jsx)(n.h3,{id:"\ubaa8\ub4e0-\uc694\uae08-\uc815\ucc45\uc744-\ud3ec\ud568\ud558\ub294-\uc0c8\ub85c\uc6b4-\uc694\uae08-\uc815\ucc45-\ub9cc\ub4e4\uae30",children:"\ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30"}),"\n",(0,i.jsxs)(n.p,{children:["\ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub97c \ubaa8\ub450 \uac00\uc9c0\uace0 \uc788\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\ub97c \ub9cc\ub4e4\uc5c8\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc774 \ub610\ud55c FarePolicy\ub97c \uad6c\ud604\ud55c \ud615\ud0dc\uac00 \ub418\uace0, \ud544\ub4dc\ub85c\ub294 \ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub4e4\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public class SubwayFarePolicy implements FarePolicy {\n\n private final List farePolicies;\n\n public SubwayFarePolicy(final List farePolicies) {\n this.farePolicies = farePolicies;\n }\n\n @Override\n public int calculate(final Path path, final Passenger passenger, final int fare) {\n int calculatedFare = fare;\n for (FarePolicy farePolicy : farePolicies) {\n calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);\n }\n return calculatedFare;\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\ub530\ub77c\uc11c \uadf8\ub9bc\uc73c\ub85c \ubcf8\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite2",src:r(33094).Z+"",width:"2020",height:"954"})}),"\n",(0,i.jsx)(n.h3,{id:"\uc815\ucc45\uc758-\uc21c\uc11c",children:"\uc815\ucc45\uc758 \uc21c\uc11c"}),"\n",(0,i.jsxs)(n.p,{children:["\uc9c0\ud558\ucca0 \uc694\uad6c\uc0ac\ud56d\uc740 \uc21c\uc11c\uac00 \uc911\uc694\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uae08\uc561\uc758 \ucd1d\ud569\uc744 \uad6c\ud558\uace0, \uadf8 \ud6c4\uc5d0 \ud560\uc778 \uc815\ucc45\uc774 \ub4e4\uc5b4\uac00\uc57c\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc790\uc2dd\ub4e4\uc758 \uc21c\uc11c\ub97c \uad00\ub9ac\ud560 \ub54c \uc8fc\uc758\ub97c \uae30\uc6b8\uc5ec\uc57c \ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Configuration \ud074\ub798\uc2a4\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc21c\uc11c\ub97c \uc9c1\uc811 \uc801\uc6a9\uc2dc\ucf30\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@Configuration\npublic class FareConfiguration {\n\n @Bean\n public FarePolicy farePolicy() {\n return new SubwayFarePolicy(List.of(\n new BaseFarePolicy(),\n new DistanceFarePolicy(),\n new AgeDiscountFarePolicy()\n ));\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc774\ub780",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite3",src:r(67922).Z+"",width:"1848",height:"482"})}),"\n",(0,i.jsx)(n.p,{children:"GOF\uc758 \ub514\uc790\uc778 \ud328\ud134 \ucc45\uc5d0\uc11c\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uba85\ud558\uace0 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:["\ubd80\ubd84\uacfc \uc804\uccb4\uc758 \uacc4\uce35\uc744 \ud45c\ud604\ud558\uae30 \uc704\ud574 \uac1d\uccb4\ub4e4\uc744 \ubaa8\uc544 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ud569\ub2c8\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ubcf5\ud569 \uac1d\uccb4\ub97c \ubaa8\ub450 \ub3d9\uc77c\ud558\uac8c \ub2e4\ub8f0 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc785\ub2c8\ub2e4."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc774 \ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uad6c\uc131\uc694\uc18c",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c"}),"\n",(0,i.jsx)(n.p,{children:"Component"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc9d1\ud569 \uad00\uacc4\uc5d0 \uc815\uc758\ub420 \ubaa8\ub4e0 \uac1d\uccb4\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uc694\uae08 \uc815\ucc45(FarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Leaf"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uac1c\ubcc4 \uac1d\uccb4, \uac1d\uccb4 \ud569\uc131\uc5d0 \uae30\ubcf8\uc774 \ub418\ub294 \uac1d\uccb4\uc758 \ud589\ub3d9"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uac70\ub9ac \ubcc4 \uc694\uae08 \uc815\ucc45(DistanceFarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Composite"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc5ec\ub7ec \uac1c\uc758 \uac1c\ubc1c \uac1d\uccb4\ub97c \ud3ec\ud568\ud558\ub294 \ud569\uc131 \uac1d\uccb4"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uc9c0\ud558\ucca0 \uc694\uae08 \uc815\ucc45(SubwayFarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Client"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uc0ac\uc6a9\uacfc-\uc8fc\uc694-\ubaa9\ud45c",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c"}),"\n",(0,i.jsxs)(n.p,{children:["\ubd80\ubd84 - \uc804\uccb4\uc758 \uad00\uacc4\ub97c \ud45c\ud604\ud558\uace0 \uc2f6\uc744 \ub54c",(0,i.jsx)(n.br,{}),"\n","Client \uae30\uc900\uc73c\ub85c Composite\uc640 Leaf\uc758 \ucc28\uc774\ub97c \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc798 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud574\uc57c\ub420 \ub54c"]}),"\n",(0,i.jsx)(n.h3,{id:"\ud328\ud134-\uc0ac\uc6a9\uc2dc-\uc8fc\uc758\ud574\uc57c\ud560-\ubd80\ubd84",children:"\ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84"}),"\n",(0,i.jsxs)(n.p,{children:["\ud328\ud134\uc740 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc758 \ud15c\ud50c\ub9bf\uc774\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ubc18\ubcf5\ub418\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc788\uc9c0\ub9cc \ud328\ud134\uc5d0 \ub9e4\ubab0\ub418\uc11c\ub294 \uc548\ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud328\ud134\uc744 \ub9f9\ubaa9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548\ub418\uace0, \ud604\uc7ac\uc758 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub530\ub77c \ud328\ud134\uc744 \uc720\ub3d9\uc801\uc73c\ub85c \uc218\uc815\ud574\uac00\uba74\uc11c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud56d\uc0c1 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uc0dd\uac01\ud558\uc790!"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134, GoF\uc758 \ub514\uc790\uc778 \ud328\ud134",(0,i.jsx)(n.br,{}),"\n","\ub514\uc790\uc778 \ud328\ud134\uacfc \ud504\ub808\uc784\uc6cc\ud06c, \uc624\ube0c\uc81d\ud2b8"]})]})}function d(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var i=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var a=i.createContext({}),o=function(e){var n=i.useContext(a),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var r=e.components,t=e.mdxType,l=e.originalType,a=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),u=o(r),h=t,j=u["".concat(a,".").concat(h)]||u[h]||p[h]||l;return r?i.createElement(j,s(s({ref:n},d),{},{components:r})):i.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"},28629:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite1-6117733e5244b235d9405ba72afb53ed.png"},33094:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite2-ac487a832bf12267cc91996ea3a5b9c7.png"},67922:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite3-016bf41863692b1f738bc89011687166.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5436],{29316:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>d,frontMatter:()=>l,metadata:()=>c,toc:()=>o});var i=r(85893),t=r(3905);const l={title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",slug:"composite",tags:["Pattern","Composite"]},s=void 0,c={permalink:"/composite",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",source:"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",description:"\uc694\uad6c\uc0ac\ud56d",date:"2023-05-26T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 26\uc77c",tags:[{label:"Pattern",permalink:"/tags/pattern"},{label:"Composite",permalink:"/tags/composite"}],readingTime:4.74,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",slug:"composite",tags:["Pattern","Composite"]},unlisted:!1,prevItem:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",permalink:"/subway-retrospective"},nextItem:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",permalink:"/tecochat-retrospective-3"}},a={authorsImageUrls:[]},o=[{value:"\uc694\uad6c\uc0ac\ud56d",id:"\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9",id:"\uc778\ud130\ud398\uc774\uc2a4-\uc0ac\uc6a9",level:3},{value:"\ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30",id:"\ubaa8\ub4e0-\uc694\uae08-\uc815\ucc45\uc744-\ud3ec\ud568\ud558\ub294-\uc0c8\ub85c\uc6b4-\uc694\uae08-\uc815\ucc45-\ub9cc\ub4e4\uae30",level:3},{value:"\uc815\ucc45\uc758 \uc21c\uc11c",id:"\uc815\ucc45\uc758-\uc21c\uc11c",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc774\ub780",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uad6c\uc131\uc694\uc18c",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uc0ac\uc6a9\uacfc-\uc8fc\uc694-\ubaa9\ud45c",level:3},{value:"\ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84",id:"\ud328\ud134-\uc0ac\uc6a9\uc2dc-\uc8fc\uc758\ud574\uc57c\ud560-\ubd80\ubd84",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={blockquote:"blockquote",br:"br",code:"code",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"\uc694\uad6c\uc0ac\ud56d",children:"\uc694\uad6c\uc0ac\ud56d"}),"\n",(0,i.jsx)(n.p,{children:"\uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uac70\ub9ac\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45"}),"\n",(0,i.jsx)(n.li,{children:"\ub178\uc120\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45"}),"\n",(0,i.jsx)(n.li,{children:"\uc5f0\ub839\ubcc4 \uc694\uae08 \ud560\uc778 \uc815\ucc45"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\uc778\ud130\ud398\uc774\uc2a4-\uc0ac\uc6a9",children:"\uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9"}),"\n",(0,i.jsxs)(n.p,{children:["\uc694\uae08 \uc815\ucc45\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud45c\ud604\ud560 \uc218 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc694\uae08\uc744 \uacc4\uc0b0\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ucd5c\ub2e8 \uacbd\ub85c \uacc4\uc0b0\uc758 \uacb0\uacfc, \uc0ac\uc6a9\uc790\uc758 \uc815\ubcf4, \uc694\uae08\uc744 \ubc1b\uc544 \uc694\uae08\uc744 \uacc4\uc0b0\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public interface FarePolicy {\n int calculate(Path path, Passenger passenger, int fare);\n}\n\npublic class BaseFarePolicy implements FarePolicy { ... }\npublic class DistanceFarePolicy implements FarePolicy { ... }\npublic class AgeDiscountFarePolicy implements FarePolicy { ... }\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite1",src:r(28629).Z+"",width:"1768",height:"554"})}),"\n",(0,i.jsx)(n.h3,{id:"\ubaa8\ub4e0-\uc694\uae08-\uc815\ucc45\uc744-\ud3ec\ud568\ud558\ub294-\uc0c8\ub85c\uc6b4-\uc694\uae08-\uc815\ucc45-\ub9cc\ub4e4\uae30",children:"\ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30"}),"\n",(0,i.jsxs)(n.p,{children:["\ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub97c \ubaa8\ub450 \uac00\uc9c0\uace0 \uc788\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\ub97c \ub9cc\ub4e4\uc5c8\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc774 \ub610\ud55c FarePolicy\ub97c \uad6c\ud604\ud55c \ud615\ud0dc\uac00 \ub418\uace0, \ud544\ub4dc\ub85c\ub294 \ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub4e4\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public class SubwayFarePolicy implements FarePolicy {\n\n private final List farePolicies;\n\n public SubwayFarePolicy(final List farePolicies) {\n this.farePolicies = farePolicies;\n }\n\n @Override\n public int calculate(final Path path, final Passenger passenger, final int fare) {\n int calculatedFare = fare;\n for (FarePolicy farePolicy : farePolicies) {\n calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);\n }\n return calculatedFare;\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\ub530\ub77c\uc11c \uadf8\ub9bc\uc73c\ub85c \ubcf8\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite2",src:r(33094).Z+"",width:"2020",height:"954"})}),"\n",(0,i.jsx)(n.h3,{id:"\uc815\ucc45\uc758-\uc21c\uc11c",children:"\uc815\ucc45\uc758 \uc21c\uc11c"}),"\n",(0,i.jsxs)(n.p,{children:["\uc9c0\ud558\ucca0 \uc694\uad6c\uc0ac\ud56d\uc740 \uc21c\uc11c\uac00 \uc911\uc694\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uae08\uc561\uc758 \ucd1d\ud569\uc744 \uad6c\ud558\uace0, \uadf8 \ud6c4\uc5d0 \ud560\uc778 \uc815\ucc45\uc774 \ub4e4\uc5b4\uac00\uc57c\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc790\uc2dd\ub4e4\uc758 \uc21c\uc11c\ub97c \uad00\ub9ac\ud560 \ub54c \uc8fc\uc758\ub97c \uae30\uc6b8\uc5ec\uc57c \ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Configuration \ud074\ub798\uc2a4\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc21c\uc11c\ub97c \uc9c1\uc811 \uc801\uc6a9\uc2dc\ucf30\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@Configuration\npublic class FareConfiguration {\n\n @Bean\n public FarePolicy farePolicy() {\n return new SubwayFarePolicy(List.of(\n new BaseFarePolicy(),\n new DistanceFarePolicy(),\n new AgeDiscountFarePolicy()\n ));\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc774\ub780",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite3",src:r(67922).Z+"",width:"1848",height:"482"})}),"\n",(0,i.jsx)(n.p,{children:"GOF\uc758 \ub514\uc790\uc778 \ud328\ud134 \ucc45\uc5d0\uc11c\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uba85\ud558\uace0 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:["\ubd80\ubd84\uacfc \uc804\uccb4\uc758 \uacc4\uce35\uc744 \ud45c\ud604\ud558\uae30 \uc704\ud574 \uac1d\uccb4\ub4e4\uc744 \ubaa8\uc544 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ud569\ub2c8\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ubcf5\ud569 \uac1d\uccb4\ub97c \ubaa8\ub450 \ub3d9\uc77c\ud558\uac8c \ub2e4\ub8f0 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc785\ub2c8\ub2e4."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc774 \ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uad6c\uc131\uc694\uc18c",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c"}),"\n",(0,i.jsx)(n.p,{children:"Component"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc9d1\ud569 \uad00\uacc4\uc5d0 \uc815\uc758\ub420 \ubaa8\ub4e0 \uac1d\uccb4\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uc694\uae08 \uc815\ucc45(FarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Leaf"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uac1c\ubcc4 \uac1d\uccb4, \uac1d\uccb4 \ud569\uc131\uc5d0 \uae30\ubcf8\uc774 \ub418\ub294 \uac1d\uccb4\uc758 \ud589\ub3d9"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uac70\ub9ac \ubcc4 \uc694\uae08 \uc815\ucc45(DistanceFarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Composite"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc5ec\ub7ec \uac1c\uc758 \uac1c\ubc1c \uac1d\uccb4\ub97c \ud3ec\ud568\ud558\ub294 \ud569\uc131 \uac1d\uccb4"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uc9c0\ud558\ucca0 \uc694\uae08 \uc815\ucc45(SubwayFarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Client"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uc0ac\uc6a9\uacfc-\uc8fc\uc694-\ubaa9\ud45c",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c"}),"\n",(0,i.jsxs)(n.p,{children:["\ubd80\ubd84 - \uc804\uccb4\uc758 \uad00\uacc4\ub97c \ud45c\ud604\ud558\uace0 \uc2f6\uc744 \ub54c",(0,i.jsx)(n.br,{}),"\n","Client \uae30\uc900\uc73c\ub85c Composite\uc640 Leaf\uc758 \ucc28\uc774\ub97c \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc798 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud574\uc57c\ub420 \ub54c"]}),"\n",(0,i.jsx)(n.h3,{id:"\ud328\ud134-\uc0ac\uc6a9\uc2dc-\uc8fc\uc758\ud574\uc57c\ud560-\ubd80\ubd84",children:"\ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84"}),"\n",(0,i.jsxs)(n.p,{children:["\ud328\ud134\uc740 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc758 \ud15c\ud50c\ub9bf\uc774\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ubc18\ubcf5\ub418\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc788\uc9c0\ub9cc \ud328\ud134\uc5d0 \ub9e4\ubab0\ub418\uc11c\ub294 \uc548\ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud328\ud134\uc744 \ub9f9\ubaa9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548\ub418\uace0, \ud604\uc7ac\uc758 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub530\ub77c \ud328\ud134\uc744 \uc720\ub3d9\uc801\uc73c\ub85c \uc218\uc815\ud574\uac00\uba74\uc11c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud56d\uc0c1 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uc0dd\uac01\ud558\uc790!"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134, GoF\uc758 \ub514\uc790\uc778 \ud328\ud134",(0,i.jsx)(n.br,{}),"\n","\ub514\uc790\uc778 \ud328\ud134\uacfc \ud504\ub808\uc784\uc6cc\ud06c, \uc624\ube0c\uc81d\ud2b8"]})]})}function d(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var i=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var a=i.createContext({}),o=function(e){var n=i.useContext(a),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var r=e.components,t=e.mdxType,l=e.originalType,a=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),u=o(r),h=t,j=u["".concat(a,".").concat(h)]||u[h]||p[h]||l;return r?i.createElement(j,s(s({ref:n},d),{},{components:r})):i.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"},28629:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite1-6117733e5244b235d9405ba72afb53ed.png"},33094:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite2-ac487a832bf12267cc91996ea3a5b9c7.png"},67922:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite3-016bf41863692b1f738bc89011687166.png"}}]); \ No newline at end of file diff --git a/assets/js/cb6229c3.5653afa0.js b/assets/js/cb6229c3.5e557995.js similarity index 97% rename from assets/js/cb6229c3.5653afa0.js rename to assets/js/cb6229c3.5e557995.js index afef57269..2fd52e1df 100644 --- a/assets/js/cb6229c3.5653afa0.js +++ b/assets/js/cb6229c3.5e557995.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7204],{95940:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>i});var t=r(85893),l=r(3905);const a={title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"mysql-lock",tags:["DataBase","Lock","MySQL"]},c=void 0,s={permalink:"/mysql-lock",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",source:"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",description:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",date:"2023-04-06T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 6\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Lock",permalink:"/tags/lock"},{label:"MySQL",permalink:"/tags/my-sql"}],readingTime:4.405,hasTruncateMarker:!1,authors:[],frontMatter:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"mysql-lock",tags:["DataBase","Lock","MySQL"]},unlisted:!1,prevItem:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/innodb-lock"},nextItem:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",permalink:"/transaction-and-isolation"}},o={authorsImageUrls:[]},i=[{value:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",id:"mysql-\uc5d4\uc9c4\uc758-\uc7a0\uae08",level:2},{value:"\uae00\ub85c\ubc8c \ub77d(Global lock)",id:"\uae00\ub85c\ubc8c-\ub77dglobal-lock",level:3},{value:"\ud14c\uc774\ube14 \ub77d(Table lock)",id:"\ud14c\uc774\ube14-\ub77dtable-lock",level:3},{value:"\ub124\uc784\ub4dc \ub77d(Named lock)",id:"\ub124\uc784\ub4dc-\ub77dnamed-lock",level:3},{value:"\uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)",id:"\uba54\ud0c0\ub370\uc774\ud130-\ub77dmetadata-lock",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"mysql-\uc5d4\uc9c4\uc758-\uc7a0\uae08",children:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08"}),"\n",(0,t.jsxs)(n.p,{children:["MySQL\uc5d0\uc11c\uc758 \ub77d\uc740 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub808\ubca8\uacfc, MySQL \uc5d4\uc9c4 \ub808\ubca8\ub85c \ub098\ub20c \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL \uc5d4\uc9c4 \ub808\ubca8\uc758 \uc7a0\uae08\uc740 \ubaa8\ub4e0 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce5c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uae00\ub85c\ubc8c-\ub77dglobal-lock",children:"\uae00\ub85c\ubc8c \ub77d(Global lock)"}),"\n",(0,t.jsx)(n.p,{children:"MySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08 \uc911 \uac00\uc7a5 \ub113\uc740 \ubc94\uc704\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc7a0\uae08\uc774\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc601\ud5a5\uc744 \ubbf8\uce58\ub294 \ubc94\uc704\ub294 \ud574\ub2f9 \uc11c\ubc84 \uc804\uccb4\uc774\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc791\uc5c5 \ub300\uc0c1 \ud14c\uc774\ube14, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0c1\uad00 \uc5c6\uc774 \ub3d9\uc77c\ud558\uac8c \uc601\ud5a5\uc744 \ubc1b\ub294\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \uc138\uc158\uc5d0\uc11c \uae00\ub85c\ubc8c \ub77d\uc744 \ud68d\ub4dd\ud558\uba74 \ud574\uc81c \ub420 \ub54c \uae4c\uc9c0 \uc870\ud68c\ub97c \uc81c\uc678\ud55c \ub300\ubd80\ubd84\uc758 \uba85\ub839\uc774 \ub300\uae30 \uc0c1\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc874\uc7ac\ud558\ub294 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \ubc31\uc5c5\uc744 \ubc1b\uc544\uc57c\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c\ub294 \ubc31\uc5c5 \uc2dc \uc870\uae08 \ub354 \uac00\ubcbc\uc6b4 \ubc31\uc5c5 \ub77d\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- GLOBAL LOCK\nFLUSH TABLES WITH READ LOCK;\n-- UNLOCK\nUNLOCK TABLES;\n\n-- BACKUP LOCK\nLOCK INSTANCE FOR BACKUP;\n-- UNLOCK\nUNLOCK INSTANCE;\n"})}),"\n",(0,t.jsx)(n.admonition,{title:"MyISAM",type:"note",children:(0,t.jsxs)(n.p,{children:["MySQL 5.5 \ubc84\uc804 \uc774\uc804\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, SELECT \uc791\uc5c5 \uc18d\ub3c4\uac00 \ube60\ub974\ub2e4."]})}),"\n",(0,t.jsx)(n.h3,{id:"\ud14c\uc774\ube14-\ub77dtable-lock",children:"\ud14c\uc774\ube14 \ub77d(Table lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\uac1c\ubcc4 \ud14c\uc774\ube14 \ub2e8\uc704\ub85c \uc124\uc815\ub418\ub294 \uc7a0\uae08\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba85\uc2dc\uc801 \ub610\ub294 \ubb35\uc2dc\uc801\uc73c\ub85c \ud2b9\uc815 \ud14c\uc774\ube14\uc758 \ub77d\uc744 \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubb35\uc2dc\uc801 \ub77d\uc740 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub294 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uba74 \ubc1c\uc0dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB \ud14c\uc774\ube14\uc5d0\ub294 DML \ucffc\ub9ac\ub294 \ubb34\uc2dc\ub418\uace0 DDL \uc77c \uacbd\uc6b0\uc5d0\ub9cc \ubb35\uc2dc\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- TABLE LOCK\nLOCK TABLES table_name [ READ | WRITE ]\n\n-- UNLOCK\nUNLOCK TABLES;\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ub124\uc784\ub4dc-\ub77dnamed-lock",children:"\ub124\uc784\ub4dc \ub77d(Named lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc784\uc758\uc758 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc7a0\uae08\uc73c\ub85c \uc720\uc800 \ub808\ubca8 \ub77d\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc5ec\ub7ec \uc2a4\ub808\ub4dc\ub098 \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc77c\ud55c \ub370\uc774\ud130\ub97c \uc218\uc815\ud558\ub824\ub294 \uacbd\uc6b0, \ub3d9\uc2dc\uc5d0 \uc218\uc815\ud558\uc9c0 \ubabb\ud558\ub3c4\ub85d \ubcf4\ud638\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- aGVyYg== \ub77c\ub294 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08 \ud68d\ub4dd, \uc774\ubbf8 \uc7a0\uae08\uc744 \uc0ac\uc6a9\uc911\uc778 \uacbd\uc6b0 1\ucd08 \ub3d9\uc548\ub9cc \ub300\uae30\nSELECT GET_LOCK('aGVyYg==', 1);\n\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc774 \uc124\uc815\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.\nSELECT IS_FREE_LOCK('aGVyYg==');\n\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4.\nSELECT RELEASE_LOCK('aGVyYg==');\n\n-- \uc704 3\uac1c \ud568\uc218 \ubaa8\ub450 \uc815\uc0c1\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud558\uac70\ub098 \ud574\uc81c\ud55c \uacbd\uc6b0\uc5d0 1\uc744, \uc544\ub2c8\uba74 0\uc744 \ubc18\ud658\ud55c\ub2e4.\n\n-- \ubaa8\ub4e0 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4. \ud574\uc81c\ub41c \uc7a0\uae08\uc758 \uac1c\uc218\ub97c \ubc18\ud658\ud55c\ub2e4.\nSELECT RELEASE_ALL_LOCKS();\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uba54\ud0c0\ub370\uc774\ud130-\ub77dmetadata-lock",children:"\uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac1d\uccb4\uc758 \uc774\ub984\uc774\ub098 \uad6c\uc870\ub97c \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \ud68d\ub4dd\ud558\ub294 \uc7a0\uae08\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba85\uc2dc\uc801\uc73c\ub85c \ud68d\ub4dd \ub610\ub294 \ud574\uc81c \ud560 \uc218 \uc5c6\uc9c0\ub9cc \ud14c\uc774\ube14\uc758 \uc774\ub984\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubcf4\ud1b5 \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ud14c\uc774\ube14\uc744 \ubc14\uafd4\uc57c\ud558\ub294 \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ubcc4\ub3c4\uc758 \uc784\uc2dc \ud14c\uc774\ube14\uc5d0 \uc11c\ube44\uc2a4\uc6a9 \ub7ad\ud0b9 \ub370\uc774\ud130 \uc0dd\uc131 \ud6c4 \uae30\uc874 \ud14c\uc774\ube14\uc744 \ubc31\uc5c5\ud558\ub294 \uacbd\uc6b0\n-- \uc544\ub798 \uad6c\ubb38 \uc2e4\ud589 \uc2dc \uba54\ud0c0\ub370\uc774\ud130 \ub77d\uc744 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.\nRENAME TABLE rank TO rank_backup, rank_new TO rank;\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://gywn.net/2013/12/mysql-user-level-lock/",children:"MySQL\uc758 User Level Lock\ub97c \ud65c\uc6a9\ud55c\ub2e4\uba74?, gywndi"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html#function_release-all-locks",children:"Locking Functions, MySQL 5.7 Reference"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks",children:"Locking Functions, MySQL 8.0 Reference"})]})]})}function p(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>i});var t=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function c(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var o=t.createContext({}),i=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):c(c({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,l=e.mdxType,a=e.originalType,o=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=i(r),m=l,h=u["".concat(o,".").concat(m)]||u[m]||d[m]||a;return r?t.createElement(h,c(c({ref:n},p),{},{components:r})):t.createElement(h,c({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7204],{95940:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>i});var t=r(85893),l=r(3905);const a={title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"mysql-lock",tags:["DataBase","Lock","MySQL"]},c=void 0,s={permalink:"/mysql-lock",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",source:"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",description:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",date:"2023-04-06T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 6\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Lock",permalink:"/tags/lock"},{label:"MySQL",permalink:"/tags/my-sql"}],readingTime:4.405,hasTruncateMarker:!1,authors:[],frontMatter:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"mysql-lock",tags:["DataBase","Lock","MySQL"]},unlisted:!1,prevItem:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",permalink:"/transaction-and-isolation"},nextItem:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/innodb-lock"}},o={authorsImageUrls:[]},i=[{value:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",id:"mysql-\uc5d4\uc9c4\uc758-\uc7a0\uae08",level:2},{value:"\uae00\ub85c\ubc8c \ub77d(Global lock)",id:"\uae00\ub85c\ubc8c-\ub77dglobal-lock",level:3},{value:"\ud14c\uc774\ube14 \ub77d(Table lock)",id:"\ud14c\uc774\ube14-\ub77dtable-lock",level:3},{value:"\ub124\uc784\ub4dc \ub77d(Named lock)",id:"\ub124\uc784\ub4dc-\ub77dnamed-lock",level:3},{value:"\uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)",id:"\uba54\ud0c0\ub370\uc774\ud130-\ub77dmetadata-lock",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"mysql-\uc5d4\uc9c4\uc758-\uc7a0\uae08",children:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08"}),"\n",(0,t.jsxs)(n.p,{children:["MySQL\uc5d0\uc11c\uc758 \ub77d\uc740 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub808\ubca8\uacfc, MySQL \uc5d4\uc9c4 \ub808\ubca8\ub85c \ub098\ub20c \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL \uc5d4\uc9c4 \ub808\ubca8\uc758 \uc7a0\uae08\uc740 \ubaa8\ub4e0 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce5c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uae00\ub85c\ubc8c-\ub77dglobal-lock",children:"\uae00\ub85c\ubc8c \ub77d(Global lock)"}),"\n",(0,t.jsx)(n.p,{children:"MySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08 \uc911 \uac00\uc7a5 \ub113\uc740 \ubc94\uc704\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc7a0\uae08\uc774\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc601\ud5a5\uc744 \ubbf8\uce58\ub294 \ubc94\uc704\ub294 \ud574\ub2f9 \uc11c\ubc84 \uc804\uccb4\uc774\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc791\uc5c5 \ub300\uc0c1 \ud14c\uc774\ube14, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0c1\uad00 \uc5c6\uc774 \ub3d9\uc77c\ud558\uac8c \uc601\ud5a5\uc744 \ubc1b\ub294\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \uc138\uc158\uc5d0\uc11c \uae00\ub85c\ubc8c \ub77d\uc744 \ud68d\ub4dd\ud558\uba74 \ud574\uc81c \ub420 \ub54c \uae4c\uc9c0 \uc870\ud68c\ub97c \uc81c\uc678\ud55c \ub300\ubd80\ubd84\uc758 \uba85\ub839\uc774 \ub300\uae30 \uc0c1\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc874\uc7ac\ud558\ub294 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \ubc31\uc5c5\uc744 \ubc1b\uc544\uc57c\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c\ub294 \ubc31\uc5c5 \uc2dc \uc870\uae08 \ub354 \uac00\ubcbc\uc6b4 \ubc31\uc5c5 \ub77d\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- GLOBAL LOCK\nFLUSH TABLES WITH READ LOCK;\n-- UNLOCK\nUNLOCK TABLES;\n\n-- BACKUP LOCK\nLOCK INSTANCE FOR BACKUP;\n-- UNLOCK\nUNLOCK INSTANCE;\n"})}),"\n",(0,t.jsx)(n.admonition,{title:"MyISAM",type:"note",children:(0,t.jsxs)(n.p,{children:["MySQL 5.5 \ubc84\uc804 \uc774\uc804\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, SELECT \uc791\uc5c5 \uc18d\ub3c4\uac00 \ube60\ub974\ub2e4."]})}),"\n",(0,t.jsx)(n.h3,{id:"\ud14c\uc774\ube14-\ub77dtable-lock",children:"\ud14c\uc774\ube14 \ub77d(Table lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\uac1c\ubcc4 \ud14c\uc774\ube14 \ub2e8\uc704\ub85c \uc124\uc815\ub418\ub294 \uc7a0\uae08\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba85\uc2dc\uc801 \ub610\ub294 \ubb35\uc2dc\uc801\uc73c\ub85c \ud2b9\uc815 \ud14c\uc774\ube14\uc758 \ub77d\uc744 \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubb35\uc2dc\uc801 \ub77d\uc740 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub294 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uba74 \ubc1c\uc0dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB \ud14c\uc774\ube14\uc5d0\ub294 DML \ucffc\ub9ac\ub294 \ubb34\uc2dc\ub418\uace0 DDL \uc77c \uacbd\uc6b0\uc5d0\ub9cc \ubb35\uc2dc\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- TABLE LOCK\nLOCK TABLES table_name [ READ | WRITE ]\n\n-- UNLOCK\nUNLOCK TABLES;\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ub124\uc784\ub4dc-\ub77dnamed-lock",children:"\ub124\uc784\ub4dc \ub77d(Named lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc784\uc758\uc758 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc7a0\uae08\uc73c\ub85c \uc720\uc800 \ub808\ubca8 \ub77d\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc5ec\ub7ec \uc2a4\ub808\ub4dc\ub098 \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc77c\ud55c \ub370\uc774\ud130\ub97c \uc218\uc815\ud558\ub824\ub294 \uacbd\uc6b0, \ub3d9\uc2dc\uc5d0 \uc218\uc815\ud558\uc9c0 \ubabb\ud558\ub3c4\ub85d \ubcf4\ud638\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- aGVyYg== \ub77c\ub294 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08 \ud68d\ub4dd, \uc774\ubbf8 \uc7a0\uae08\uc744 \uc0ac\uc6a9\uc911\uc778 \uacbd\uc6b0 1\ucd08 \ub3d9\uc548\ub9cc \ub300\uae30\nSELECT GET_LOCK('aGVyYg==', 1);\n\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc774 \uc124\uc815\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.\nSELECT IS_FREE_LOCK('aGVyYg==');\n\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4.\nSELECT RELEASE_LOCK('aGVyYg==');\n\n-- \uc704 3\uac1c \ud568\uc218 \ubaa8\ub450 \uc815\uc0c1\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud558\uac70\ub098 \ud574\uc81c\ud55c \uacbd\uc6b0\uc5d0 1\uc744, \uc544\ub2c8\uba74 0\uc744 \ubc18\ud658\ud55c\ub2e4.\n\n-- \ubaa8\ub4e0 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4. \ud574\uc81c\ub41c \uc7a0\uae08\uc758 \uac1c\uc218\ub97c \ubc18\ud658\ud55c\ub2e4.\nSELECT RELEASE_ALL_LOCKS();\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uba54\ud0c0\ub370\uc774\ud130-\ub77dmetadata-lock",children:"\uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac1d\uccb4\uc758 \uc774\ub984\uc774\ub098 \uad6c\uc870\ub97c \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \ud68d\ub4dd\ud558\ub294 \uc7a0\uae08\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba85\uc2dc\uc801\uc73c\ub85c \ud68d\ub4dd \ub610\ub294 \ud574\uc81c \ud560 \uc218 \uc5c6\uc9c0\ub9cc \ud14c\uc774\ube14\uc758 \uc774\ub984\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubcf4\ud1b5 \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ud14c\uc774\ube14\uc744 \ubc14\uafd4\uc57c\ud558\ub294 \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ubcc4\ub3c4\uc758 \uc784\uc2dc \ud14c\uc774\ube14\uc5d0 \uc11c\ube44\uc2a4\uc6a9 \ub7ad\ud0b9 \ub370\uc774\ud130 \uc0dd\uc131 \ud6c4 \uae30\uc874 \ud14c\uc774\ube14\uc744 \ubc31\uc5c5\ud558\ub294 \uacbd\uc6b0\n-- \uc544\ub798 \uad6c\ubb38 \uc2e4\ud589 \uc2dc \uba54\ud0c0\ub370\uc774\ud130 \ub77d\uc744 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.\nRENAME TABLE rank TO rank_backup, rank_new TO rank;\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://gywn.net/2013/12/mysql-user-level-lock/",children:"MySQL\uc758 User Level Lock\ub97c \ud65c\uc6a9\ud55c\ub2e4\uba74?, gywndi"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html#function_release-all-locks",children:"Locking Functions, MySQL 5.7 Reference"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks",children:"Locking Functions, MySQL 8.0 Reference"})]})]})}function p(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>i});var t=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function c(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var o=t.createContext({}),i=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):c(c({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,l=e.mdxType,a=e.originalType,o=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=i(r),m=l,h=u["".concat(o,".").concat(m)]||u[m]||d[m]||a;return r?t.createElement(h,c(c({ref:n},p),{},{components:r})):t.createElement(h,c({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/cc519f63.46c3d20e.js b/assets/js/cc519f63.a2f54eb7.js similarity index 99% rename from assets/js/cc519f63.46c3d20e.js rename to assets/js/cc519f63.a2f54eb7.js index d6fa36b61..58fc19444 100644 --- a/assets/js/cc519f63.46c3d20e.js +++ b/assets/js/cc519f63.a2f54eb7.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5323],{75824:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>d});var i=t(85893),r=t(3905);const o={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",slug:"route-image-implementation",tags:["image","awt"]},a=void 0,s={permalink:"/route-image-implementation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",source:"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",description:"\uac1c\uc694",date:"2023-08-02T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 2\uc77c",tags:[{label:"image",permalink:"/tags/image"},{label:"awt",permalink:"/tags/awt"}],readingTime:11.665,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",slug:"route-image-implementation",tags:["image","awt"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",permalink:"/route-image-async-with-event"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",permalink:"/route-image-python"}},l={authorsImageUrls:[]},d=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:2},{value:"\uad6c\ud604 \uacb0\uacfc",id:"\uad6c\ud604-\uacb0\uacfc",level:3},{value:"IMAGE_SIZE & ROUTE_SIZE",id:"image_size--route_size",level:3},{value:"\uc8fc\uc694 \ud074\ub798\uc2a4",id:"\uc8fc\uc694-\ud074\ub798\uc2a4",level:2},{value:"\uc694\uc57d",id:"\uc694\uc57d",level:3},{value:"\uc758\uc874\uad00\uacc4",id:"\uc758\uc874\uad00\uacc4",level:3},{value:"Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)",id:"coordinates\uc704\ub3c4-\uacbd\ub3c4\uc758-\uc77c\uae09-\uceec\ub809\uc158",level:3},{value:"Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)",id:"positions\uc2e4\uc81c-\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc5d0-\uc0ac\uc6a9\ud560-\uc704\uce58",level:3},{value:"RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)",id:"routeimagedrawer\uc2e4\uc81c-\uc774\ubbf8\uc9c0\uc5d0-\uacbd\ub85c\ub97c-\uadf8\ub824\uc8fc\ub294-\ud074\ub798\uc2a4",level:3},{value:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow",id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131-flow",level:2},{value:"1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44",id:"1-\uc774\ubbf8\uc9c0-\uc0dd\uc131-\uc900\ube44",level:3},{value:"2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad",id:"2-\uc120-\uadf8\ub9ac\uae30-\uc694\uccad",level:3},{value:"3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad",id:"3-\uc704\uce58-\uc810-\uadf8\ub9ac\uae30-\uc694\uccad",level:3},{value:"4. \uc5c5\ub85c\ub4dc \uc694\uccad",id:"4-\uc5c5\ub85c\ub4dc-\uc694\uccad",level:3},{value:"\uc804\uccb4 Flow",id:"\uc804\uccb4-flow",level:3}];function c(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,i.jsxs)(n.p,{children:["\uc5ec\ud589\uc5d0 \ub300\ud55c \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\uae30 \uc704\ud574 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d \ubc0f \uae30\uc220 \uc120\ud0dd\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 ",(0,i.jsx)(n.a,{href:"./route-image-intro",children:"\ub9c1\ud06c"}),"\uc5d0 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\uad6c\ud604-\uacb0\uacfc",children:"\uad6c\ud604 \uacb0\uacfc"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./result.png",src:t(59563).Z+"",width:"1840",height:"714"})}),"\n",(0,i.jsxs)(n.p,{children:["\uc608\uc2dc \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.strong,{children:"\uc11c\uc6b8\uc5ed(\uc810)"})," \u2192 \uc2e0\uc0ac\uc5ed \u2192 \ub178\ub7c9\uc9c4\uc5ed \u2192 \ud64d\ub300\uc785\uad6c\uc5ed \u2192 \uc885\ub85c3\uac00\uc5ed \u2192 \uc625\uc218\uc5ed \u2192 ",(0,i.jsx)(n.strong,{children:"\uad6c\ub85c\uc5ed(\uc810)"})," \u2192 \uc2e0\ub9bc\uc5ed \u2192 \ubc1c\uc0b0\uc5ed"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="\uc608\uc2dc \ub370\uc774\ud130"',children:"List x = List.of(\n 126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,\n 126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639\n);\nList y = List.of(\n 37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,\n 37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184\n);\nList xPoints = List.of(126.97094933811682, 126.88474839801178);\nList yPoints = List.of(37.55302829553499, 37.50129417536773);\n"})}),"\n",(0,i.jsx)(n.h3,{id:"image_size--route_size",children:"IMAGE_SIZE & ROUTE_SIZE"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageGenerator.java"',children:"private static final int IMAGE_SIZE = 800;\nprivate static final int ROUTE_SIZE = 600;\n"})}),"\n",(0,i.jsxs)(n.p,{children:["\ucf54\ub4dc\ub97c \ubcf4\uba74 IMAGE_SIZE\uc640 ROUTE_SIZE\uac00 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","IMAGE_SIZE\ub294 \ub9d0 \uadf8\ub300\ub85c \uc774\ubbf8\uc9c0\uc758 width\uc640 height\ub97c \uc758\ubbf8\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","ROUTE_SIZE\uc758 \uacbd\uc6b0 \uc0c1\ud558\uc88c\uc6b0 100px \ub9cc\ud07c\uc758 \uac04\uaca9\uc744 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc2e4\uc81c \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub294 600 * 600 \uc0ac\uc774\uc988\ub85c \uc0dd\uc131\ub41c\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./600.png",src:t(49812).Z+"",width:"976",height:"970"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"\uc0ac\uc774\uc988 \ubcc0\uacbd\uc758 \uc774\uc720"})}),"\n",(0,i.jsx)(n.p,{children:"255 * 255 \uc815\ub3c4\uc758 \uc791\uc740 \uc0ac\uc774\uc988\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud574\ubcf4\ub824\uace0 \ud588\ub294\ub370, \uc774\ubbf8\uc9c0\uc758 \uc120\uba85\ub3c4\uac00 \uc88b\uc9c0 \uc54a\uc544 800 * 800 \uc0ac\uc774\uc988\ub85c \ubcc0\uacbd\ud588\ub2e4."}),"\n",(0,i.jsx)(n.h2,{id:"\uc8fc\uc694-\ud074\ub798\uc2a4",children:"\uc8fc\uc694 \ud074\ub798\uc2a4"}),"\n",(0,i.jsx)(n.h3,{id:"\uc694\uc57d",children:"\uc694\uc57d"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"\ud074\ub798\uc2a4\uba85"}),(0,i.jsx)(n.th,{children:"\uc124\uba85"}),(0,i.jsx)(n.th,{children:"\ud2b9\uc774\uc0ac\ud56d"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Coordinate"}),(0,i.jsx)(n.td,{children:"\uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \uc704\uce58 \uac12"}),(0,i.jsx)(n.td,{children:"\uc88c\ud45c\ub97c \ub73b\ud558\uc9c0\ub9cc \uc5ec\ud589 \ub3c4\uba54\uc778\uc5d0 \ud3ec\ud568\ub41c Point \ud074\ub798\uc2a4\uc640 \uad6c\ubd84\ud558\uae30 \uc704\ud574 longitude, latitude\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 x, y \uc0ac\uc6a9"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Coordinates"}),(0,i.jsx)(n.td,{children:"Coordinate\uc758 \uc77c\uae09 \uceec\ub809\uc158"}),(0,i.jsx)(n.td,{children:"-"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Position"}),(0,i.jsx)(n.td,{children:"\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58 \uac12"}),(0,i.jsx)(n.td,{children:"Integer \ud0c0\uc785\uc758 x, y \uc0ac\uc6a9"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Positions"}),(0,i.jsx)(n.td,{children:"Positions\uc758 \uc77c\uae09 \uceec\ub809\uc158"}),(0,i.jsx)(n.td,{children:"-"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageDrawer"}),(0,i.jsx)(n.td,{children:"\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4 BufferedImage, Graphics2D\ub97c \uac00\uc9c0\uace0 \uc788\uc74c"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc0c1\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc74c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageUploader"}),(0,i.jsx)(n.td,{children:"BufferedImage\ub97c \ubc1b\uc544 \uc11c\ubc84\uc5d0 \uc5c5\ub85c\ub4dc \ud558\ub294 \ud074\ub798\uc2a4"}),(0,i.jsx)(n.td,{children:"\ud604\uc7ac \uc5c5\ub85c\ub4dc \uc704\uce58\uac00 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc544 \uc77c\ub2e8 \uae30\ubcf8(\ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8) \uc704\uce58\uc5d0 \uc0dd\uc131"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageGenerator"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uace0 \uc5c5\ub85c\ub4dc\ud558\ub294 \uc11c\ube44\uc2a4"}),(0,i.jsx)(n.td,{children:"\uc5ec\ud589 \uc885\ub8cc, \uac10\uc0c1 \uc800\uc7a5\uc2dc \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"BufferedImage(AWT)"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0 \ub370\uc774\ud130\ub97c \ucc98\ub9ac\ud558\uace0 \uc870\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9"}),(0,i.jsx)(n.td,{children:"\uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c\uac00 (0, 0)"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Graphics2D(AWT)"}),(0,i.jsx)(n.td,{children:"\uc120 \uadf8\ub9ac\uae30, \uc0c9\uc0c1 \uad00\ub9ac \ub4f1\uc744 \uc9c0\uc6d0\ud558\ub294 \ud074\ub798\uc2a4 \uc2e4\uc81c \ud574\ub2f9 \ud074\ub798\uc2a4\uc758 draw \uba54\uc11c\ub4dc\ub97c \uacbd\ub85c\ub97c \uadf8\ub9bc"}),(0,i.jsx)(n.td,{children:"JDK 1.2 \uc774\ud6c4\uc5d0 \ucd94\uac00\ub428, 2D(\ud3c9\uba74) \uadf8\ub798\ud53d \ud658\uacbd\uc744 \uc9c0\uc6d0, bufferedImage.createGraphics \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \uc0dd\uc131"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"\uc758\uc874\uad00\uacc4",children:"\uc758\uc874\uad00\uacc4"}),"\n",(0,i.jsx)(n.mermaid,{value:'graph TD\n C1[Coordinates] --\x3e C[Coordinate]\n P1[Positions] --\x3e P[Position]\n\n\tRID[RouteImageDrawer] -- "\uc911\uc559 \uc815\ub82c\ub41c Positions\ub97c \ubc1b\uc544 \uc774\ubbf8\uc9c0 \uc0dd\uc131" --\x3e P1\n\tRID --\x3e B[BufferedImage]\n\tRID --\x3e G[Graphics2D]\n\n\tC1 -- "calculatePositions \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc704\uce58 \uacc4\uc0b0" --\x3e P1\n\n\tRIU[RouteImageUploader] --\x3e B\n\tRIG[RouteImageGenerator] --\x3e RID\n\tRIG --\x3e RIU\n\tRIG --\x3e C1\n\tRIG --\x3e P1'}),"\n",(0,i.jsx)(n.h3,{id:"coordinates\uc704\ub3c4-\uacbd\ub3c4\uc758-\uc77c\uae09-\uceec\ub809\uc158",children:"Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"List"})," 2\uac1c(\uc704\ub3c4, \uacbd\ub3c4)\uc778 \ud615\ud0dc\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uc5c8\uc9c0\ub9cc, \uc704\uce58 \uc810\uc744 \uc5ec\ub7ec\uac1c \ucc0d\ub294 \ubd80\ubd84\uc5d0\uc11c \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud574 \uc9c8 \uac83 \uac19\uc544\uc11c Coordinate(x, y)\uc640 \uc77c\uae09 \uceec\ub809\uc158\uc778 Coordinates\ub85c \uad00\ub9ac\ud558\uae30\ub85c \ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Coordinates \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub450 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"calculatePositions: \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub97c \ubc1b\uc544 \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \uc0ac\uc6a9\ub420 Positions\ub97c \ubc18\ud658"}),"\n",(0,i.jsx)(n.li,{children:"indexOf: \ub2e4\ub978 Coordinates\ub97c \ubc1b\uc544 \ub3d9\uc77c\ud55c \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4\ub97c \ubc18\ud658\ud558\ub294"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Positions \uacc4\uc0b0 \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc704\ub3c4, \uacbd\ub3c4 \uac01\uac01\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \ud544\uc694\ud55c \uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="Coordinates.java"',children:"// \ud638\ucd9c\n// List xPositions = toPositions(xValues, maxDifference, routeImageSize);\n// List yPositions = toPositions(yValues, maxDifference, routeImageSize);\n\nprivate List toPositions(List values, Double maxDifference, Integer routeImageSize) {\n Double minValue = Collections.min(values);\n return values.stream()\n .map(value -> normalizeCoordinate(value, maxDifference, minValue))\n .map(value -> mapToPosition(value, routeImageSize))\n .toList();\n}\n\nprivate double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {\n return (coordinate - minValue) / maxDifference;\n}\n\nprivate int mapToPosition(Double coordinate, Integer routeImageSize) {\n return (int) (coordinate * routeImageSize);\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\uc704\ub3c4\ub85c \uc608\uc2dc\ub4e0 \ub0b4\uc6a9\uc774\ub2e4."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Collections.min(values) \u2192 \uc704\ub3c4 \ub9ac\uc2a4\ud2b8\uc758 \ucd5c\uc18c\uac12\uc744 \uad6c\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.li,{children:["normalizeCoordinate \u2192 \uac01\uac01\uc758 \uc704\ub3c4 \uac12\uc5d0\uc11c \ucd5c\uc18c\uac12\uc744 \ube7c\uace0 0 ~ 1 \uc0ac\uc774 \uac12\uc73c\ub85c \ubcc0\ud658 \ud6c4 ",(0,i.jsx)(n.strong,{children:"\uc704\uacbd\ub3c4\uc758 \ucd5c\ub300 \ucc28\uc774"}),"\ub85c \ub098\ub208\ub2e4."]}),"\n",(0,i.jsx)(n.li,{children:"mapToPosition \u2192 \uadf8\ub798\ud504 \ud06c\uae30\ub97c \ubc1b\uc544 0 ~ 1 \uc0ac\uc774 \uac12\uc744 \uc2e4\uc81c \uc774\ubbf8\uc9c0\ub97c \uc704\ud55c \uc704\uce58\uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"positions\uc2e4\uc81c-\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc5d0-\uc0ac\uc6a9\ud560-\uc704\uce58",children:"Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)"}),"\n",(0,i.jsx)(n.p,{children:"Positions \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub2e4\uc12f \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"align: \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\uc640 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\ub97c \ubc1b\uc544 Position \uac12\ub4e4\uc744 \uc911\uc559 \uc815\ub82c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"getPositionsByIndexes: \uc778\ub371\uc2a4 \ub9ac\uc2a4\ud2b8\ub97c \ubc1b\uc544 \uc785\ub825\ubc1b\uc740 \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"size: \ud06c\uae30\ub97c \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"xPositions: x \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"yPositions: y \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uc559 \uc815\ub82c \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="Positions.java"',children:"public Positions align(int imageSize, int routeSize) {\n int xOffset = calculateOffset(Position::x, imageSize);\n int yOffset = calculateOffset(Position::y, imageSize);\n\n return items.stream()\n .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))\n .collect(collectingAndThen(toList(), Positions::new));\n}\n\nprivate int calculateOffset(ToIntFunction positionToInteger, int imageSize) {\n List positions = items.stream()\n .mapToInt(positionToInteger)\n .boxed()\n .toList();\n\n int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;\n return imageSize / 2 - midValue;\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["\uc0c1\ud558\uc88c\uc6b0 \uc5ec\ubc31\uc744 \ub3d9\uc77c\ud558\uac8c \uc8fc\uae30 \uc704\ud574\uc11c offset \uac12\uc744 \uad6c\ud574\uc11c x, y \uac12\uc5d0 \uac01\uac01 \ub354\ud558\ub294 \ud615\ud0dc\ub85c \uc911\uc559 \uc815\ub82c\uc744 \uc218\ud589\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","BufferedImage\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c (0, 0) \uae30\uc900\uc73c\ub85c \uc544\ub798\ub85c \ub0b4\ub824\uac08\uc218\ub85d y \uac12\uc774 \ucee4\uc9c0\uace0, \uc624\ub978\ucabd\uc73c\ub85c \uac08 \uc218\ub85d x \uac12\uc774 \ucee4\uc9c4\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./800.png",src:t(77421).Z+"",width:"968",height:"978"})}),"\n",(0,i.jsx)(n.p,{children:"\ub530\ub77c\uc11c \ucd5c\uc885\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c \uac12\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud588\ub2e4."}),"\n",(0,i.jsxs)(n.p,{children:["x \uac12 \u2192 \uacc4\uc0b0\ud55c offset \uadf8\ub300\ub85c \ub354\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","y \uac12 \u2192 imageSize(800)\uc5d0\uc11c y + offset \uac12\uc744 \ube80\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"routeimagedrawer\uc2e4\uc81c-\uc774\ubbf8\uc9c0\uc5d0-\uacbd\ub85c\ub97c-\uadf8\ub824\uc8fc\ub294-\ud074\ub798\uc2a4",children:"RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)"}),"\n",(0,i.jsxs)(n.p,{children:["BufferedImage, Graphics2D\ub97c \ud544\ub4dc\ub85c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uadf8\ub9bc\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \uc124\uc815\ud55c \uc0c1\uc218\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageDrawer.java"',children:"// RGB\uc5d0 \uac01\uac01 8\ube44\ud2b8\uc529 \ud560\ub2f9\ud55c \uac12\uc744 24\ube44\ud2b8 \ud2b8\ub8e8\uceec\ub7ec\ub77c \ubd80\ub978\ub2e4.\n// \ud574\ub2f9 \uc124\uc815\uc740 24\ube44\ud2b8 + 8\ube44\ud2b8(alpha, \ud22c\uba85\ub3c4)\ub97c \ucd94\uac00\ud55c 32\ube44\ud2b8 \uc774\ubbf8\uc9c0 \ud0c0\uc785\uc774\ub2e4.\n// \uc774\ub97c RGBA\ub77c\uace0 \ubd80\ub978\ub2e4.\nprivate static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;\n// \ubc30\uacbd \ud22c\uba85\uc0c9\nprivate static final Color TRANSPARENT = new Color(0, 0, 0, 0);\n// \uacbd\ub85c\ub97c \uc704\ud55c STROKE\nprivate static final int LINE_STROKE_WIDTH = 7;\nprivate static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\n// \uc704\uce58 \uc810\uc744 \uc704\ud55c STROKE\nprivate static final int POINT_STROKE_WIDTH = 20;\nprivate static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\n// \uc548\ud2f0\uc568\ub9ac\uc5b4\uc2f1 \ub4f1 \ud654\uc9c8 \uac1c\uc120\uc744 \uc704\ud55c \uc124\uc815\nprivate static final Map renderingHints = Map.of(\n RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,\n RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,\n RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC\n);\n"})}),"\n",(0,i.jsx)(n.p,{children:"RouteImageDrawer \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \uc138 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"drawLine: \uc120\uc744 \uadf8\ub9b0\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"drawPoint: \uc810\uc744 \ucc0d\ub294\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"dispose: \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"dispose\uc758 \uacbd\uc6b0 \ub0b4\ubd80\uc5d0\uc11c \uc0dd\uc131\ub41c graphics2D\uc5d0 \ub300\ud55c \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud558\ub294 \uba54\uc11c\ub4dc\uc778 graphics2D.dispose\ub97c \ud638\ucd9c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h2,{id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131-flow",children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow"}),"\n",(0,i.jsx)(n.h3,{id:"1-\uc774\ubbf8\uc9c0-\uc0dd\uc131-\uc900\ube44",children:"1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\n"}),"\n",(0,i.jsx)(n.h3,{id:"2-\uc120-\uadf8\ub9ac\uae30-\uc694\uccad",children:"2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.h3,{id:"3-\uc704\uce58-\uc810-\uadf8\ub9ac\uae30-\uc694\uccad",children:"3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\n\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.h3,{id:"4-\uc5c5\ub85c\ub4dc-\uc694\uccad",children:"4. \uc5c5\ub85c\ub4dc \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \tRouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\n \tRouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n \tRouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658"}),"\n",(0,i.jsx)(n.h3,{id:"\uc804\uccb4-flow",children:"\uc804\uccb4 Flow"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\n\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\n RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\n RouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n RouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n\t"})]})}function u(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var i=t(67294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),d=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=d(t),g=r,h=m["".concat(l,".").concat(g)]||m[g]||c[g]||o;return t?i.createElement(h,a(a({ref:n},u),{},{components:t})):i.createElement(h,a({ref:n},u))}));u.displayName="MDXCreateElement"},49812:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/600-50ee65176288cb73d2c777d255460f4f.png"},77421:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/800-88542ba3914ad40b45b999e95df96cdf.png"},59563:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/result-c2887223d62510a96c9c8f733bf5edf6.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5323],{75824:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>d});var i=t(85893),r=t(3905);const o={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",slug:"route-image-implementation",tags:["image","awt"]},a=void 0,s={permalink:"/route-image-implementation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",source:"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",description:"\uac1c\uc694",date:"2023-08-02T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 2\uc77c",tags:[{label:"image",permalink:"/tags/image"},{label:"awt",permalink:"/tags/awt"}],readingTime:11.665,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",slug:"route-image-implementation",tags:["image","awt"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",permalink:"/route-image-python"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",permalink:"/route-image-async-with-event"}},l={authorsImageUrls:[]},d=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:2},{value:"\uad6c\ud604 \uacb0\uacfc",id:"\uad6c\ud604-\uacb0\uacfc",level:3},{value:"IMAGE_SIZE & ROUTE_SIZE",id:"image_size--route_size",level:3},{value:"\uc8fc\uc694 \ud074\ub798\uc2a4",id:"\uc8fc\uc694-\ud074\ub798\uc2a4",level:2},{value:"\uc694\uc57d",id:"\uc694\uc57d",level:3},{value:"\uc758\uc874\uad00\uacc4",id:"\uc758\uc874\uad00\uacc4",level:3},{value:"Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)",id:"coordinates\uc704\ub3c4-\uacbd\ub3c4\uc758-\uc77c\uae09-\uceec\ub809\uc158",level:3},{value:"Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)",id:"positions\uc2e4\uc81c-\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc5d0-\uc0ac\uc6a9\ud560-\uc704\uce58",level:3},{value:"RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)",id:"routeimagedrawer\uc2e4\uc81c-\uc774\ubbf8\uc9c0\uc5d0-\uacbd\ub85c\ub97c-\uadf8\ub824\uc8fc\ub294-\ud074\ub798\uc2a4",level:3},{value:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow",id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131-flow",level:2},{value:"1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44",id:"1-\uc774\ubbf8\uc9c0-\uc0dd\uc131-\uc900\ube44",level:3},{value:"2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad",id:"2-\uc120-\uadf8\ub9ac\uae30-\uc694\uccad",level:3},{value:"3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad",id:"3-\uc704\uce58-\uc810-\uadf8\ub9ac\uae30-\uc694\uccad",level:3},{value:"4. \uc5c5\ub85c\ub4dc \uc694\uccad",id:"4-\uc5c5\ub85c\ub4dc-\uc694\uccad",level:3},{value:"\uc804\uccb4 Flow",id:"\uc804\uccb4-flow",level:3}];function c(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,i.jsxs)(n.p,{children:["\uc5ec\ud589\uc5d0 \ub300\ud55c \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\uae30 \uc704\ud574 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d \ubc0f \uae30\uc220 \uc120\ud0dd\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 ",(0,i.jsx)(n.a,{href:"./route-image-intro",children:"\ub9c1\ud06c"}),"\uc5d0 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\uad6c\ud604-\uacb0\uacfc",children:"\uad6c\ud604 \uacb0\uacfc"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./result.png",src:t(59563).Z+"",width:"1840",height:"714"})}),"\n",(0,i.jsxs)(n.p,{children:["\uc608\uc2dc \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.strong,{children:"\uc11c\uc6b8\uc5ed(\uc810)"})," \u2192 \uc2e0\uc0ac\uc5ed \u2192 \ub178\ub7c9\uc9c4\uc5ed \u2192 \ud64d\ub300\uc785\uad6c\uc5ed \u2192 \uc885\ub85c3\uac00\uc5ed \u2192 \uc625\uc218\uc5ed \u2192 ",(0,i.jsx)(n.strong,{children:"\uad6c\ub85c\uc5ed(\uc810)"})," \u2192 \uc2e0\ub9bc\uc5ed \u2192 \ubc1c\uc0b0\uc5ed"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="\uc608\uc2dc \ub370\uc774\ud130"',children:"List x = List.of(\n 126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,\n 126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639\n);\nList y = List.of(\n 37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,\n 37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184\n);\nList xPoints = List.of(126.97094933811682, 126.88474839801178);\nList yPoints = List.of(37.55302829553499, 37.50129417536773);\n"})}),"\n",(0,i.jsx)(n.h3,{id:"image_size--route_size",children:"IMAGE_SIZE & ROUTE_SIZE"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageGenerator.java"',children:"private static final int IMAGE_SIZE = 800;\nprivate static final int ROUTE_SIZE = 600;\n"})}),"\n",(0,i.jsxs)(n.p,{children:["\ucf54\ub4dc\ub97c \ubcf4\uba74 IMAGE_SIZE\uc640 ROUTE_SIZE\uac00 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","IMAGE_SIZE\ub294 \ub9d0 \uadf8\ub300\ub85c \uc774\ubbf8\uc9c0\uc758 width\uc640 height\ub97c \uc758\ubbf8\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","ROUTE_SIZE\uc758 \uacbd\uc6b0 \uc0c1\ud558\uc88c\uc6b0 100px \ub9cc\ud07c\uc758 \uac04\uaca9\uc744 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc2e4\uc81c \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub294 600 * 600 \uc0ac\uc774\uc988\ub85c \uc0dd\uc131\ub41c\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./600.png",src:t(49812).Z+"",width:"976",height:"970"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"\uc0ac\uc774\uc988 \ubcc0\uacbd\uc758 \uc774\uc720"})}),"\n",(0,i.jsx)(n.p,{children:"255 * 255 \uc815\ub3c4\uc758 \uc791\uc740 \uc0ac\uc774\uc988\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud574\ubcf4\ub824\uace0 \ud588\ub294\ub370, \uc774\ubbf8\uc9c0\uc758 \uc120\uba85\ub3c4\uac00 \uc88b\uc9c0 \uc54a\uc544 800 * 800 \uc0ac\uc774\uc988\ub85c \ubcc0\uacbd\ud588\ub2e4."}),"\n",(0,i.jsx)(n.h2,{id:"\uc8fc\uc694-\ud074\ub798\uc2a4",children:"\uc8fc\uc694 \ud074\ub798\uc2a4"}),"\n",(0,i.jsx)(n.h3,{id:"\uc694\uc57d",children:"\uc694\uc57d"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"\ud074\ub798\uc2a4\uba85"}),(0,i.jsx)(n.th,{children:"\uc124\uba85"}),(0,i.jsx)(n.th,{children:"\ud2b9\uc774\uc0ac\ud56d"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Coordinate"}),(0,i.jsx)(n.td,{children:"\uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \uc704\uce58 \uac12"}),(0,i.jsx)(n.td,{children:"\uc88c\ud45c\ub97c \ub73b\ud558\uc9c0\ub9cc \uc5ec\ud589 \ub3c4\uba54\uc778\uc5d0 \ud3ec\ud568\ub41c Point \ud074\ub798\uc2a4\uc640 \uad6c\ubd84\ud558\uae30 \uc704\ud574 longitude, latitude\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 x, y \uc0ac\uc6a9"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Coordinates"}),(0,i.jsx)(n.td,{children:"Coordinate\uc758 \uc77c\uae09 \uceec\ub809\uc158"}),(0,i.jsx)(n.td,{children:"-"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Position"}),(0,i.jsx)(n.td,{children:"\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58 \uac12"}),(0,i.jsx)(n.td,{children:"Integer \ud0c0\uc785\uc758 x, y \uc0ac\uc6a9"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Positions"}),(0,i.jsx)(n.td,{children:"Positions\uc758 \uc77c\uae09 \uceec\ub809\uc158"}),(0,i.jsx)(n.td,{children:"-"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageDrawer"}),(0,i.jsx)(n.td,{children:"\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4 BufferedImage, Graphics2D\ub97c \uac00\uc9c0\uace0 \uc788\uc74c"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc0c1\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc74c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageUploader"}),(0,i.jsx)(n.td,{children:"BufferedImage\ub97c \ubc1b\uc544 \uc11c\ubc84\uc5d0 \uc5c5\ub85c\ub4dc \ud558\ub294 \ud074\ub798\uc2a4"}),(0,i.jsx)(n.td,{children:"\ud604\uc7ac \uc5c5\ub85c\ub4dc \uc704\uce58\uac00 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc544 \uc77c\ub2e8 \uae30\ubcf8(\ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8) \uc704\uce58\uc5d0 \uc0dd\uc131"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"RouteImageGenerator"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uace0 \uc5c5\ub85c\ub4dc\ud558\ub294 \uc11c\ube44\uc2a4"}),(0,i.jsx)(n.td,{children:"\uc5ec\ud589 \uc885\ub8cc, \uac10\uc0c1 \uc800\uc7a5\uc2dc \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"BufferedImage(AWT)"}),(0,i.jsx)(n.td,{children:"\uc774\ubbf8\uc9c0 \ub370\uc774\ud130\ub97c \ucc98\ub9ac\ud558\uace0 \uc870\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9"}),(0,i.jsx)(n.td,{children:"\uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c\uac00 (0, 0)"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Graphics2D(AWT)"}),(0,i.jsx)(n.td,{children:"\uc120 \uadf8\ub9ac\uae30, \uc0c9\uc0c1 \uad00\ub9ac \ub4f1\uc744 \uc9c0\uc6d0\ud558\ub294 \ud074\ub798\uc2a4 \uc2e4\uc81c \ud574\ub2f9 \ud074\ub798\uc2a4\uc758 draw \uba54\uc11c\ub4dc\ub97c \uacbd\ub85c\ub97c \uadf8\ub9bc"}),(0,i.jsx)(n.td,{children:"JDK 1.2 \uc774\ud6c4\uc5d0 \ucd94\uac00\ub428, 2D(\ud3c9\uba74) \uadf8\ub798\ud53d \ud658\uacbd\uc744 \uc9c0\uc6d0, bufferedImage.createGraphics \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \uc0dd\uc131"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"\uc758\uc874\uad00\uacc4",children:"\uc758\uc874\uad00\uacc4"}),"\n",(0,i.jsx)(n.mermaid,{value:'graph TD\n C1[Coordinates] --\x3e C[Coordinate]\n P1[Positions] --\x3e P[Position]\n\n\tRID[RouteImageDrawer] -- "\uc911\uc559 \uc815\ub82c\ub41c Positions\ub97c \ubc1b\uc544 \uc774\ubbf8\uc9c0 \uc0dd\uc131" --\x3e P1\n\tRID --\x3e B[BufferedImage]\n\tRID --\x3e G[Graphics2D]\n\n\tC1 -- "calculatePositions \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc704\uce58 \uacc4\uc0b0" --\x3e P1\n\n\tRIU[RouteImageUploader] --\x3e B\n\tRIG[RouteImageGenerator] --\x3e RID\n\tRIG --\x3e RIU\n\tRIG --\x3e C1\n\tRIG --\x3e P1'}),"\n",(0,i.jsx)(n.h3,{id:"coordinates\uc704\ub3c4-\uacbd\ub3c4\uc758-\uc77c\uae09-\uceec\ub809\uc158",children:"Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"List"})," 2\uac1c(\uc704\ub3c4, \uacbd\ub3c4)\uc778 \ud615\ud0dc\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uc5c8\uc9c0\ub9cc, \uc704\uce58 \uc810\uc744 \uc5ec\ub7ec\uac1c \ucc0d\ub294 \ubd80\ubd84\uc5d0\uc11c \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud574 \uc9c8 \uac83 \uac19\uc544\uc11c Coordinate(x, y)\uc640 \uc77c\uae09 \uceec\ub809\uc158\uc778 Coordinates\ub85c \uad00\ub9ac\ud558\uae30\ub85c \ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Coordinates \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub450 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"calculatePositions: \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub97c \ubc1b\uc544 \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \uc0ac\uc6a9\ub420 Positions\ub97c \ubc18\ud658"}),"\n",(0,i.jsx)(n.li,{children:"indexOf: \ub2e4\ub978 Coordinates\ub97c \ubc1b\uc544 \ub3d9\uc77c\ud55c \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4\ub97c \ubc18\ud658\ud558\ub294"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Positions \uacc4\uc0b0 \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc704\ub3c4, \uacbd\ub3c4 \uac01\uac01\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \ud544\uc694\ud55c \uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="Coordinates.java"',children:"// \ud638\ucd9c\n// List xPositions = toPositions(xValues, maxDifference, routeImageSize);\n// List yPositions = toPositions(yValues, maxDifference, routeImageSize);\n\nprivate List toPositions(List values, Double maxDifference, Integer routeImageSize) {\n Double minValue = Collections.min(values);\n return values.stream()\n .map(value -> normalizeCoordinate(value, maxDifference, minValue))\n .map(value -> mapToPosition(value, routeImageSize))\n .toList();\n}\n\nprivate double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {\n return (coordinate - minValue) / maxDifference;\n}\n\nprivate int mapToPosition(Double coordinate, Integer routeImageSize) {\n return (int) (coordinate * routeImageSize);\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\uc704\ub3c4\ub85c \uc608\uc2dc\ub4e0 \ub0b4\uc6a9\uc774\ub2e4."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Collections.min(values) \u2192 \uc704\ub3c4 \ub9ac\uc2a4\ud2b8\uc758 \ucd5c\uc18c\uac12\uc744 \uad6c\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.li,{children:["normalizeCoordinate \u2192 \uac01\uac01\uc758 \uc704\ub3c4 \uac12\uc5d0\uc11c \ucd5c\uc18c\uac12\uc744 \ube7c\uace0 0 ~ 1 \uc0ac\uc774 \uac12\uc73c\ub85c \ubcc0\ud658 \ud6c4 ",(0,i.jsx)(n.strong,{children:"\uc704\uacbd\ub3c4\uc758 \ucd5c\ub300 \ucc28\uc774"}),"\ub85c \ub098\ub208\ub2e4."]}),"\n",(0,i.jsx)(n.li,{children:"mapToPosition \u2192 \uadf8\ub798\ud504 \ud06c\uae30\ub97c \ubc1b\uc544 0 ~ 1 \uc0ac\uc774 \uac12\uc744 \uc2e4\uc81c \uc774\ubbf8\uc9c0\ub97c \uc704\ud55c \uc704\uce58\uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"positions\uc2e4\uc81c-\uc774\ubbf8\uc9c0-\uc0dd\uc131\uc5d0-\uc0ac\uc6a9\ud560-\uc704\uce58",children:"Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)"}),"\n",(0,i.jsx)(n.p,{children:"Positions \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub2e4\uc12f \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"align: \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\uc640 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\ub97c \ubc1b\uc544 Position \uac12\ub4e4\uc744 \uc911\uc559 \uc815\ub82c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"getPositionsByIndexes: \uc778\ub371\uc2a4 \ub9ac\uc2a4\ud2b8\ub97c \ubc1b\uc544 \uc785\ub825\ubc1b\uc740 \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"size: \ud06c\uae30\ub97c \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"xPositions: x \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"yPositions: y \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uc559 \uc815\ub82c \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="Positions.java"',children:"public Positions align(int imageSize, int routeSize) {\n int xOffset = calculateOffset(Position::x, imageSize);\n int yOffset = calculateOffset(Position::y, imageSize);\n\n return items.stream()\n .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))\n .collect(collectingAndThen(toList(), Positions::new));\n}\n\nprivate int calculateOffset(ToIntFunction positionToInteger, int imageSize) {\n List positions = items.stream()\n .mapToInt(positionToInteger)\n .boxed()\n .toList();\n\n int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;\n return imageSize / 2 - midValue;\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["\uc0c1\ud558\uc88c\uc6b0 \uc5ec\ubc31\uc744 \ub3d9\uc77c\ud558\uac8c \uc8fc\uae30 \uc704\ud574\uc11c offset \uac12\uc744 \uad6c\ud574\uc11c x, y \uac12\uc5d0 \uac01\uac01 \ub354\ud558\ub294 \ud615\ud0dc\ub85c \uc911\uc559 \uc815\ub82c\uc744 \uc218\ud589\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","BufferedImage\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c (0, 0) \uae30\uc900\uc73c\ub85c \uc544\ub798\ub85c \ub0b4\ub824\uac08\uc218\ub85d y \uac12\uc774 \ucee4\uc9c0\uace0, \uc624\ub978\ucabd\uc73c\ub85c \uac08 \uc218\ub85d x \uac12\uc774 \ucee4\uc9c4\ub2e4."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"./800.png",src:t(77421).Z+"",width:"968",height:"978"})}),"\n",(0,i.jsx)(n.p,{children:"\ub530\ub77c\uc11c \ucd5c\uc885\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c \uac12\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud588\ub2e4."}),"\n",(0,i.jsxs)(n.p,{children:["x \uac12 \u2192 \uacc4\uc0b0\ud55c offset \uadf8\ub300\ub85c \ub354\ud55c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","y \uac12 \u2192 imageSize(800)\uc5d0\uc11c y + offset \uac12\uc744 \ube80\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"routeimagedrawer\uc2e4\uc81c-\uc774\ubbf8\uc9c0\uc5d0-\uacbd\ub85c\ub97c-\uadf8\ub824\uc8fc\ub294-\ud074\ub798\uc2a4",children:"RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)"}),"\n",(0,i.jsxs)(n.p,{children:["BufferedImage, Graphics2D\ub97c \ud544\ub4dc\ub85c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uadf8\ub9bc\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \uc124\uc815\ud55c \uc0c1\uc218\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageDrawer.java"',children:"// RGB\uc5d0 \uac01\uac01 8\ube44\ud2b8\uc529 \ud560\ub2f9\ud55c \uac12\uc744 24\ube44\ud2b8 \ud2b8\ub8e8\uceec\ub7ec\ub77c \ubd80\ub978\ub2e4.\n// \ud574\ub2f9 \uc124\uc815\uc740 24\ube44\ud2b8 + 8\ube44\ud2b8(alpha, \ud22c\uba85\ub3c4)\ub97c \ucd94\uac00\ud55c 32\ube44\ud2b8 \uc774\ubbf8\uc9c0 \ud0c0\uc785\uc774\ub2e4.\n// \uc774\ub97c RGBA\ub77c\uace0 \ubd80\ub978\ub2e4.\nprivate static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;\n// \ubc30\uacbd \ud22c\uba85\uc0c9\nprivate static final Color TRANSPARENT = new Color(0, 0, 0, 0);\n// \uacbd\ub85c\ub97c \uc704\ud55c STROKE\nprivate static final int LINE_STROKE_WIDTH = 7;\nprivate static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\n// \uc704\uce58 \uc810\uc744 \uc704\ud55c STROKE\nprivate static final int POINT_STROKE_WIDTH = 20;\nprivate static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\n// \uc548\ud2f0\uc568\ub9ac\uc5b4\uc2f1 \ub4f1 \ud654\uc9c8 \uac1c\uc120\uc744 \uc704\ud55c \uc124\uc815\nprivate static final Map renderingHints = Map.of(\n RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,\n RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,\n RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC\n);\n"})}),"\n",(0,i.jsx)(n.p,{children:"RouteImageDrawer \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \uc138 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"drawLine: \uc120\uc744 \uadf8\ub9b0\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"drawPoint: \uc810\uc744 \ucc0d\ub294\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"dispose: \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"dispose\uc758 \uacbd\uc6b0 \ub0b4\ubd80\uc5d0\uc11c \uc0dd\uc131\ub41c graphics2D\uc5d0 \ub300\ud55c \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud558\ub294 \uba54\uc11c\ub4dc\uc778 graphics2D.dispose\ub97c \ud638\ucd9c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h2,{id:"\uc774\ubbf8\uc9c0-\uc0dd\uc131-flow",children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow"}),"\n",(0,i.jsx)(n.h3,{id:"1-\uc774\ubbf8\uc9c0-\uc0dd\uc131-\uc900\ube44",children:"1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\n"}),"\n",(0,i.jsx)(n.h3,{id:"2-\uc120-\uadf8\ub9ac\uae30-\uc694\uccad",children:"2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.h3,{id:"3-\uc704\uce58-\uc810-\uadf8\ub9ac\uae30-\uc694\uccad",children:"3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\n\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad"}),"\n",(0,i.jsx)(n.h3,{id:"4-\uc5c5\ub85c\ub4dc-\uc694\uccad",children:"4. \uc5c5\ub85c\ub4dc \uc694\uccad"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \tRouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\n \tRouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n \tRouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658"}),"\n",(0,i.jsx)(n.h3,{id:"\uc804\uccb4-flow",children:"\uc804\uccb4 Flow"}),"\n",(0,i.jsx)(n.mermaid,{value:"sequenceDiagram\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\n\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\n RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\n RouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n RouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\n\t"})]})}function u(e={}){const{wrapper:n}={...(0,r.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var i=t(67294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),d=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=d(t),g=r,h=m["".concat(l,".").concat(g)]||m[g]||c[g]||o;return t?i.createElement(h,a(a({ref:n},u),{},{components:t})):i.createElement(h,a({ref:n},u))}));u.displayName="MDXCreateElement"},49812:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/600-50ee65176288cb73d2c777d255460f4f.png"},77421:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/800-88542ba3914ad40b45b999e95df96cdf.png"},59563:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/result-c2887223d62510a96c9c8f733bf5edf6.png"}}]); \ No newline at end of file diff --git a/assets/js/cd68cda1.c2b122c5.js b/assets/js/cd68cda1.fb88bddb.js similarity index 97% rename from assets/js/cd68cda1.c2b122c5.js rename to assets/js/cd68cda1.fb88bddb.js index ab5040b39..a9cf8938f 100644 --- a/assets/js/cd68cda1.c2b122c5.js +++ b/assets/js/cd68cda1.fb88bddb.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8683],{2915:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var t=r(85893),c=r(3905);const a={title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},o=void 0,i={permalink:"/log-async-exception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",description:"\ubb38\uc81c \uc0c1\ud669",date:"2023-09-18T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 18\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"exception",permalink:"/tags/exception"}],readingTime:3.615,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",permalink:"/web-application-evolution"},nextItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"}},s={authorsImageUrls:[]},l=[{value:"\ubb38\uc81c \uc0c1\ud669",id:"\ubb38\uc81c-\uc0c1\ud669",level:3},{value:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",level:3},{value:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c",id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={a:"a",br:"br",code:"code",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ubb38\uc81c-\uc0c1\ud669",children:"\ubb38\uc81c \uc0c1\ud669"}),"\n",(0,t.jsxs)(n.p,{children:["\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 ",(0,t.jsx)(n.code,{children:"@Async"}),"\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 ",(0,t.jsx)(n.code,{children:"@ControllerAdvice"})," + ",(0,t.jsx)(n.code,{children:"@ExceptionHandler"}),"\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",children:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1 4.1 \ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html",children:"AsyncUncaughtExceptionHandler"}),"\uc758 \uacbd\uc6b0 \ubc18\ud658 \ud0c0\uc785\uc774 void\uc778 \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\ub97c \uc608\uc678 \ucc98\ub9ac\ud558\uae30 \uc27d\ub3c4\ub85d \ub3c4\uc640\uc900\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ub530\ub77c\uc11c AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ud578\ub4e4\ub9c1\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 \ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\ub3c4 \ub9c8\ucc2c\uac00\uc9c0\ub85c MDC\uc758 \uc815\ubcf4\ub97c \uac00\uc838\uc640\uc11c \ub85c\uadf8\ub97c \ucd9c\ub825\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncExceptionHandler",children:'@Slf4j\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\n\n private static final String LOG_FORMAT = "[%s] %s";\n\n @Override\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["AsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","getAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncConfig",children:"@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc774\uc81c \ube44\ub3d9\uae30 \uc0c1\ud669\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544 \ucc98\ub9ac\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",children:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c"}),"\n",(0,t.jsx)(n.p,{children:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"./mdc-null.png",src:r(81450).Z+"",width:"2236",height:"426"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html",children:"TaskDecorator"}),"\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=MdcTaskDecorator",children:"public class MdcTaskDecorator implements TaskDecorator {\n\n @Override\n public Runnable decorate(final Runnable runnable) {\n Map threadContext = MDC.getCopyOfContextMap();\n return () -> {\n MDC.setContextMap(threadContext);\n runnable.run();\n };\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc0dd\uc131\ud55c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncConfig",children:"@RequiredArgsConstructor\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n private final AsyncConfigurationProperties properties;\n\n @Bean\n public ThreadPoolTaskExecutor taskExecutor() {\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n executor.setCorePoolSize(properties.coreSize());\n executor.setMaxPoolSize(properties.maxSize());\n executor.setQueueCapacity(properties.queueCapacity());\n \n // highlight-next-line\n executor.setTaskDecorator(new MdcTaskDecorator());\n executor.setWaitForTasksToCompleteOnShutdown(true);\n executor.initialize();\n return executor;\n }\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"./mdc-not-null.png",src:r(97754).Z+"",width:"2620",height:"440"})}),"\n",(0,t.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://www.baeldung.com/spring-async",children:"spring async, baeldung"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception",children:"@Async will not call by @ControllerAdvice for global exception"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://blog.gangnamunni.com/post/mdc-context-task-decorator/",children:"Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html",children:"TaskDecorator, Spring docs"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html",children:"AsyncUncaughtExceptionHandler"})]})]})}function d(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>l});var t=r(67294);function c(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(c[r]=e[r]);return c}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var s=t.createContext({}),l=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,c=e.mdxType,a=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),u=l(r),g=c,h=u["".concat(s,".").concat(g)]||u[g]||p[g]||a;return r?t.createElement(h,o(o({ref:n},d),{},{components:r})):t.createElement(h,o({ref:n},d))}));d.displayName="MDXCreateElement"},97754:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/mdc-not-null-2b12c13f4f420a335c9e55dbea503f1b.png"},81450:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/mdc-null-95b3bbdce99ef36ba843986413e0421a.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8683],{2915:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var t=r(85893),c=r(3905);const a={title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},o=void 0,i={permalink:"/log-async-exception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",description:"\ubb38\uc81c \uc0c1\ud669",date:"2023-09-18T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 18\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"exception",permalink:"/tags/exception"}],readingTime:3.615,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},unlisted:!1,prevItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"},nextItem:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",permalink:"/web-application-evolution"}},s={authorsImageUrls:[]},l=[{value:"\ubb38\uc81c \uc0c1\ud669",id:"\ubb38\uc81c-\uc0c1\ud669",level:3},{value:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",level:3},{value:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c",id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={a:"a",br:"br",code:"code",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ubb38\uc81c-\uc0c1\ud669",children:"\ubb38\uc81c \uc0c1\ud669"}),"\n",(0,t.jsxs)(n.p,{children:["\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 ",(0,t.jsx)(n.code,{children:"@Async"}),"\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 ",(0,t.jsx)(n.code,{children:"@ControllerAdvice"})," + ",(0,t.jsx)(n.code,{children:"@ExceptionHandler"}),"\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",children:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1 4.1 \ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html",children:"AsyncUncaughtExceptionHandler"}),"\uc758 \uacbd\uc6b0 \ubc18\ud658 \ud0c0\uc785\uc774 void\uc778 \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\ub97c \uc608\uc678 \ucc98\ub9ac\ud558\uae30 \uc27d\ub3c4\ub85d \ub3c4\uc640\uc900\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ub530\ub77c\uc11c AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ud578\ub4e4\ub9c1\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 \ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\ub3c4 \ub9c8\ucc2c\uac00\uc9c0\ub85c MDC\uc758 \uc815\ubcf4\ub97c \uac00\uc838\uc640\uc11c \ub85c\uadf8\ub97c \ucd9c\ub825\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncExceptionHandler",children:'@Slf4j\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\n\n private static final String LOG_FORMAT = "[%s] %s";\n\n @Override\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["AsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","getAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncConfig",children:"@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc774\uc81c \ube44\ub3d9\uae30 \uc0c1\ud669\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544 \ucc98\ub9ac\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",children:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c"}),"\n",(0,t.jsx)(n.p,{children:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"./mdc-null.png",src:r(81450).Z+"",width:"2236",height:"426"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html",children:"TaskDecorator"}),"\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=MdcTaskDecorator",children:"public class MdcTaskDecorator implements TaskDecorator {\n\n @Override\n public Runnable decorate(final Runnable runnable) {\n Map threadContext = MDC.getCopyOfContextMap();\n return () -> {\n MDC.setContextMap(threadContext);\n runnable.run();\n };\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc0dd\uc131\ud55c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncConfig",children:"@RequiredArgsConstructor\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n private final AsyncConfigurationProperties properties;\n\n @Bean\n public ThreadPoolTaskExecutor taskExecutor() {\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n executor.setCorePoolSize(properties.coreSize());\n executor.setMaxPoolSize(properties.maxSize());\n executor.setQueueCapacity(properties.queueCapacity());\n \n // highlight-next-line\n executor.setTaskDecorator(new MdcTaskDecorator());\n executor.setWaitForTasksToCompleteOnShutdown(true);\n executor.initialize();\n return executor;\n }\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"./mdc-not-null.png",src:r(97754).Z+"",width:"2620",height:"440"})}),"\n",(0,t.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://www.baeldung.com/spring-async",children:"spring async, baeldung"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception",children:"@Async will not call by @ControllerAdvice for global exception"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://blog.gangnamunni.com/post/mdc-context-task-decorator/",children:"Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html",children:"TaskDecorator, Spring docs"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html",children:"AsyncUncaughtExceptionHandler"})]})]})}function d(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>l});var t=r(67294);function c(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(c[r]=e[r]);return c}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var s=t.createContext({}),l=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,c=e.mdxType,a=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),u=l(r),g=c,h=u["".concat(s,".").concat(g)]||u[g]||p[g]||a;return r?t.createElement(h,o(o({ref:n},d),{},{components:r})):t.createElement(h,o({ref:n},d))}));d.displayName="MDXCreateElement"},97754:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/mdc-not-null-2b12c13f4f420a335c9e55dbea503f1b.png"},81450:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/mdc-null-95b3bbdce99ef36ba843986413e0421a.png"}}]); \ No newline at end of file diff --git a/assets/js/cef46b76.69423224.js b/assets/js/cef46b76.6d320653.js similarity index 98% rename from assets/js/cef46b76.69423224.js rename to assets/js/cef46b76.6d320653.js index 044b5fbe4..69de37a0b 100644 --- a/assets/js/cef46b76.69423224.js +++ b/assets/js/cef46b76.6d320653.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8644],{91704:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var a=t(85893),i=t(3905);const r={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",slug:"route-image-python",tags:["Image","Python"]},l=void 0,s={permalink:"/route-image-python",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",source:"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",description:"\uac1c\uc694",date:"2023-07-31T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 31\uc77c",tags:[{label:"Image",permalink:"/tags/image"},{label:"Python",permalink:"/tags/python"}],readingTime:6.185,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",slug:"route-image-python",tags:["Image","Python"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",permalink:"/route-image-implementation"},nextItem:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",permalink:"/mock-static-method"}},o={authorsImageUrls:[]},d=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\uc0ac\uc6a9 \uae30\uc220",id:"\uc0ac\uc6a9-\uae30\uc220",level:3},{value:"\uc694\uad6c\uc0ac\ud56d",id:"\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd",id:"\uc774\ubbf8\uc9c0-\ucd9c\ub825-\ubc29\uc2dd",level:3},{value:"\ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604",id:"\ub85c\uceec\uc5d0\uc11c-\uae30\ub2a5-\uad6c\ud604",level:3},{value:"AWS Lambda",id:"aws-lambda",level:3},{value:"\ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131",id:"\ub78c\ub2e4-s3-\uc811\uadfc\uc744-\uc704\ud55c-iam-\uc0dd\uc131",level:3},{value:"\ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc",id:"\ub78c\ub2e4-\ubc30\ud3ec\uc6a9-\ucf54\ub4dc",level:3},{value:"Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131",id:"layer-\ucd94\uac00\ub97c-\uc704\ud55c-zip-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"No module named 'numpy.core._multiarray_umath' \uc5d0\ub7ec",id:"no-module-named-numpycore_multiarray_umath-\uc5d0\ub7ec",level:3},{value:"\uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01",id:"\uc801\uc815\uae30\uc220\uc5d0-\ub300\ud55c-\uc0dd\uac01",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,a.jsx)(n.p,{children:"\uc774\uc804\uc5d0 \uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\uc0ac\ud558\uba74\uc11c \ud30c\uc774\uc36c\uc744 \uc0ac\uc6a9\ud55c \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud55c \ub0b4\uc6a9\uc774\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\uc0ac\uc6a9-\uae30\uc220",children:"\uc0ac\uc6a9 \uae30\uc220"}),"\n",(0,a.jsxs)(n.p,{children:["\uc5b8\uc5b4: Python 3.10",(0,a.jsx)(n.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131: matplotlib",(0,a.jsx)(n.br,{}),"\n","\uc11c\ube44\uc2a4: AWS Lambda, AWS API Gateway",(0,a.jsx)(n.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc800\uc7a5 \ubc0f URL: AWS S3, AWS CloudFront"]}),"\n",(0,a.jsx)(n.p,{children:"\ud50c\ub85c\uc6b0\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n Server -- \uc0dd\uc131 \uc694\uccad --\x3e AG[API Gateway] --\x3e Lambda --\x3e S3\n Client --\x3e CloudFront --\x3e S3"}),"\n",(0,a.jsx)(n.h3,{id:"\uc694\uad6c\uc0ac\ud56d",children:"\uc694\uad6c\uc0ac\ud56d"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"./route.png",src:t(13533).Z+"",width:"1014",height:"902"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc6b0\uce21 \uc0c1\ub2e8\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub824\uace0 \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"\uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \ubc30\uc5f4\uc744 \uc785\ub825\ubc1b\ub294\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131"}),"\n",(0,a.jsx)(n.li,{children:"\uc120\uacfc \uc810 \ud45c\ud604"}),"\n",(0,a.jsx)(n.li,{children:"\ud22c\uba85\ud55c \ubc30\uacbd\uc0c9"}),"\n",(0,a.jsx)(n.li,{children:"\uc704\uacbd\ub3c4 \ucc28\uc774\uac00 \ud06c\ub4e0 \uc791\ub4e0 \uc81c\uacf5\ud558\ub294 \uc774\ubbf8\uc9c0 \ub0b4\uc5d0 \uacbd\ub85c\uac00 \ub2e4 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"\uc774\ubbf8\uc9c0-\ucd9c\ub825-\ubc29\uc2dd",children:"\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"\uc704\uacbd\ub3c4\ub97c \ucc98\ub9ac\ud55c \uac12\uc73c\ub85c \uc9c1\uc811 \uacbd\ub85c\ub97c \uadf8\ub9b0 \ub2e4\uc74c \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5"}),"\n",(0,a.jsx)(n.li,{children:"\ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc0ac\uc6a9\ud558\uc5ec \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5"}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\uc758 \uacbd\uc6b0 1\ubc88\uacfc 2\ubc88\uc744 \uace0\ubbfc\ud588\uc5c8\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud30c\uc774\uc36c\uc73c\ub85c\ub294 \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc778 matplotlib\uc744 \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ub85c\uceec\uc5d0\uc11c-\uae30\ub2a5-\uad6c\ud604",children:"\ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"import time\n\nimport matplotlib.pyplot as plt\n\n\ndef draw(point):\n start = time.time()\n x, y = zip(*point)\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\n draw_lines(pixel_x, pixel_y)\n end = time.time()\n print(end - start)\n \ndef convert_to_pixel_values(x, y):\n max_diff = max(max(x) - min(x), max(y) - min(y))\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\n\n\ndef scale_to_pixel_values(points, max_diff):\n min_value = min(points)\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\n return scaled_coordinates\n\n\ndef draw_lines(x, y):\n figure = plt.gcf()\n figure.set_size_inches(5, 5)\n plt.plot(x, y, c = 'w',linewidth=5)\n plt.scatter(x[3],y[3], c = 'w', s = 125)\n plt.axis('off')\n plt.savefig('name.png', transparent=True, format='png')\n\npoint = [\n [126.96352960597338, 37.590841000217125],\n [126.96987292787792, 37.58435564234159],\n [126.98128481452298, 37.58594375113966],\n [126.99360339342958, 37.58248524741927],\n [126.99867565340067, 37.56778118088622],\n [127.001935378366117, 37.55985240444085],\n [126.9831048919687, 37.548030119488665],\n [126.97189273528845, 37.5119879225856],\n [127.02689859997221, 37.48488593333883]\n]\n\ndraw(point)\n"})}),"\n",(0,a.jsx)(n.p,{children:"\uc0dd\uc131 \uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4. (\uc608\uc2dc\ub97c \uc704\ud574 \uac80\uc740\uc0c9\uc73c\ub85c \ucd9c\ub825)"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"./routeImage.png",src:t(46365).Z+"",width:"500",height:"500"})}),"\n",(0,a.jsx)(n.h3,{id:"aws-lambda",children:"AWS Lambda"}),"\n",(0,a.jsxs)(n.p,{children:["\uc378\ub124\uc77c \uc0dd\uc131 \uc11c\ubc84\ub97c \ub530\ub85c \ub450\uae30\ub294 \uae30\ub2a5 \ub300\ube44 \ube44\uc6a9\uc774 \ub108\ubb34 \ud074 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc11c\ubc84\ub9ac\uc2a4\ub85c \ud30c\uc77c\uc744 \ucc98\ub9ac\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c s3 \uc811\uadfc\uc740 boto3\ub97c \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ub78c\ub2e4-s3-\uc811\uadfc\uc744-\uc704\ud55c-iam-\uc0dd\uc131",children:"\ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131"}),"\n",(0,a.jsx)(n.p,{children:"AmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy \ub450\uac00\uc9c0\ub97c \ucd94\uac00\ud574\uc11c Lambda \uc804\uc6a9 \uc5ed\ud560\uc744 \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud588\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\ub78c\ub2e4-\ubc30\ud3ec\uc6a9-\ucf54\ub4dc",children:"\ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc"}),"\n",(0,a.jsx)(n.p,{children:"\uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \ud655\uc778\ud560 \ub550 \uc704\uce58 \uc810\uc744 \ucc0d\ub294 \uae30\ub2a5\uc744 \ub78c\ub2e4\uc5d0 \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"\nimport io\nimport uuid\n\nimport boto3\nimport matplotlib.pyplot as plt\n\nPIXEL = 255\nBUCKET_NAME = 'image-plot'\nS3 = 's3'\n\ndef lambda_handler(event, context):\n x = event['x']\n y = event['y']\n image_name = str(uuid.uuid4())\n\n img_data = draw(x, y)\n s3 = boto3.client(S3)\n s3.put_object(Body=img_data.getvalue(), ContentType='image/png', Bucket=BUCKET_NAME, Key=image_name)\n url = f'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}'\n\n return {\n 'statusCode': 200,\n 'body': url\n }\n\ndef draw(x, y):\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\n img_data = draw_lines(pixel_x, pixel_y)\n plt.close()\n return img_data\n\ndef convert_to_pixel_values(x, y):\n max_diff = max(max(x) - min(x), max(y) - min(y))\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\n\ndef scale_to_pixel_values(points, max_diff):\n min_value = min(points)\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\n pixel_values = [int(p * PIXEL) for p in scaled_coordinates]\n return pixel_values\n\ndef draw_lines(x, y):\n plt.plot(x, y, 'k-', linewidth=10)\n plt.axis('off')\n img_data = io.BytesIO()\n plt.savefig(img_data, transparent=True, format='png')\n img_data.seek(0)\n return img_data\n\n"})}),"\n",(0,a.jsx)(n.h3,{id:"layer-\ucd94\uac00\ub97c-\uc704\ud55c-zip-\ud30c\uc77c-\uc0dd\uc131",children:"Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,a.jsxs)(n.p,{children:["matplotlib\uc758 \uacbd\uc6b0 \uc678\ubd80 \ub77c\uc774\ube0c\ub7ec\ub9ac\uae30 \ub54c\ubb38\uc5d0 \ub530\ub85c Layer\ub97c \ucd94\uac00\ud574\uc57c \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \uc5c5\ub85c\ub4dc\ud574\uc57c\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub54c python\uc758 Lambda \ub7f0\ud0c0\uc784\uc5d0 \ub300\ud55c \uacc4\uce35 \uacbd\ub85c\ub294 python\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc555\ucd95\ud55c zip \ud30c\uc77c\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \ub744\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"pillow.zip\n\u2502 python/PIL\n\u2514 python/Pillow-5.3.0.dist-info\n"})}),"\n",(0,a.jsx)(n.p,{children:"Ubuntu \uae30\uc900 \ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc0dd\uc131\uc744 \uc9c4\ud589\ud588\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"sudo apt update\nsudo apt install zip\nsudo apt install python3-pip\n\nmkdir python\npip3 install matplotlib -t python # pip3 install \uc124\uce58\ud560_\ud328\ud0a4\uc9c0 -t \uc124\uce58_\uacbd\ub85c\nzip -r my_layer.zip python # zip -r \uc555\ucd95_\ud30c\uc77c\uba85 \uc555\ucd95_\ud30c\uc77c\uc774_\uc874\uc7ac\ud558\ub294_\uacbd\ub85c\n"})}),"\n",(0,a.jsxs)(n.h3,{id:"no-module-named-numpycore_multiarray_umath-\uc5d0\ub7ec",children:[(0,a.jsx)(n.code,{children:"No module named 'numpy.core._multiarray_umath'"})," \uc5d0\ub7ec"]}),"\n",(0,a.jsxs)(n.p,{children:["Layer \ucd94\uac00 \ud6c4 \ub78c\ub2e4 \uc2e4\ud589 \uc2dc \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\uc600\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucc98\uc74c\uc5d0 mac\uc5d0\uc11c zip \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc5c5\ub85c\ub4dc\ud588\ub294\ub370 \ud574\ub2f9 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub294 lambda\uac00 \ub3cc\uc544\uac00\ub294 \ub3d9\uc77c\ud55c \ud658\uacbd\uc5d0\uc11c layer\ub97c \uc704\ud55c zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc9c0 \uc54a\uc544\uc11c \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud558\uac8c ec2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c \ub530\ub85c Layer\ub97c \uc0dd\uc131\ud558\uba74 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\uc801\uc815\uae30\uc220\uc5d0-\ub300\ud55c-\uc0dd\uac01",children:"\uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01"}),"\n",(0,a.jsxs)(n.p,{children:["\ud504\ub85c\uc81d\ud2b8\uc5d0 Lambda\uc640 Python\uc744 \uc0ac\uc6a9\ud558\ub824\uace0 \ud588\uc9c0\ub9cc \uc544\uc27d\uac8c\ub3c4 \ubc18\ub824\ub2f9\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","AWS Lambda\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc778\uc2a4\ud134\uc2a4\uc5d0 \ud574\ub2f9 \ucf54\ub4dc\ub97c \ubc30\ud3ec\ud558\ub294 \uac83\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc77c \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uac00\uc6a9 \uac00\ub2a5\ud55c \uc790\uc6d0, \uae30\uc220\uc758 \ub09c\uc774\ub3c4, \uc0ac\uc6a9\ud558\ub294 \ud300\uc6d0\uc744 \uace0\ub824\ud55c\ub2e4\uba74 Lambda\ub294 \uc801\uc815\uae30\uc220\uc774 \uc544\ub2d0 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud574\ub2f9 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\ub97c \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud560\uc9c0 \uc870\uae08 \ub354 \uace0\ub824\ub97c \ud574\uc57c \ub420 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\ucd5c\uc885\uc801\uc73c\ub85c Java AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4."})}),"\n",(0,a.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://aws.amazon.com/ko/lambda/",children:"AWS Lambda"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html",children:"Lambda Layer"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html",children:"Python Lambda \ud568\uc218\uc5d0 \ub300\ud55c .zip \ud30c\uc77c \uc544\uce74\uc774\ube0c \uc791\uc5c5"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://gist.github.com/ksmin23/0f3f243408a8497f766b43cf589fea7b",children:"No module named 'numpy.core._multiarray_umath'"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://techblog.woowahan.com/6217/",children:"\uc0ac\ub840\ubcc4\ub85c \uc54c\uc544\ubcf8 \uc548\uc804\ud55c S3 \uc0ac\uc6a9 \uac00\uc774\ub4dc"})]})]})}function c(e={}){const{wrapper:n}={...(0,i.ah)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var a=t(67294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var o=a.createContext({}),d=function(e){var n=a.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},p={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,o=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=d(t),x=i,u=m["".concat(o,".").concat(x)]||m[x]||p[x]||r;return t?a.createElement(u,l(l({ref:n},c),{},{components:t})):a.createElement(u,l({ref:n},c))}));c.displayName="MDXCreateElement"},13533:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/route-89cacb9b7815a3191ab1f9d9e23c43a1.png"},46365:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/routeImage-0eac25ba9b356cd034ade6e062c1ce19.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8644],{91704:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var a=t(85893),i=t(3905);const r={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",slug:"route-image-python",tags:["Image","Python"]},l=void 0,s={permalink:"/route-image-python",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",source:"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",description:"\uac1c\uc694",date:"2023-07-31T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 31\uc77c",tags:[{label:"Image",permalink:"/tags/image"},{label:"Python",permalink:"/tags/python"}],readingTime:6.185,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c",slug:"route-image-python",tags:["Image","Python"]},unlisted:!1,prevItem:{title:"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30",permalink:"/mock-static-method"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",permalink:"/route-image-implementation"}},o={authorsImageUrls:[]},d=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\uc0ac\uc6a9 \uae30\uc220",id:"\uc0ac\uc6a9-\uae30\uc220",level:3},{value:"\uc694\uad6c\uc0ac\ud56d",id:"\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd",id:"\uc774\ubbf8\uc9c0-\ucd9c\ub825-\ubc29\uc2dd",level:3},{value:"\ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604",id:"\ub85c\uceec\uc5d0\uc11c-\uae30\ub2a5-\uad6c\ud604",level:3},{value:"AWS Lambda",id:"aws-lambda",level:3},{value:"\ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131",id:"\ub78c\ub2e4-s3-\uc811\uadfc\uc744-\uc704\ud55c-iam-\uc0dd\uc131",level:3},{value:"\ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc",id:"\ub78c\ub2e4-\ubc30\ud3ec\uc6a9-\ucf54\ub4dc",level:3},{value:"Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131",id:"layer-\ucd94\uac00\ub97c-\uc704\ud55c-zip-\ud30c\uc77c-\uc0dd\uc131",level:3},{value:"No module named 'numpy.core._multiarray_umath' \uc5d0\ub7ec",id:"no-module-named-numpycore_multiarray_umath-\uc5d0\ub7ec",level:3},{value:"\uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01",id:"\uc801\uc815\uae30\uc220\uc5d0-\ub300\ud55c-\uc0dd\uac01",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h3,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,a.jsx)(n.p,{children:"\uc774\uc804\uc5d0 \uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\uc0ac\ud558\uba74\uc11c \ud30c\uc774\uc36c\uc744 \uc0ac\uc6a9\ud55c \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud55c \ub0b4\uc6a9\uc774\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\uc0ac\uc6a9-\uae30\uc220",children:"\uc0ac\uc6a9 \uae30\uc220"}),"\n",(0,a.jsxs)(n.p,{children:["\uc5b8\uc5b4: Python 3.10",(0,a.jsx)(n.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc0dd\uc131: matplotlib",(0,a.jsx)(n.br,{}),"\n","\uc11c\ube44\uc2a4: AWS Lambda, AWS API Gateway",(0,a.jsx)(n.br,{}),"\n","\uc774\ubbf8\uc9c0 \uc800\uc7a5 \ubc0f URL: AWS S3, AWS CloudFront"]}),"\n",(0,a.jsx)(n.p,{children:"\ud50c\ub85c\uc6b0\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n Server -- \uc0dd\uc131 \uc694\uccad --\x3e AG[API Gateway] --\x3e Lambda --\x3e S3\n Client --\x3e CloudFront --\x3e S3"}),"\n",(0,a.jsx)(n.h3,{id:"\uc694\uad6c\uc0ac\ud56d",children:"\uc694\uad6c\uc0ac\ud56d"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"./route.png",src:t(13533).Z+"",width:"1014",height:"902"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc6b0\uce21 \uc0c1\ub2e8\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub824\uace0 \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"\uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \ubc30\uc5f4\uc744 \uc785\ub825\ubc1b\ub294\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131"}),"\n",(0,a.jsx)(n.li,{children:"\uc120\uacfc \uc810 \ud45c\ud604"}),"\n",(0,a.jsx)(n.li,{children:"\ud22c\uba85\ud55c \ubc30\uacbd\uc0c9"}),"\n",(0,a.jsx)(n.li,{children:"\uc704\uacbd\ub3c4 \ucc28\uc774\uac00 \ud06c\ub4e0 \uc791\ub4e0 \uc81c\uacf5\ud558\ub294 \uc774\ubbf8\uc9c0 \ub0b4\uc5d0 \uacbd\ub85c\uac00 \ub2e4 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"\uc774\ubbf8\uc9c0-\ucd9c\ub825-\ubc29\uc2dd",children:"\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"\uc704\uacbd\ub3c4\ub97c \ucc98\ub9ac\ud55c \uac12\uc73c\ub85c \uc9c1\uc811 \uacbd\ub85c\ub97c \uadf8\ub9b0 \ub2e4\uc74c \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5"}),"\n",(0,a.jsx)(n.li,{children:"\ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc0ac\uc6a9\ud558\uc5ec \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5"}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\uc758 \uacbd\uc6b0 1\ubc88\uacfc 2\ubc88\uc744 \uace0\ubbfc\ud588\uc5c8\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud30c\uc774\uc36c\uc73c\ub85c\ub294 \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc778 matplotlib\uc744 \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ub85c\uceec\uc5d0\uc11c-\uae30\ub2a5-\uad6c\ud604",children:"\ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"import time\n\nimport matplotlib.pyplot as plt\n\n\ndef draw(point):\n start = time.time()\n x, y = zip(*point)\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\n draw_lines(pixel_x, pixel_y)\n end = time.time()\n print(end - start)\n \ndef convert_to_pixel_values(x, y):\n max_diff = max(max(x) - min(x), max(y) - min(y))\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\n\n\ndef scale_to_pixel_values(points, max_diff):\n min_value = min(points)\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\n return scaled_coordinates\n\n\ndef draw_lines(x, y):\n figure = plt.gcf()\n figure.set_size_inches(5, 5)\n plt.plot(x, y, c = 'w',linewidth=5)\n plt.scatter(x[3],y[3], c = 'w', s = 125)\n plt.axis('off')\n plt.savefig('name.png', transparent=True, format='png')\n\npoint = [\n [126.96352960597338, 37.590841000217125],\n [126.96987292787792, 37.58435564234159],\n [126.98128481452298, 37.58594375113966],\n [126.99360339342958, 37.58248524741927],\n [126.99867565340067, 37.56778118088622],\n [127.001935378366117, 37.55985240444085],\n [126.9831048919687, 37.548030119488665],\n [126.97189273528845, 37.5119879225856],\n [127.02689859997221, 37.48488593333883]\n]\n\ndraw(point)\n"})}),"\n",(0,a.jsx)(n.p,{children:"\uc0dd\uc131 \uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4. (\uc608\uc2dc\ub97c \uc704\ud574 \uac80\uc740\uc0c9\uc73c\ub85c \ucd9c\ub825)"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"./routeImage.png",src:t(46365).Z+"",width:"500",height:"500"})}),"\n",(0,a.jsx)(n.h3,{id:"aws-lambda",children:"AWS Lambda"}),"\n",(0,a.jsxs)(n.p,{children:["\uc378\ub124\uc77c \uc0dd\uc131 \uc11c\ubc84\ub97c \ub530\ub85c \ub450\uae30\ub294 \uae30\ub2a5 \ub300\ube44 \ube44\uc6a9\uc774 \ub108\ubb34 \ud074 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc11c\ubc84\ub9ac\uc2a4\ub85c \ud30c\uc77c\uc744 \ucc98\ub9ac\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c s3 \uc811\uadfc\uc740 boto3\ub97c \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ub78c\ub2e4-s3-\uc811\uadfc\uc744-\uc704\ud55c-iam-\uc0dd\uc131",children:"\ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131"}),"\n",(0,a.jsx)(n.p,{children:"AmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy \ub450\uac00\uc9c0\ub97c \ucd94\uac00\ud574\uc11c Lambda \uc804\uc6a9 \uc5ed\ud560\uc744 \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud588\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\ub78c\ub2e4-\ubc30\ud3ec\uc6a9-\ucf54\ub4dc",children:"\ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc"}),"\n",(0,a.jsx)(n.p,{children:"\uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \ud655\uc778\ud560 \ub550 \uc704\uce58 \uc810\uc744 \ucc0d\ub294 \uae30\ub2a5\uc744 \ub78c\ub2e4\uc5d0 \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"\nimport io\nimport uuid\n\nimport boto3\nimport matplotlib.pyplot as plt\n\nPIXEL = 255\nBUCKET_NAME = 'image-plot'\nS3 = 's3'\n\ndef lambda_handler(event, context):\n x = event['x']\n y = event['y']\n image_name = str(uuid.uuid4())\n\n img_data = draw(x, y)\n s3 = boto3.client(S3)\n s3.put_object(Body=img_data.getvalue(), ContentType='image/png', Bucket=BUCKET_NAME, Key=image_name)\n url = f'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}'\n\n return {\n 'statusCode': 200,\n 'body': url\n }\n\ndef draw(x, y):\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\n img_data = draw_lines(pixel_x, pixel_y)\n plt.close()\n return img_data\n\ndef convert_to_pixel_values(x, y):\n max_diff = max(max(x) - min(x), max(y) - min(y))\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\n\ndef scale_to_pixel_values(points, max_diff):\n min_value = min(points)\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\n pixel_values = [int(p * PIXEL) for p in scaled_coordinates]\n return pixel_values\n\ndef draw_lines(x, y):\n plt.plot(x, y, 'k-', linewidth=10)\n plt.axis('off')\n img_data = io.BytesIO()\n plt.savefig(img_data, transparent=True, format='png')\n img_data.seek(0)\n return img_data\n\n"})}),"\n",(0,a.jsx)(n.h3,{id:"layer-\ucd94\uac00\ub97c-\uc704\ud55c-zip-\ud30c\uc77c-\uc0dd\uc131",children:"Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,a.jsxs)(n.p,{children:["matplotlib\uc758 \uacbd\uc6b0 \uc678\ubd80 \ub77c\uc774\ube0c\ub7ec\ub9ac\uae30 \ub54c\ubb38\uc5d0 \ub530\ub85c Layer\ub97c \ucd94\uac00\ud574\uc57c \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \uc5c5\ub85c\ub4dc\ud574\uc57c\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub54c python\uc758 Lambda \ub7f0\ud0c0\uc784\uc5d0 \ub300\ud55c \uacc4\uce35 \uacbd\ub85c\ub294 python\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc555\ucd95\ud55c zip \ud30c\uc77c\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \ub744\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"pillow.zip\n\u2502 python/PIL\n\u2514 python/Pillow-5.3.0.dist-info\n"})}),"\n",(0,a.jsx)(n.p,{children:"Ubuntu \uae30\uc900 \ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc0dd\uc131\uc744 \uc9c4\ud589\ud588\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"sudo apt update\nsudo apt install zip\nsudo apt install python3-pip\n\nmkdir python\npip3 install matplotlib -t python # pip3 install \uc124\uce58\ud560_\ud328\ud0a4\uc9c0 -t \uc124\uce58_\uacbd\ub85c\nzip -r my_layer.zip python # zip -r \uc555\ucd95_\ud30c\uc77c\uba85 \uc555\ucd95_\ud30c\uc77c\uc774_\uc874\uc7ac\ud558\ub294_\uacbd\ub85c\n"})}),"\n",(0,a.jsxs)(n.h3,{id:"no-module-named-numpycore_multiarray_umath-\uc5d0\ub7ec",children:[(0,a.jsx)(n.code,{children:"No module named 'numpy.core._multiarray_umath'"})," \uc5d0\ub7ec"]}),"\n",(0,a.jsxs)(n.p,{children:["Layer \ucd94\uac00 \ud6c4 \ub78c\ub2e4 \uc2e4\ud589 \uc2dc \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\uc600\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucc98\uc74c\uc5d0 mac\uc5d0\uc11c zip \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc5c5\ub85c\ub4dc\ud588\ub294\ub370 \ud574\ub2f9 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub294 lambda\uac00 \ub3cc\uc544\uac00\ub294 \ub3d9\uc77c\ud55c \ud658\uacbd\uc5d0\uc11c layer\ub97c \uc704\ud55c zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc9c0 \uc54a\uc544\uc11c \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uac04\ub2e8\ud558\uac8c ec2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c \ub530\ub85c Layer\ub97c \uc0dd\uc131\ud558\uba74 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\uc801\uc815\uae30\uc220\uc5d0-\ub300\ud55c-\uc0dd\uac01",children:"\uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01"}),"\n",(0,a.jsxs)(n.p,{children:["\ud504\ub85c\uc81d\ud2b8\uc5d0 Lambda\uc640 Python\uc744 \uc0ac\uc6a9\ud558\ub824\uace0 \ud588\uc9c0\ub9cc \uc544\uc27d\uac8c\ub3c4 \ubc18\ub824\ub2f9\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","AWS Lambda\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc778\uc2a4\ud134\uc2a4\uc5d0 \ud574\ub2f9 \ucf54\ub4dc\ub97c \ubc30\ud3ec\ud558\ub294 \uac83\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc77c \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uac00\uc6a9 \uac00\ub2a5\ud55c \uc790\uc6d0, \uae30\uc220\uc758 \ub09c\uc774\ub3c4, \uc0ac\uc6a9\ud558\ub294 \ud300\uc6d0\uc744 \uace0\ub824\ud55c\ub2e4\uba74 Lambda\ub294 \uc801\uc815\uae30\uc220\uc774 \uc544\ub2d0 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud574\ub2f9 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\ub97c \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud560\uc9c0 \uc870\uae08 \ub354 \uace0\ub824\ub97c \ud574\uc57c \ub420 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\ucd5c\uc885\uc801\uc73c\ub85c Java AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4."})}),"\n",(0,a.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://aws.amazon.com/ko/lambda/",children:"AWS Lambda"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html",children:"Lambda Layer"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html",children:"Python Lambda \ud568\uc218\uc5d0 \ub300\ud55c .zip \ud30c\uc77c \uc544\uce74\uc774\ube0c \uc791\uc5c5"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://gist.github.com/ksmin23/0f3f243408a8497f766b43cf589fea7b",children:"No module named 'numpy.core._multiarray_umath'"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://techblog.woowahan.com/6217/",children:"\uc0ac\ub840\ubcc4\ub85c \uc54c\uc544\ubcf8 \uc548\uc804\ud55c S3 \uc0ac\uc6a9 \uac00\uc774\ub4dc"})]})]})}function c(e={}){const{wrapper:n}={...(0,i.ah)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>d});var a=t(67294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var o=a.createContext({}),d=function(e){var n=a.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},p={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,o=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=d(t),x=i,u=m["".concat(o,".").concat(x)]||m[x]||p[x]||r;return t?a.createElement(u,l(l({ref:n},c),{},{components:t})):a.createElement(u,l({ref:n},c))}));c.displayName="MDXCreateElement"},13533:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/route-89cacb9b7815a3191ab1f9d9e23c43a1.png"},46365:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/routeImage-0eac25ba9b356cd034ade6e062c1ce19.png"}}]); \ No newline at end of file diff --git a/assets/js/d28e30d7.489aca7d.js b/assets/js/d28e30d7.c8b5ab46.js similarity index 99% rename from assets/js/d28e30d7.489aca7d.js rename to assets/js/d28e30d7.c8b5ab46.js index 507ef1812..46e6311cc 100644 --- a/assets/js/d28e30d7.489aca7d.js +++ b/assets/js/d28e30d7.c8b5ab46.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6671],{70633:(e,n,l)=>{l.r(n),l.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>u,toc:()=>d});var r=l(85893),t=l(3905),a=l(74866),s=l(85162);const i={title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",slug:"kotlin-null",tags:["Kotlin"]},o=void 0,u={permalink:"/kotlin-null",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",source:"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",description:"nullable \ud0c0\uc785",date:"2023-01-16T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 16\uc77c",tags:[{label:"Kotlin",permalink:"/tags/kotlin"}],readingTime:4.225,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",slug:"kotlin-null",tags:["Kotlin"]},unlisted:!1,prevItem:{title:"IntelliJ \uc124\uc815",permalink:"/intellij-settings"},nextItem:{title:"JSR-310",permalink:"/jsr-310"}},c={authorsImageUrls:[]},d=[{value:"nullable \ud0c0\uc785",id:"nullable-\ud0c0\uc785",level:3},{value:"?. Safe Calls \uc5f0\uc0b0\uc790",id:"-safe-calls-\uc5f0\uc0b0\uc790",level:3},{value:"?: \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790",id:"-\uc5d8\ube44\uc2a4-\uc5f0\uc0b0\uc790",level:3},{value:"!! \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790",id:"-\ub110-\uc544\ub2d8-\ub2e8\uc5b8-\uc5f0\uc0b0\uc790",level:3},{value:"as? \uc548\uc804\ud55c \uce90\uc2a4\ud305",id:"as-\uc548\uc804\ud55c-\uce90\uc2a4\ud305",level:3},{value:"List\uc5d0\uc11c\uc758 null \ucc98\ub9ac",id:"list\uc5d0\uc11c\uc758-null-\ucc98\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function h(e){const n={a:"a",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"nullable-\ud0c0\uc785",children:"nullable \ud0c0\uc785"}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc740 ",(0,r.jsx)(n.code,{children:"NullPointerException"})," \uc608\uc678\ub97c \ucd5c\ub300\ud55c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 \ud0c0\uc785 \uc2dc\uc2a4\ud15c\uc774 \uc124\uacc4\ub418\uc5b4 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ub294 \uc2e4\ud589 \uc2dc\uc810\uc774 \uc544\ub2cc \ucef4\ud30c\uc77c \uc2dc \ubbf8\ub9ac \uc624\ub958\uac00 \ubc1c\uc0dd\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub294 \ubd80\ubd84\uc744 \ubbf8\ub9ac \uac10\uc9c0\ud558\uc5ec NPE \ubc1c\uc0dd\uc758 \uac00\ub2a5\uc131\uc744 \uc904\uc5ec\uc900\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\ucf54\ud2c0\ub9b0\uc758 \uacbd\uc6b0 nullable \ud0c0\uc785\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val number: Int?\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc785 \ub4a4\uc5d0 ",(0,r.jsx)(n.code,{children:"?"}),"\ub97c \ubd99\uc5ec \ud574\ub2f9 \uac12\uc774 null\uc774 \ub420 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9cc\uc57d ",(0,r.jsx)(n.code,{children:"?"}),"\ub97c \ubd99\uc774\uc9c0 \uc54a\uc744 \ub54c null\uc744 \ubc1b\ub294 \uacbd\uc6b0 \ucef4\ud30c\uc77c \uc2dc \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(n.h3,{id:"-safe-calls-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"?."})," Safe Calls \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsx)(n.p,{children:"\uc790\ubc14\uc5d0\uc11c NPE\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 null\uc744 \ucc98\ub9ac\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c\ub294 \ubd84\uae30\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4."}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc740 \uc548\uc804\ud55c \ud638\ucd9c \uc5f0\uc0b0\uc790\uc778 ",(0,r.jsx)(n.code,{children:"?."})," \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ucc38\uc870 \uac12\uc774 null\uc774 \uc544\ub2d0 \uacbd\uc6b0\uc5d0\ub9cc \uba54\uc11c\ub4dc \ud638\ucd9c\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucc38\uc870 \uac12\uc774 null\uc778 \uacbd\uc6b0 \uba54\uc11c\ub4dc \ud638\ucd9c\uc774 \ubb34\uc2dc\ub418\uace0, null\uc744 \ubc18\ud658\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(s.Z,{value:"Java",label:"Java",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public String repeat(String word) {\n if (word == null) {\n return null;\n }\n return word.repeat(2);\n}\n"})})}),(0,r.jsx)(s.Z,{value:"Kotlin",label:"Kotlin",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"fun repeat(word: String?): String? {\n return word?.repeat(2)\n}\n"})})})]}),"\n",(0,r.jsxs)(n.h3,{id:"-\uc5d8\ube44\uc2a4-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"?:"})," \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsxs)(n.p,{children:["\ucc38\uc870\ud558\ub824\ub294 \uac12\uc774 null\uc77c \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud558\uace0 \uc2f6\uc744 \ub54c\ub294 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?",(0,r.jsx)(n.br,{}),"\n","\ucf54\ud2c0\ub9b0\uc740 null\uc774 \uc544\ub2cc \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \ub54c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(s.Z,{value:"Java",label:"Java",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public String stringSafe(String word) {\n if (word == null) {\n return "";\n }\n return word;\n}\n'})})}),(0,r.jsx)(s.Z,{value:"Kotlin",label:"Kotlin",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:'fun stringSafe(word: String?): String {\n return word ?: ""\n}\n'})})})]}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 throw\ub3c4 \uc2dd\uc774\uae30 \ub54c\ubb38\uc5d0 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 \uc0ac\uc6a9\uc790 \uc815\ubcf4\uac00 \uc788\ub294 \uc800\uc7a5\uc18c\uc5d0 \ucc3e\ub294 \uc0ac\uc6a9\uc790\uac00 \uc5c6\ub294 \uacbd\uc6b0 \uc544\ub798\uc640 \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"userRepository.findByName(name) ?: throw IllegalArgumentException()\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"-\ub110-\uc544\ub2d8-\ub2e8\uc5b8-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"!!"})," \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsxs)(n.p,{children:["!! \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud55c\ub2e4\uba74 \uac15\uc81c\ub85c \uc5b4\ub5a4 \uac12\uc774\ub4e0 non-nullable \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc null\uc778 \uac12\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4\uba74 NPE\uac00 \ubc1c\uc0dd\ud558\uac8c \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc77c\ubc18\uc801\uc778 \uacbd\uc6b0\uc5d0\ub294 !! \uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc704\ud5d8\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc0ac\uc6a9\ud558\uae30 \uc27d\uc9c0\ub9cc, \ub9ac\uc2a4\ud06c\uac00 \ud06c\uace0 \ud639\uc2dc\ub098 \ud574\ub2f9 \uac12\uc774 \ucd94\ud6c4\uc5d0\ub294 null\uc774 \ub420 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc591\ud574\uc57c \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val length: Int = word!!.length\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"as-\uc548\uc804\ud55c-\uce90\uc2a4\ud305",children:[(0,r.jsx)(n.code,{children:"as?"})," \uc548\uc804\ud55c \uce90\uc2a4\ud305"]}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \ub54c \uc9c0\uc815\ud55c \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc5c6\ub2e4\uba74 ",(0,r.jsx)(n.code,{children:"ClassCastException"}),"\uc774 \ubc1c\uc0dd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 as \ub4a4\uc5d0 ?\ub97c \ubd99\uc5ec \uc548\uc804\ud558\uac8c \ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ubbf8\ub9ac \ubcc0\ud658 \uac00\ub2a5\ud55c \ud0c0\uc785\uc778\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uace0, \uc548\uc804\ud558\uac8c \ud0c0\uc785\uc744 \ubcc0\ud658 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\ud0c0\uc785 \ubcc0\ud658\uc774 \ubd88\uac00\ub2a5 \ud560 \uacbd\uc6b0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uace0 null\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val value: Int? = something as? Int\n"})}),"\n",(0,r.jsx)(n.h3,{id:"list\uc5d0\uc11c\uc758-null-\ucc98\ub9ac",children:"List\uc5d0\uc11c\uc758 null \ucc98\ub9ac"}),"\n",(0,r.jsxs)(n.p,{children:["List\uc5d0\ub294 null\uc774 \uc544\ub2cc \uac12\ub9cc \ubc18\ud658\ud558\ub294 ",(0,r.jsx)(n.code,{children:"filterNotNull"})," \uc720\ud2f8\ub9ac\ud2f0 \uba54\uc11c\ub4dc\ub97c \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:'val foodsWithNull: List = listOf("Pizza", "Cheese", null, "Potato")\nval foods = foodsWithNull.filterNotNull()\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://product.kyobobook.co.kr/detail/S000001804588",children:"Kotlin in Action"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://product.kyobobook.co.kr/detail/S000001033129",children:"Effective Kotlin Item 8"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://www.baeldung.com/kotlin/null-safety",children:"Comprehensive Guide to Null Safety in Kotlin"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://kotlinlang.org/docs/null-safety.html",children:"Kotlin NullSafety"})}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,n,l)=>{l.d(n,{ah:()=>u});var r=l(67294);function t(e,n,l){return n in e?Object.defineProperty(e,n,{value:l,enumerable:!0,configurable:!0,writable:!0}):e[n]=l,e}function a(e,n){var l=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),l.push.apply(l,r)}return l}function s(e){for(var n=1;n=0||(t[l]=e[l]);return t}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,l)&&(t[l]=e[l])}return t}var o=r.createContext({}),u=function(e){var n=r.useContext(o),l=n;return e&&(l="function"==typeof e?e(n):s(s({},n),e)),l},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var l=e.components,t=e.mdxType,a=e.originalType,o=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),h=u(l),p=t,f=h["".concat(o,".").concat(p)]||h[p]||c[p]||a;return l?r.createElement(f,s(s({ref:n},d),{},{components:l})):r.createElement(f,s({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,l)=>{l.d(n,{Z:()=>s});l(67294);var r=l(86010);const t={tabItem:"tabItem_Ymn6"};var a=l(85893);function s(e){let{children:n,hidden:l,className:s}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.Z)(t.tabItem,s),hidden:l,children:n})}},74866:(e,n,l)=>{l.d(n,{Z:()=>w});var r=l(67294),t=l(86010),a=l(12466),s=l(16550),i=l(20469),o=l(91980),u=l(67392),c=l(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function h(e){const{values:n,children:l}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:l,attributes:r,default:t}}=e;return{value:n,label:l,attributes:r,default:t}}))}(l);return function(e){const n=(0,u.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,l])}function p(e){let{value:n,tabValues:l}=e;return l.some((e=>e.value===n))}function f(e){let{queryString:n=!1,groupId:l}=e;const t=(0,s.k6)(),a=function(e){let{queryString:n=!1,groupId:l}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!l)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return l??null}({queryString:n,groupId:l});return[(0,o._X)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(t.location.search);n.set(a,e),t.replace({...t.location,search:n.toString()})}),[a,t])]}function b(e){const{defaultValue:n,queryString:l=!1,groupId:t}=e,a=h(e),[s,o]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:l}=e;if(0===l.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:l}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${l.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=l.find((e=>e.default))??l[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[u,d]=f({queryString:l,groupId:t}),[b,j]=function(e){let{groupId:n}=e;const l=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,a]=(0,c.Nk)(l);return[t,(0,r.useCallback)((e=>{l&&a.set(e)}),[l,a])]}({groupId:t}),m=(()=>{const e=u??b;return p({value:e,tabValues:a})?e:null})();(0,i.Z)((()=>{m&&o(m)}),[m]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!p({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);o(e),d(e),j(e)}),[d,j,a]),tabValues:a}}var j=l(72389);const m={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=l(85893);function g(e){let{className:n,block:l,selectedValue:r,selectValue:s,tabValues:i}=e;const o=[],{blockElementScrollPositionUntilNextRender:u}=(0,a.o5)(),c=e=>{const n=e.currentTarget,l=o.indexOf(n),t=i[l].value;t!==r&&(u(n),s(t))},d=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const l=o.indexOf(e.currentTarget)+1;n=o[l]??o[0];break}case"ArrowLeft":{const l=o.indexOf(e.currentTarget)-1;n=o[l]??o[o.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.Z)("tabs",{"tabs--block":l},n),children:i.map((e=>{let{value:n,label:l,attributes:a}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>o.push(e),onKeyDown:d,onClick:c,...a,className:(0,t.Z)("tabs__item",m.tabItem,a?.className,{"tabs__item--active":r===n}),children:l??n},n)}))})}function v(e){let{lazy:n,children:l,selectedValue:t}=e;const a=(Array.isArray(l)?l:[l]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===t));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function y(e){const n=b(e);return(0,x.jsxs)("div",{className:(0,t.Z)("tabs-container",m.tabList),children:[(0,x.jsx)(g,{...e,...n}),(0,x.jsx)(v,{...e,...n})]})}function w(e){const n=(0,j.Z)();return(0,x.jsx)(y,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6671],{70633:(e,n,l)=>{l.r(n),l.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>u,toc:()=>d});var r=l(85893),t=l(3905),a=l(74866),s=l(85162);const i={title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",slug:"kotlin-null",tags:["Kotlin"]},o=void 0,u={permalink:"/kotlin-null",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",source:"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",description:"nullable \ud0c0\uc785",date:"2023-01-16T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 16\uc77c",tags:[{label:"Kotlin",permalink:"/tags/kotlin"}],readingTime:4.225,hasTruncateMarker:!1,authors:[],frontMatter:{title:"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95",slug:"kotlin-null",tags:["Kotlin"]},unlisted:!1,prevItem:{title:"JSR-310",permalink:"/jsr-310"},nextItem:{title:"IntelliJ \uc124\uc815",permalink:"/intellij-settings"}},c={authorsImageUrls:[]},d=[{value:"nullable \ud0c0\uc785",id:"nullable-\ud0c0\uc785",level:3},{value:"?. Safe Calls \uc5f0\uc0b0\uc790",id:"-safe-calls-\uc5f0\uc0b0\uc790",level:3},{value:"?: \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790",id:"-\uc5d8\ube44\uc2a4-\uc5f0\uc0b0\uc790",level:3},{value:"!! \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790",id:"-\ub110-\uc544\ub2d8-\ub2e8\uc5b8-\uc5f0\uc0b0\uc790",level:3},{value:"as? \uc548\uc804\ud55c \uce90\uc2a4\ud305",id:"as-\uc548\uc804\ud55c-\uce90\uc2a4\ud305",level:3},{value:"List\uc5d0\uc11c\uc758 null \ucc98\ub9ac",id:"list\uc5d0\uc11c\uc758-null-\ucc98\ub9ac",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function h(e){const n={a:"a",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"nullable-\ud0c0\uc785",children:"nullable \ud0c0\uc785"}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc740 ",(0,r.jsx)(n.code,{children:"NullPointerException"})," \uc608\uc678\ub97c \ucd5c\ub300\ud55c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 \ud0c0\uc785 \uc2dc\uc2a4\ud15c\uc774 \uc124\uacc4\ub418\uc5b4 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ub294 \uc2e4\ud589 \uc2dc\uc810\uc774 \uc544\ub2cc \ucef4\ud30c\uc77c \uc2dc \ubbf8\ub9ac \uc624\ub958\uac00 \ubc1c\uc0dd\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub294 \ubd80\ubd84\uc744 \ubbf8\ub9ac \uac10\uc9c0\ud558\uc5ec NPE \ubc1c\uc0dd\uc758 \uac00\ub2a5\uc131\uc744 \uc904\uc5ec\uc900\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\ucf54\ud2c0\ub9b0\uc758 \uacbd\uc6b0 nullable \ud0c0\uc785\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val number: Int?\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc785 \ub4a4\uc5d0 ",(0,r.jsx)(n.code,{children:"?"}),"\ub97c \ubd99\uc5ec \ud574\ub2f9 \uac12\uc774 null\uc774 \ub420 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9cc\uc57d ",(0,r.jsx)(n.code,{children:"?"}),"\ub97c \ubd99\uc774\uc9c0 \uc54a\uc744 \ub54c null\uc744 \ubc1b\ub294 \uacbd\uc6b0 \ucef4\ud30c\uc77c \uc2dc \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(n.h3,{id:"-safe-calls-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"?."})," Safe Calls \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsx)(n.p,{children:"\uc790\ubc14\uc5d0\uc11c NPE\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 null\uc744 \ucc98\ub9ac\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c\ub294 \ubd84\uae30\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4."}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc740 \uc548\uc804\ud55c \ud638\ucd9c \uc5f0\uc0b0\uc790\uc778 ",(0,r.jsx)(n.code,{children:"?."})," \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ucc38\uc870 \uac12\uc774 null\uc774 \uc544\ub2d0 \uacbd\uc6b0\uc5d0\ub9cc \uba54\uc11c\ub4dc \ud638\ucd9c\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucc38\uc870 \uac12\uc774 null\uc778 \uacbd\uc6b0 \uba54\uc11c\ub4dc \ud638\ucd9c\uc774 \ubb34\uc2dc\ub418\uace0, null\uc744 \ubc18\ud658\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(s.Z,{value:"Java",label:"Java",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public String repeat(String word) {\n if (word == null) {\n return null;\n }\n return word.repeat(2);\n}\n"})})}),(0,r.jsx)(s.Z,{value:"Kotlin",label:"Kotlin",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"fun repeat(word: String?): String? {\n return word?.repeat(2)\n}\n"})})})]}),"\n",(0,r.jsxs)(n.h3,{id:"-\uc5d8\ube44\uc2a4-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"?:"})," \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsxs)(n.p,{children:["\ucc38\uc870\ud558\ub824\ub294 \uac12\uc774 null\uc77c \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud558\uace0 \uc2f6\uc744 \ub54c\ub294 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?",(0,r.jsx)(n.br,{}),"\n","\ucf54\ud2c0\ub9b0\uc740 null\uc774 \uc544\ub2cc \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \ub54c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4."]}),"\n",(0,r.jsxs)(a.Z,{children:[(0,r.jsx)(s.Z,{value:"Java",label:"Java",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public String stringSafe(String word) {\n if (word == null) {\n return "";\n }\n return word;\n}\n'})})}),(0,r.jsx)(s.Z,{value:"Kotlin",label:"Kotlin",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:'fun stringSafe(word: String?): String {\n return word ?: ""\n}\n'})})})]}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 throw\ub3c4 \uc2dd\uc774\uae30 \ub54c\ubb38\uc5d0 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 \uc0ac\uc6a9\uc790 \uc815\ubcf4\uac00 \uc788\ub294 \uc800\uc7a5\uc18c\uc5d0 \ucc3e\ub294 \uc0ac\uc6a9\uc790\uac00 \uc5c6\ub294 \uacbd\uc6b0 \uc544\ub798\uc640 \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"userRepository.findByName(name) ?: throw IllegalArgumentException()\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"-\ub110-\uc544\ub2d8-\ub2e8\uc5b8-\uc5f0\uc0b0\uc790",children:[(0,r.jsx)(n.code,{children:"!!"})," \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790"]}),"\n",(0,r.jsxs)(n.p,{children:["!! \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud55c\ub2e4\uba74 \uac15\uc81c\ub85c \uc5b4\ub5a4 \uac12\uc774\ub4e0 non-nullable \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc null\uc778 \uac12\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4\uba74 NPE\uac00 \ubc1c\uc0dd\ud558\uac8c \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc77c\ubc18\uc801\uc778 \uacbd\uc6b0\uc5d0\ub294 !! \uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc704\ud5d8\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc0ac\uc6a9\ud558\uae30 \uc27d\uc9c0\ub9cc, \ub9ac\uc2a4\ud06c\uac00 \ud06c\uace0 \ud639\uc2dc\ub098 \ud574\ub2f9 \uac12\uc774 \ucd94\ud6c4\uc5d0\ub294 null\uc774 \ub420 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc591\ud574\uc57c \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val length: Int = word!!.length\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"as-\uc548\uc804\ud55c-\uce90\uc2a4\ud305",children:[(0,r.jsx)(n.code,{children:"as?"})," \uc548\uc804\ud55c \uce90\uc2a4\ud305"]}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \ub54c \uc9c0\uc815\ud55c \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc5c6\ub2e4\uba74 ",(0,r.jsx)(n.code,{children:"ClassCastException"}),"\uc774 \ubc1c\uc0dd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 as \ub4a4\uc5d0 ?\ub97c \ubd99\uc5ec \uc548\uc804\ud558\uac8c \ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ubbf8\ub9ac \ubcc0\ud658 \uac00\ub2a5\ud55c \ud0c0\uc785\uc778\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uace0, \uc548\uc804\ud558\uac8c \ud0c0\uc785\uc744 \ubcc0\ud658 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\ud0c0\uc785 \ubcc0\ud658\uc774 \ubd88\uac00\ub2a5 \ud560 \uacbd\uc6b0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uace0 null\uc744 \ubc18\ud658\ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:"val value: Int? = something as? Int\n"})}),"\n",(0,r.jsx)(n.h3,{id:"list\uc5d0\uc11c\uc758-null-\ucc98\ub9ac",children:"List\uc5d0\uc11c\uc758 null \ucc98\ub9ac"}),"\n",(0,r.jsxs)(n.p,{children:["List\uc5d0\ub294 null\uc774 \uc544\ub2cc \uac12\ub9cc \ubc18\ud658\ud558\ub294 ",(0,r.jsx)(n.code,{children:"filterNotNull"})," \uc720\ud2f8\ub9ac\ud2f0 \uba54\uc11c\ub4dc\ub97c \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-kotlin",children:'val foodsWithNull: List = listOf("Pizza", "Cheese", null, "Potato")\nval foods = foodsWithNull.filterNotNull()\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://product.kyobobook.co.kr/detail/S000001804588",children:"Kotlin in Action"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://product.kyobobook.co.kr/detail/S000001033129",children:"Effective Kotlin Item 8"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://www.baeldung.com/kotlin/null-safety",children:"Comprehensive Guide to Null Safety in Kotlin"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://kotlinlang.org/docs/null-safety.html",children:"Kotlin NullSafety"})}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,n,l)=>{l.d(n,{ah:()=>u});var r=l(67294);function t(e,n,l){return n in e?Object.defineProperty(e,n,{value:l,enumerable:!0,configurable:!0,writable:!0}):e[n]=l,e}function a(e,n){var l=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),l.push.apply(l,r)}return l}function s(e){for(var n=1;n=0||(t[l]=e[l]);return t}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,l)&&(t[l]=e[l])}return t}var o=r.createContext({}),u=function(e){var n=r.useContext(o),l=n;return e&&(l="function"==typeof e?e(n):s(s({},n),e)),l},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var l=e.components,t=e.mdxType,a=e.originalType,o=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),h=u(l),p=t,f=h["".concat(o,".").concat(p)]||h[p]||c[p]||a;return l?r.createElement(f,s(s({ref:n},d),{},{components:l})):r.createElement(f,s({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,l)=>{l.d(n,{Z:()=>s});l(67294);var r=l(86010);const t={tabItem:"tabItem_Ymn6"};var a=l(85893);function s(e){let{children:n,hidden:l,className:s}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.Z)(t.tabItem,s),hidden:l,children:n})}},74866:(e,n,l)=>{l.d(n,{Z:()=>w});var r=l(67294),t=l(86010),a=l(12466),s=l(16550),i=l(20469),o=l(91980),u=l(67392),c=l(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function h(e){const{values:n,children:l}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:l,attributes:r,default:t}}=e;return{value:n,label:l,attributes:r,default:t}}))}(l);return function(e){const n=(0,u.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,l])}function p(e){let{value:n,tabValues:l}=e;return l.some((e=>e.value===n))}function f(e){let{queryString:n=!1,groupId:l}=e;const t=(0,s.k6)(),a=function(e){let{queryString:n=!1,groupId:l}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!l)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return l??null}({queryString:n,groupId:l});return[(0,o._X)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(t.location.search);n.set(a,e),t.replace({...t.location,search:n.toString()})}),[a,t])]}function b(e){const{defaultValue:n,queryString:l=!1,groupId:t}=e,a=h(e),[s,o]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:l}=e;if(0===l.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:l}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${l.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=l.find((e=>e.default))??l[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[u,d]=f({queryString:l,groupId:t}),[b,j]=function(e){let{groupId:n}=e;const l=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,a]=(0,c.Nk)(l);return[t,(0,r.useCallback)((e=>{l&&a.set(e)}),[l,a])]}({groupId:t}),m=(()=>{const e=u??b;return p({value:e,tabValues:a})?e:null})();(0,i.Z)((()=>{m&&o(m)}),[m]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!p({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);o(e),d(e),j(e)}),[d,j,a]),tabValues:a}}var j=l(72389);const m={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=l(85893);function g(e){let{className:n,block:l,selectedValue:r,selectValue:s,tabValues:i}=e;const o=[],{blockElementScrollPositionUntilNextRender:u}=(0,a.o5)(),c=e=>{const n=e.currentTarget,l=o.indexOf(n),t=i[l].value;t!==r&&(u(n),s(t))},d=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const l=o.indexOf(e.currentTarget)+1;n=o[l]??o[0];break}case"ArrowLeft":{const l=o.indexOf(e.currentTarget)-1;n=o[l]??o[o.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.Z)("tabs",{"tabs--block":l},n),children:i.map((e=>{let{value:n,label:l,attributes:a}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>o.push(e),onKeyDown:d,onClick:c,...a,className:(0,t.Z)("tabs__item",m.tabItem,a?.className,{"tabs__item--active":r===n}),children:l??n},n)}))})}function v(e){let{lazy:n,children:l,selectedValue:t}=e;const a=(Array.isArray(l)?l:[l]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===t));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function y(e){const n=b(e);return(0,x.jsxs)("div",{className:(0,t.Z)("tabs-container",m.tabList),children:[(0,x.jsx)(g,{...e,...n}),(0,x.jsx)(v,{...e,...n})]})}function w(e){const n=(0,j.Z)();return(0,x.jsx)(y,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file diff --git a/assets/js/d350f5d9.668ec20f.js b/assets/js/d350f5d9.ebc27a24.js similarity index 70% rename from assets/js/d350f5d9.668ec20f.js rename to assets/js/d350f5d9.ebc27a24.js index 248841034..b22a3326b 100644 --- a/assets/js/d350f5d9.668ec20f.js +++ b/assets/js/d350f5d9.ebc27a24.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2098],{82622:e=>{e.exports=JSON.parse('{"label":"test","permalink":"/tags/test","allTagsPath":"/tags","count":2,"unlisted":false}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2098],{82622:e=>{e.exports=JSON.parse('{"label":"Test","permalink":"/tags/test","allTagsPath":"/tags","count":2,"unlisted":false}')}}]); \ No newline at end of file diff --git a/assets/js/d5bb232a.61c24a0e.js b/assets/js/d5bb232a.a8801f4d.js similarity index 98% rename from assets/js/d5bb232a.61c24a0e.js rename to assets/js/d5bb232a.a8801f4d.js index 401cb2fa7..969a68432 100644 --- a/assets/js/d5bb232a.61c24a0e.js +++ b/assets/js/d5bb232a.a8801f4d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3651],{46116:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>d,frontMatter:()=>l,metadata:()=>c,toc:()=>o});var i=r(85893),t=r(3905);const l={title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",slug:"composite",tags:["Pattern","Composite"]},s=void 0,c={permalink:"/composite",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",source:"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",description:"\uc694\uad6c\uc0ac\ud56d",date:"2023-05-26T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 26\uc77c",tags:[{label:"Pattern",permalink:"/tags/pattern"},{label:"Composite",permalink:"/tags/composite"}],readingTime:4.74,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",slug:"composite",tags:["Pattern","Composite"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",permalink:"/tecochat-retrospective-3"},nextItem:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",permalink:"/subway-retrospective"}},a={authorsImageUrls:[]},o=[{value:"\uc694\uad6c\uc0ac\ud56d",id:"\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9",id:"\uc778\ud130\ud398\uc774\uc2a4-\uc0ac\uc6a9",level:3},{value:"\ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30",id:"\ubaa8\ub4e0-\uc694\uae08-\uc815\ucc45\uc744-\ud3ec\ud568\ud558\ub294-\uc0c8\ub85c\uc6b4-\uc694\uae08-\uc815\ucc45-\ub9cc\ub4e4\uae30",level:3},{value:"\uc815\ucc45\uc758 \uc21c\uc11c",id:"\uc815\ucc45\uc758-\uc21c\uc11c",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc774\ub780",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uad6c\uc131\uc694\uc18c",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uc0ac\uc6a9\uacfc-\uc8fc\uc694-\ubaa9\ud45c",level:3},{value:"\ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84",id:"\ud328\ud134-\uc0ac\uc6a9\uc2dc-\uc8fc\uc758\ud574\uc57c\ud560-\ubd80\ubd84",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={blockquote:"blockquote",br:"br",code:"code",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"\uc694\uad6c\uc0ac\ud56d",children:"\uc694\uad6c\uc0ac\ud56d"}),"\n",(0,i.jsx)(n.p,{children:"\uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uac70\ub9ac\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45"}),"\n",(0,i.jsx)(n.li,{children:"\ub178\uc120\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45"}),"\n",(0,i.jsx)(n.li,{children:"\uc5f0\ub839\ubcc4 \uc694\uae08 \ud560\uc778 \uc815\ucc45"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\uc778\ud130\ud398\uc774\uc2a4-\uc0ac\uc6a9",children:"\uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9"}),"\n",(0,i.jsxs)(n.p,{children:["\uc694\uae08 \uc815\ucc45\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud45c\ud604\ud560 \uc218 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc694\uae08\uc744 \uacc4\uc0b0\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ucd5c\ub2e8 \uacbd\ub85c \uacc4\uc0b0\uc758 \uacb0\uacfc, \uc0ac\uc6a9\uc790\uc758 \uc815\ubcf4, \uc694\uae08\uc744 \ubc1b\uc544 \uc694\uae08\uc744 \uacc4\uc0b0\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public interface FarePolicy {\n int calculate(Path path, Passenger passenger, int fare);\n}\n\npublic class BaseFarePolicy implements FarePolicy { ... }\npublic class DistanceFarePolicy implements FarePolicy { ... }\npublic class AgeDiscountFarePolicy implements FarePolicy { ... }\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite1",src:r(28629).Z+"",width:"1768",height:"554"})}),"\n",(0,i.jsx)(n.h3,{id:"\ubaa8\ub4e0-\uc694\uae08-\uc815\ucc45\uc744-\ud3ec\ud568\ud558\ub294-\uc0c8\ub85c\uc6b4-\uc694\uae08-\uc815\ucc45-\ub9cc\ub4e4\uae30",children:"\ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30"}),"\n",(0,i.jsxs)(n.p,{children:["\ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub97c \ubaa8\ub450 \uac00\uc9c0\uace0 \uc788\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\ub97c \ub9cc\ub4e4\uc5c8\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc774 \ub610\ud55c FarePolicy\ub97c \uad6c\ud604\ud55c \ud615\ud0dc\uac00 \ub418\uace0, \ud544\ub4dc\ub85c\ub294 \ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub4e4\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public class SubwayFarePolicy implements FarePolicy {\n\n private final List farePolicies;\n\n public SubwayFarePolicy(final List farePolicies) {\n this.farePolicies = farePolicies;\n }\n\n @Override\n public int calculate(final Path path, final Passenger passenger, final int fare) {\n int calculatedFare = fare;\n for (FarePolicy farePolicy : farePolicies) {\n calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);\n }\n return calculatedFare;\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\ub530\ub77c\uc11c \uadf8\ub9bc\uc73c\ub85c \ubcf8\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite2",src:r(33094).Z+"",width:"2020",height:"954"})}),"\n",(0,i.jsx)(n.h3,{id:"\uc815\ucc45\uc758-\uc21c\uc11c",children:"\uc815\ucc45\uc758 \uc21c\uc11c"}),"\n",(0,i.jsxs)(n.p,{children:["\uc9c0\ud558\ucca0 \uc694\uad6c\uc0ac\ud56d\uc740 \uc21c\uc11c\uac00 \uc911\uc694\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uae08\uc561\uc758 \ucd1d\ud569\uc744 \uad6c\ud558\uace0, \uadf8 \ud6c4\uc5d0 \ud560\uc778 \uc815\ucc45\uc774 \ub4e4\uc5b4\uac00\uc57c\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc790\uc2dd\ub4e4\uc758 \uc21c\uc11c\ub97c \uad00\ub9ac\ud560 \ub54c \uc8fc\uc758\ub97c \uae30\uc6b8\uc5ec\uc57c \ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Configuration \ud074\ub798\uc2a4\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc21c\uc11c\ub97c \uc9c1\uc811 \uc801\uc6a9\uc2dc\ucf30\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@Configuration\npublic class FareConfiguration {\n\n @Bean\n public FarePolicy farePolicy() {\n return new SubwayFarePolicy(List.of(\n new BaseFarePolicy(),\n new DistanceFarePolicy(),\n new AgeDiscountFarePolicy()\n ));\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc774\ub780",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite3",src:r(67922).Z+"",width:"1848",height:"482"})}),"\n",(0,i.jsx)(n.p,{children:"GOF\uc758 \ub514\uc790\uc778 \ud328\ud134 \ucc45\uc5d0\uc11c\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uba85\ud558\uace0 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:["\ubd80\ubd84\uacfc \uc804\uccb4\uc758 \uacc4\uce35\uc744 \ud45c\ud604\ud558\uae30 \uc704\ud574 \uac1d\uccb4\ub4e4\uc744 \ubaa8\uc544 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ud569\ub2c8\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ubcf5\ud569 \uac1d\uccb4\ub97c \ubaa8\ub450 \ub3d9\uc77c\ud558\uac8c \ub2e4\ub8f0 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc785\ub2c8\ub2e4."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc774 \ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uad6c\uc131\uc694\uc18c",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c"}),"\n",(0,i.jsx)(n.p,{children:"Component"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc9d1\ud569 \uad00\uacc4\uc5d0 \uc815\uc758\ub420 \ubaa8\ub4e0 \uac1d\uccb4\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uc694\uae08 \uc815\ucc45(FarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Leaf"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uac1c\ubcc4 \uac1d\uccb4, \uac1d\uccb4 \ud569\uc131\uc5d0 \uae30\ubcf8\uc774 \ub418\ub294 \uac1d\uccb4\uc758 \ud589\ub3d9"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uac70\ub9ac \ubcc4 \uc694\uae08 \uc815\ucc45(DistanceFarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Composite"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc5ec\ub7ec \uac1c\uc758 \uac1c\ubc1c \uac1d\uccb4\ub97c \ud3ec\ud568\ud558\ub294 \ud569\uc131 \uac1d\uccb4"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uc9c0\ud558\ucca0 \uc694\uae08 \uc815\ucc45(SubwayFarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Client"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uc0ac\uc6a9\uacfc-\uc8fc\uc694-\ubaa9\ud45c",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c"}),"\n",(0,i.jsxs)(n.p,{children:["\ubd80\ubd84 - \uc804\uccb4\uc758 \uad00\uacc4\ub97c \ud45c\ud604\ud558\uace0 \uc2f6\uc744 \ub54c",(0,i.jsx)(n.br,{}),"\n","Client \uae30\uc900\uc73c\ub85c Composite\uc640 Leaf\uc758 \ucc28\uc774\ub97c \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc798 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud574\uc57c\ub420 \ub54c"]}),"\n",(0,i.jsx)(n.h3,{id:"\ud328\ud134-\uc0ac\uc6a9\uc2dc-\uc8fc\uc758\ud574\uc57c\ud560-\ubd80\ubd84",children:"\ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84"}),"\n",(0,i.jsxs)(n.p,{children:["\ud328\ud134\uc740 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc758 \ud15c\ud50c\ub9bf\uc774\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ubc18\ubcf5\ub418\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc788\uc9c0\ub9cc \ud328\ud134\uc5d0 \ub9e4\ubab0\ub418\uc11c\ub294 \uc548\ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud328\ud134\uc744 \ub9f9\ubaa9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548\ub418\uace0, \ud604\uc7ac\uc758 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub530\ub77c \ud328\ud134\uc744 \uc720\ub3d9\uc801\uc73c\ub85c \uc218\uc815\ud574\uac00\uba74\uc11c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud56d\uc0c1 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uc0dd\uac01\ud558\uc790!"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134, GoF\uc758 \ub514\uc790\uc778 \ud328\ud134",(0,i.jsx)(n.br,{}),"\n","\ub514\uc790\uc778 \ud328\ud134\uacfc \ud504\ub808\uc784\uc6cc\ud06c, \uc624\ube0c\uc81d\ud2b8"]})]})}function d(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var i=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var a=i.createContext({}),o=function(e){var n=i.useContext(a),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var r=e.components,t=e.mdxType,l=e.originalType,a=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),u=o(r),h=t,j=u["".concat(a,".").concat(h)]||u[h]||p[h]||l;return r?i.createElement(j,s(s({ref:n},d),{},{components:r})):i.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"},28629:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite1-6117733e5244b235d9405ba72afb53ed.png"},33094:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite2-ac487a832bf12267cc91996ea3a5b9c7.png"},67922:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite3-016bf41863692b1f738bc89011687166.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3651],{46116:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>d,frontMatter:()=>l,metadata:()=>c,toc:()=>o});var i=r(85893),t=r(3905);const l={title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",slug:"composite",tags:["Pattern","Composite"]},s=void 0,c={permalink:"/composite",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",source:"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",description:"\uc694\uad6c\uc0ac\ud56d",date:"2023-05-26T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 26\uc77c",tags:[{label:"Pattern",permalink:"/tags/pattern"},{label:"Composite",permalink:"/tags/composite"}],readingTime:4.74,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30",slug:"composite",tags:["Pattern","Composite"]},unlisted:!1,prevItem:{title:"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0",permalink:"/subway-retrospective"},nextItem:{title:"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604",permalink:"/tecochat-retrospective-3"}},a={authorsImageUrls:[]},o=[{value:"\uc694\uad6c\uc0ac\ud56d",id:"\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9",id:"\uc778\ud130\ud398\uc774\uc2a4-\uc0ac\uc6a9",level:3},{value:"\ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30",id:"\ubaa8\ub4e0-\uc694\uae08-\uc815\ucc45\uc744-\ud3ec\ud568\ud558\ub294-\uc0c8\ub85c\uc6b4-\uc694\uae08-\uc815\ucc45-\ub9cc\ub4e4\uae30",level:3},{value:"\uc815\ucc45\uc758 \uc21c\uc11c",id:"\uc815\ucc45\uc758-\uc21c\uc11c",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc774\ub780",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uad6c\uc131\uc694\uc18c",level:3},{value:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c",id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uc0ac\uc6a9\uacfc-\uc8fc\uc694-\ubaa9\ud45c",level:3},{value:"\ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84",id:"\ud328\ud134-\uc0ac\uc6a9\uc2dc-\uc8fc\uc758\ud574\uc57c\ud560-\ubd80\ubd84",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={blockquote:"blockquote",br:"br",code:"code",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"\uc694\uad6c\uc0ac\ud56d",children:"\uc694\uad6c\uc0ac\ud56d"}),"\n",(0,i.jsx)(n.p,{children:"\uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uac70\ub9ac\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45"}),"\n",(0,i.jsx)(n.li,{children:"\ub178\uc120\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45"}),"\n",(0,i.jsx)(n.li,{children:"\uc5f0\ub839\ubcc4 \uc694\uae08 \ud560\uc778 \uc815\ucc45"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\uc778\ud130\ud398\uc774\uc2a4-\uc0ac\uc6a9",children:"\uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9"}),"\n",(0,i.jsxs)(n.p,{children:["\uc694\uae08 \uc815\ucc45\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud45c\ud604\ud560 \uc218 \uc788\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc694\uae08\uc744 \uacc4\uc0b0\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ucd5c\ub2e8 \uacbd\ub85c \uacc4\uc0b0\uc758 \uacb0\uacfc, \uc0ac\uc6a9\uc790\uc758 \uc815\ubcf4, \uc694\uae08\uc744 \ubc1b\uc544 \uc694\uae08\uc744 \uacc4\uc0b0\ud55c\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public interface FarePolicy {\n int calculate(Path path, Passenger passenger, int fare);\n}\n\npublic class BaseFarePolicy implements FarePolicy { ... }\npublic class DistanceFarePolicy implements FarePolicy { ... }\npublic class AgeDiscountFarePolicy implements FarePolicy { ... }\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite1",src:r(28629).Z+"",width:"1768",height:"554"})}),"\n",(0,i.jsx)(n.h3,{id:"\ubaa8\ub4e0-\uc694\uae08-\uc815\ucc45\uc744-\ud3ec\ud568\ud558\ub294-\uc0c8\ub85c\uc6b4-\uc694\uae08-\uc815\ucc45-\ub9cc\ub4e4\uae30",children:"\ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30"}),"\n",(0,i.jsxs)(n.p,{children:["\ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub97c \ubaa8\ub450 \uac00\uc9c0\uace0 \uc788\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\ub97c \ub9cc\ub4e4\uc5c8\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc774 \ub610\ud55c FarePolicy\ub97c \uad6c\ud604\ud55c \ud615\ud0dc\uac00 \ub418\uace0, \ud544\ub4dc\ub85c\ub294 \ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub4e4\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public class SubwayFarePolicy implements FarePolicy {\n\n private final List farePolicies;\n\n public SubwayFarePolicy(final List farePolicies) {\n this.farePolicies = farePolicies;\n }\n\n @Override\n public int calculate(final Path path, final Passenger passenger, final int fare) {\n int calculatedFare = fare;\n for (FarePolicy farePolicy : farePolicies) {\n calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);\n }\n return calculatedFare;\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\ub530\ub77c\uc11c \uadf8\ub9bc\uc73c\ub85c \ubcf8\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite2",src:r(33094).Z+"",width:"2020",height:"954"})}),"\n",(0,i.jsx)(n.h3,{id:"\uc815\ucc45\uc758-\uc21c\uc11c",children:"\uc815\ucc45\uc758 \uc21c\uc11c"}),"\n",(0,i.jsxs)(n.p,{children:["\uc9c0\ud558\ucca0 \uc694\uad6c\uc0ac\ud56d\uc740 \uc21c\uc11c\uac00 \uc911\uc694\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uae08\uc561\uc758 \ucd1d\ud569\uc744 \uad6c\ud558\uace0, \uadf8 \ud6c4\uc5d0 \ud560\uc778 \uc815\ucc45\uc774 \ub4e4\uc5b4\uac00\uc57c\ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc790\uc2dd\ub4e4\uc758 \uc21c\uc11c\ub97c \uad00\ub9ac\ud560 \ub54c \uc8fc\uc758\ub97c \uae30\uc6b8\uc5ec\uc57c \ud588\ub2e4.",(0,i.jsx)(n.br,{}),"\n","Configuration \ud074\ub798\uc2a4\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc21c\uc11c\ub97c \uc9c1\uc811 \uc801\uc6a9\uc2dc\ucf30\ub2e4."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@Configuration\npublic class FareConfiguration {\n\n @Bean\n public FarePolicy farePolicy() {\n return new SubwayFarePolicy(List.of(\n new BaseFarePolicy(),\n new DistanceFarePolicy(),\n new AgeDiscountFarePolicy()\n ));\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc774\ub780",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"composite3",src:r(67922).Z+"",width:"1848",height:"482"})}),"\n",(0,i.jsx)(n.p,{children:"GOF\uc758 \ub514\uc790\uc778 \ud328\ud134 \ucc45\uc5d0\uc11c\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uba85\ud558\uace0 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:["\ubd80\ubd84\uacfc \uc804\uccb4\uc758 \uacc4\uce35\uc744 \ud45c\ud604\ud558\uae30 \uc704\ud574 \uac1d\uccb4\ub4e4\uc744 \ubaa8\uc544 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ud569\ub2c8\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ubcf5\ud569 \uac1d\uccb4\ub97c \ubaa8\ub450 \ub3d9\uc77c\ud558\uac8c \ub2e4\ub8f0 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc785\ub2c8\ub2e4."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\uc774 \ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uad6c\uc131\uc694\uc18c",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c"}),"\n",(0,i.jsx)(n.p,{children:"Component"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc9d1\ud569 \uad00\uacc4\uc5d0 \uc815\uc758\ub420 \ubaa8\ub4e0 \uac1d\uccb4\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uc694\uae08 \uc815\ucc45(FarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Leaf"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uac1c\ubcc4 \uac1d\uccb4, \uac1d\uccb4 \ud569\uc131\uc5d0 \uae30\ubcf8\uc774 \ub418\ub294 \uac1d\uccb4\uc758 \ud589\ub3d9"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uac70\ub9ac \ubcc4 \uc694\uae08 \uc815\ucc45(DistanceFarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Composite"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc5ec\ub7ec \uac1c\uc758 \uac1c\ubc1c \uac1d\uccb4\ub97c \ud3ec\ud568\ud558\ub294 \ud569\uc131 \uac1d\uccb4"}),"\n",(0,i.jsx)(n.li,{children:"ex) \uc9c0\ud558\ucca0 \uc694\uae08 \uc815\ucc45(SubwayFarePolicy)"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Client"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucef4\ud3ec\uc9c0\ud2b8-\ud328\ud134\uc758-\uc0ac\uc6a9\uacfc-\uc8fc\uc694-\ubaa9\ud45c",children:"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c"}),"\n",(0,i.jsxs)(n.p,{children:["\ubd80\ubd84 - \uc804\uccb4\uc758 \uad00\uacc4\ub97c \ud45c\ud604\ud558\uace0 \uc2f6\uc744 \ub54c",(0,i.jsx)(n.br,{}),"\n","Client \uae30\uc900\uc73c\ub85c Composite\uc640 Leaf\uc758 \ucc28\uc774\ub97c \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc798 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud574\uc57c\ub420 \ub54c"]}),"\n",(0,i.jsx)(n.h3,{id:"\ud328\ud134-\uc0ac\uc6a9\uc2dc-\uc8fc\uc758\ud574\uc57c\ud560-\ubd80\ubd84",children:"\ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84"}),"\n",(0,i.jsxs)(n.p,{children:["\ud328\ud134\uc740 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc758 \ud15c\ud50c\ub9bf\uc774\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ubc18\ubcf5\ub418\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc788\uc9c0\ub9cc \ud328\ud134\uc5d0 \ub9e4\ubab0\ub418\uc11c\ub294 \uc548\ub41c\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud328\ud134\uc744 \ub9f9\ubaa9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548\ub418\uace0, \ud604\uc7ac\uc758 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub530\ub77c \ud328\ud134\uc744 \uc720\ub3d9\uc801\uc73c\ub85c \uc218\uc815\ud574\uac00\uba74\uc11c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,i.jsx)(n.br,{}),"\n","\ud56d\uc0c1 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uc0dd\uac01\ud558\uc790!"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:["\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134, GoF\uc758 \ub514\uc790\uc778 \ud328\ud134",(0,i.jsx)(n.br,{}),"\n","\ub514\uc790\uc778 \ud328\ud134\uacfc \ud504\ub808\uc784\uc6cc\ud06c, \uc624\ube0c\uc81d\ud2b8"]})]})}function d(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var i=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var a=i.createContext({}),o=function(e){var n=i.useContext(a),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var r=e.components,t=e.mdxType,l=e.originalType,a=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),u=o(r),h=t,j=u["".concat(a,".").concat(h)]||u[h]||p[h]||l;return r?i.createElement(j,s(s({ref:n},d),{},{components:r})):i.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"},28629:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite1-6117733e5244b235d9405ba72afb53ed.png"},33094:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite2-ac487a832bf12267cc91996ea3a5b9c7.png"},67922:(e,n,r)=>{r.d(n,{Z:()=>i});const i=r.p+"assets/images/composite3-016bf41863692b1f738bc89011687166.png"}}]); \ No newline at end of file diff --git a/assets/js/d65e25b7.04063c18.js b/assets/js/d65e25b7.d8647075.js similarity index 98% rename from assets/js/d65e25b7.04063c18.js rename to assets/js/d65e25b7.d8647075.js index 3416c3067..73f587aaf 100644 --- a/assets/js/d65e25b7.04063c18.js +++ b/assets/js/d65e25b7.d8647075.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7776],{60626:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>d});var r=t(85893),a=t(3905),i=t(74866),s=t(85162);const o={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",slug:"route-image-async-with-event",tags:["async","event"]},l=void 0,c={permalink:"/route-image-async-with-event",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",description:"\uc774\uc804 \uae00",date:"2023-08-13T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 13\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"event",permalink:"/tags/event"}],readingTime:11.2,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",slug:"route-image-async-with-event",tags:["async","event"]},unlisted:!1,prevItem:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/cloudwatch"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",permalink:"/route-image-implementation"}},u={authorsImageUrls:[]},d=[{value:"\uc774\uc804 \uae00",id:"\uc774\uc804-\uae00",level:2},{value:"\uac1c\uc694",id:"\uac1c\uc694",level:2},{value:"\uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120",id:"\uc8fc\uae30\ub2a5\uc758-\uc751\ub2f5\uc18d\ub3c4-\uac1c\uc120",level:3},{value:"\ud655\uc7a5\uc131 \ub300\ube44",id:"\ud655\uc7a5\uc131-\ub300\ube44",level:3},{value:"\ube44\ub3d9\uae30 \ucc98\ub9ac",id:"\ube44\ub3d9\uae30-\ucc98\ub9ac",level:2},{value:"\ube44\ub3d9\uae30 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc124\uc815",level:3},{value:"@Async \uc801\uc6a9",id:"async-\uc801\uc6a9",level:3},{value:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810",id:"\ube44\ub3d9\uae30-\ucc98\ub9ac\uc2dc-\ubb38\uc81c\uc810",level:3},{value:"\uc774\ubca4\ud2b8 \uc0ac\uc6a9",id:"\uc774\ubca4\ud2b8-\uc0ac\uc6a9",level:2},{value:"\uc774\ubca4\ud2b8 \ubc1c\ud589",id:"\uc774\ubca4\ud2b8-\ubc1c\ud589",level:3},{value:"\uc774\ubca4\ud2b8 \uad6c\ub3c5",id:"\uc774\ubca4\ud2b8-\uad6c\ub3c5",level:3},{value:"\ud14c\uc2a4\ud2b8",id:"\ud14c\uc2a4\ud2b8",level:3},{value:"\uacb0\uacfc",id:"\uacb0\uacfc",level:2},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",mermaid:"mermaid",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"\uc774\uc804-\uae00",children:"\uc774\uc804 \uae00"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"./route-image-intro",children:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"./route-image-implementation",children:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604"})]}),"\n",(0,r.jsx)(n.h2,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac \uc5ec\ud589\uc744 \ub9c8\uce58\ub294 \uacbd\uc6b0, \uac10\uc0c1\uc744 \uc0dd\uc131\ud558\ub294 \uacbd\uc6b0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \uc704\uce58 \uc815\ubcf4\uc758 \uac1c\uc218\uc5d0 \uc815\ube44\ub840\ud558\uc5ec \uc0dd\uc131 \uc2dc\uac04\uc774 \uc99d\uac00\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ube44\ub3d9\uae30\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uc5ec \uc0ac\uc6a9\uc790\uc758 \uacbd\ud5d8\uc744 \uac1c\uc120\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc8fc\uae30\ub2a5\uc758-\uc751\ub2f5\uc18d\ub3c4-\uac1c\uc120",children:"\uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120"}),"\n",(0,r.jsxs)(n.p,{children:["\uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc774 \uc8fc\uae30\ub2a5\uc774\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ubd80\uae30\ub2a5\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ud604\uc7ac \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc758 \uc751\ub2f5 \uc18d\ub3c4\uac00 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uc5ec\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc18c\uc694 \uc2dc\uac04\uc774 1\ucd08 \uc774\uc0c1 \uac78\ub9ac\ub294 \uacbd\uc6b0\uac00 \uc874\uc7ac\ud558\uae30\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uace0 \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131 \uae30\ub2a5\uc758 \uc751\ub2f5 \uc2dc\uac04\uc744 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc911\uc694\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ud655\uc7a5\uc131-\ub300\ube44",children:"\ud655\uc7a5\uc131 \ub300\ube44"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac 10\ubd84 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc11c\ubc84\uc5d0 \uc800\uc7a5\ud558\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc870\uae08 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uadf8\ub9ac\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 \uc5ec\ud589\uc5d0 \ub9ce\uc740 \uc704\uce58 \uc815\ubcf4\uac00 \uc800\uc7a5\ub420 \uc218\ubc16\uc5d0 \uc5c6\uace0 \ub530\ub77c\uc11c \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uac78\ub9ac\ub294 \uc2dc\uac04\uc774 \ub354 \uae38\uc5b4\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ucd94\ud6c4\uc5d0 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0\ub97c \ub300\ube44\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \ud569\ub2f9\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ube44\ub3d9\uae30-\ucc98\ub9ac",children:"\ube44\ub3d9\uae30 \ucc98\ub9ac"}),"\n",(0,r.jsx)(n.p,{children:"@Async\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uba54\uc11c\ub4dc\ub97c \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ub9cc\ub4e4 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\uc124\uc815",children:"\ube44\ub3d9\uae30 \uc124\uc815"}),"\n",(0,r.jsxs)(n.p,{children:["\uc0ac\uc6a9\ud558\uae30 \uc804\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c EnableAsync \uc124\uc815\uc744 \ud574\uc57c\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc124\uc815\uc744 \uc801\uc6a9\ud558\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc\uc5d0 @Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uae30\ub9cc \ud558\uba74 \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="AsyncConfig"',children:"@EnableAsync\n@Configuration\npublic class AsyncConfig {\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud560 \ub54c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ub808\ub4dc \ud480 \uc124\uc815\uc744 \ub530\ub85c \ud574\uc918\uc57c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ThreadPoolTaskExecutor\ub97c \ub530\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \uae30\ubcf8\uc801\uc73c\ub85c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uac00 \uc0dd\uc131\uc744 \ub3c4\uc640\uc900\ub2e4."}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.\n7.7. Task Execution and Scheduling, Spring Boot Docs"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"async-\uc801\uc6a9",children:"@Async \uc801\uc6a9"}),"\n",(0,r.jsx)(n.p,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\uc5d0 Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageGenerator"',children:"@Async\npublic void generate(\n List latitudes,\n List longitudes,\n List pointedLatitudes,\n List pointedLongitudes,\n Long tripId\n) {\n // \uc774\ubbf8\uc9c0 \uc0dd\uc131\n RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);\n Coordinates coordinates = Coordinates.of(latitudes, longitudes);\n Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);\n drawImage(coordinates, routeImageDrawer, pointedCoordinates);\n\n // \uc774\ubbf8\uc9c0 \uc800\uc7a5\n String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());\n\n // \uc790\uc6d0 \ud560\ub2f9 \ud574\uc81c\n routeImageDrawer.dispose();\n\n // \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac12 \ubcc0\uacbd\n Trip trip = tripRepository.findById(tripId)\n .orElseThrow();\n trip.changeRouteImageUrl(imageUrl);\n tripRepository.save(trip);\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\ucc98\ub9ac\uc2dc-\ubb38\uc81c\uc810",children:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uace0 \uc800\uc7a5 \ud6c4, \uc800\uc7a5 \uacbd\ub85c\ub97c DB\uc5d0 \ubc18\uc601\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ud615\ud0dc\uac00 \ub418\uba70 \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n trip[trip: \uc5ec\ud589 \uad00\ub828 \ud328\ud0a4\uc9c0] --\x3e draw[draw: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294 \ud328\ud0a4\uc9c0]\n draw --\x3e trip"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uacfc \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph draw\n\t\tdirection LR\n\t\tRG[RouteImageGenerator] -- DB \ubc18\uc601 \uc694\uccad --\x3e ILR[ImageLinkTripRepository]\n\tend\n subgraph trip\n\t\tdirection LR\n\t\tTS[TripService] -- \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e RG\n\t\tILRI[ImageLinkTripRepositoryImpl] -- \uad6c\ud604 --\x3e ILR\n\tend\n\n\ttrip --\x3e draw"}),"\n",(0,r.jsxs)(n.p,{children:["\ud328\ud0a4\uc9c0 \uac04 \uc758\uc874\uc131\uc740 \ud574\uacb0\ub418\uc5c8\uc9c0\ub9cc, \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5\uc744 \uc704\ud574 tripId\ub97c \ubc1b\uc544\uc57c\ud558\ub294 \ub4f1\uc758 \ub17c\ub9ac\uc801\uc778 \uc758\uc874\uc131\uc740 \uc544\uc9c1 \ud574\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uc774\ubca4\ud2b8-\uc0ac\uc6a9",children:"\uc774\ubca4\ud2b8 \uc0ac\uc6a9"}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uba74 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ube44\uad00\uc2ec\uc0ac(ex. \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131)\uc744 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\uc774\ubca4\ud2b8-\ubc1c\ud589",children:"\uc774\ubca4\ud2b8 \ubc1c\ud589"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 ApplicationEventPublisher \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c ApplicationContext\uac00 \uad6c\ud604\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="TripService & TripUpdateEvent"',children:"public void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {\n ...\n\n // \uc774\ubca4\ud2b8 \ubc1c\ud589\n applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));\n}\n\npublic record TripUpdateEvent(Long tripId) {\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \ub54c \ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc774 \uc911\uc694\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\ub294 \ub3c4\uba54\uc778\uc758 \ud589\uc704\ub97c \ub2f4\uace0 \uc788\ub294 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589(ex. RouteImageGenerateEvent)\ud55c\ub2e4\uba74 \ub17c\ub9ac\uc801\uc778 \uc758\uc874 \uad00\uacc4\uac00 \ub0a8\uc544\uc788\uae30\uc5d0 \uc774\ubca4\ud2b8\ub97c \uc801\uc808\ud788 \uc0ac\uc6a9\ud588\ub2e4\uace0 \ubcf4\uae30 \uc5b4\ub835\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc740 \uc8fc\uae30\ub2a5\uc774 \uc5b4\ub5a4 \ud589\uc704(ex. TripUpdateEvent)\ub97c \ud588\ub294\uc9c0\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 \uc774\ubca4\ud2b8\uba85\uc73c\ub85c \ubc1c\ud589\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc774\ubca4\ud2b8-\uad6c\ub3c5",children:"\uc774\ubca4\ud2b8 \uad6c\ub3c5"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc2e4\ud589\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\uae30 \uc704\ud558\uc5ec ",(0,r.jsx)(n.code,{children:"@Async"})," \uc560\ub108\ud14c\uc774\uc158\uc744 \uc801\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ubca4\ud2b8\uc758 \uad6c\ub3c5\uc740 \uc5ec\ud589\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc\ub420 \ub54c \uc5ec\ud589\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 ",(0,r.jsx)(n.code,{children:"@TransactionalEventListener"}),"\ub97c \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,r.jsxs)(n.admonition,{title:"TransactionPhase \uc124\uc815",type:"note",children:[(0,r.jsx)(n.p,{children:"TransactionPhase\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \uc774\ubca4\ud2b8\ub97c \uc5b4\ub5a4 \ub2e8\uacc4\uc5d0\uc11c \uc218\uc2e0\ud558\uace0 \ucc98\ub9ac\ud560\uc9c0\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),(0,r.jsxs)(n.p,{children:["AFTER_COMMIT(\uae30\ubcf8\uac12): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ucee4\ubc0b \ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","AFTER_ROLLBACK: \ud2b8\ub79c\uc7ad\uc158\uc774 \ub864\ubc31\ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","AFTER_COMPLETION: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub610\ub294 \ub864\ubc31 \ub418\uc5c8\uc744 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","BEFORE_COMMIT: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub418\uae30 \uc804 \uc774\ubca4\ud2b8 \uc2e4\ud589"]})]}),"\n",(0,r.jsx)(n.p,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uae30 \uc704\ud574 @Transactional \uc560\ub108\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="TripUpdateEventHandler"',children:"@Component\npublic class TripUpdateEventHandler {\n\n private final RouteImageGenerator routeImageGenerator;\n private final TripRepository tripRepository;\n\n public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {\n this.routeImageGenerator = routeImageGenerator;\n this.tripRepository = tripRepository;\n }\n\n @Async\n @TransactionalEventListener(phase = AFTER_COMMIT)\n public void handle(TripUpdateEvent tripUpdateEvent) {\n Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());\n\n String imageUrl = routeImageGenerator.generate(\n trip.getLatitudes(),\n trip.getLongitudes(),\n trip.getPointedLatitudes(),\n trip.getPointedLongitudes()\n );\n\n trip.changeRouteImageUrl(imageUrl);\n tripRepository.save(trip);\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c\uc368 \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ubb38\uc81c\uac00 \ub2e4\uc74c\uacfc \uac19\uc774 \ud574\uacb0\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c \uc8fc\uae30\ub2a5\uacfc \ubd80\uae30\ub2a5\uc744 \ubd84\ub9ac\ud568\uc73c\ub85c\uc368 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uc5c8\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n subgraph trip\n TripServcie -- \ubc1c\ud589 --\x3e TripUpdateEvent\n TripRepository\n end\n\n subgraph draw\n TripUpdateEventHandler -- \uad6c\ub3c5 \ud6c4 \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e TripUpdateEvent\n TripUpdateEventHandler -- \uc0dd\uc131\ub41c \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5 --\x3e TripRepository\n end"}),"\n",(0,r.jsx)(n.h3,{id:"\ud14c\uc2a4\ud2b8",children:"\ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsx)(n.p,{children:"\ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \ubc29\ubc95\uc774 \uc788\ub2e4."}),"\n","\n","\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(s.Z,{value:"\ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \uc885\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30 \ud6c4 \uac80\uc99d",label:"\ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \uc885\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30 \ud6c4 \uac80\uc99d",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@SpringBootTest\npublic class TripUpdateEventHandlerIntegrationTest {\n\n ...\n\n @Test\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\n // given\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\n .willReturn(\uc5ec\ud589());\n\n // when\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\n\n // then\n then(routeImageGenerator)\n .should(Mockito.timeout(5000).times(1))\n .generate(any(), any(), any(), any());\n }\n}\n"})})}),(0,r.jsx)(s.Z,{value:"\ud14c\uc2a4\ud2b8 \ud560 \ub54c\ub9cc \ube44\ub3d9\uae30\ub97c \ub3d9\uae30\ub85c \ubcc0\uacbd\ud558\uc5ec \uac80\uc99d",label:"\ud14c\uc2a4\ud2b8 \ud560 \ub54c\ub9cc \ube44\ub3d9\uae30\ub97c \ub3d9\uae30\ub85c \ubcc0\uacbd\ud558\uc5ec \uac80\uc99d",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@ContextConfiguration(classes = TestSyncConfig.class)\n@SpringBootTest\npublic class TripUpdateEventHandlerIntegrationTest {\n\n ...\n\n @Test\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\n // given\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\n .willReturn(\uc5ec\ud589());\n\n // when\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\n\n // then\n then(routeImageGenerator)\n .should(times(1))\n .generate(any(), any(), any(), any());\n }\n}\n"})})})]}),"\n",(0,r.jsxs)(n.p,{children:["\ucc98\uc74c\uc5d0\ub294 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub9cc \ub3d9\uae30\ub85c \uc124\uc815 \ud6c4 \uac80\uc99d\ud558\ub824\uace0 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud1b5\ud569 \ud14c\uc2a4\ud2b8\uc5d0\uc120 ",(0,r.jsx)(n.code,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1 \uc885\ub8cc\ub418\uc5c8\uc744 \ub54c \ube44\ub3d9\uae30\ub85c \uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0"})," \uac80\uc99d\uc774 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc885\uc801\uc73c\ub85c ",(0,r.jsx)(n.code,{children:"Mockito.timeout"})," \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \ud1b5\uacfc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uacb0\uacfc",children:"\uacb0\uacfc"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"./time.png",src:t(89297).Z+"",width:"1682",height:"678"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc704 \uc751\ub2f5 \uc2dc\uac04\uc740 \uc704\uce58 \uc815\ubcf4 1000\uac1c\ub97c \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud55c \uac12\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc751\ub2f5 \uc2dc\uac04\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ud3ec\ud568\ub418\uc9c0 \uc54a\uc544\uc11c \uc131\ub2a5\uc774 \uac1c\uc120\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.task-execution-and-scheduling",children:"7.7. Task Execution and Scheduling, Spring Boot Docs"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.baeldung.com/spring-events",children:"Spring Events, Baeldung"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://techblog.woowahan.com/7835/",children:"\ud68c\uc6d0\uc2dc\uc2a4\ud15c \uc774\ubca4\ud2b8\uae30\ubc18 \uc544\ud0a4\ud14d\ucc98 \uad6c\ucd95\ud558\uae30"})]})]})}function h(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),c=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),p=c(t),h=a,g=p["".concat(l,".").concat(h)]||p[h]||u[h]||i;return t?r.createElement(g,s(s({ref:n},d),{},{components:t})):r.createElement(g,s({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>s});t(67294);var r=t(86010);const a={tabItem:"tabItem_Ymn6"};var i=t(85893);function s(e){let{children:n,hidden:t,className:s}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.Z)(a.tabItem,s),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>T});var r=t(67294),a=t(86010),i=t(12466),s=t(16550),o=t(20469),l=t(91980),c=t(67392),u=t(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:a}}=e;return{value:n,label:t,attributes:r,default:a}}))}(t);return function(e){const n=(0,c.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function g(e){let{queryString:n=!1,groupId:t}=e;const a=(0,s.k6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function m(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=p(e),[s,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[c,d]=g({queryString:t,groupId:a}),[m,b]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,u.Nk)(t);return[a,(0,r.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),v=(()=>{const e=c??m;return h({value:e,tabValues:i})?e:null})();(0,o.Z)((()=>{v&&l(v)}),[v]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!h({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),b(e)}),[d,b,i]),tabValues:i}}var b=t(72389);const v={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=t(85893);function j(e){let{className:n,block:t,selectedValue:r,selectValue:s,tabValues:o}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,i.o5)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),a=o[t].value;a!==r&&(c(n),s(a))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...i,className:(0,a.Z)("tabs__item",v.tabItem,i?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function f(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function y(e){const n=m(e);return(0,x.jsxs)("div",{className:(0,a.Z)("tabs-container",v.tabList),children:[(0,x.jsx)(j,{...e,...n}),(0,x.jsx)(f,{...e,...n})]})}function T(e){const n=(0,b.Z)();return(0,x.jsx)(y,{...e,children:d(e.children)},String(n))}},89297:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/time-8bef9a6cf2dcace85f12ae5624da94f5.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7776],{60626:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>d});var r=t(85893),a=t(3905),i=t(74866),s=t(85162);const o={title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",slug:"route-image-async-with-event",tags:["async","event"]},l=void 0,c={permalink:"/route-image-async-with-event",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",description:"\uc774\uc804 \uae00",date:"2023-08-13T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 13\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"event",permalink:"/tags/event"}],readingTime:11.2,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",slug:"route-image-async-with-event",tags:["async","event"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604",permalink:"/route-image-implementation"},nextItem:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/cloudwatch"}},u={authorsImageUrls:[]},d=[{value:"\uc774\uc804 \uae00",id:"\uc774\uc804-\uae00",level:2},{value:"\uac1c\uc694",id:"\uac1c\uc694",level:2},{value:"\uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120",id:"\uc8fc\uae30\ub2a5\uc758-\uc751\ub2f5\uc18d\ub3c4-\uac1c\uc120",level:3},{value:"\ud655\uc7a5\uc131 \ub300\ube44",id:"\ud655\uc7a5\uc131-\ub300\ube44",level:3},{value:"\ube44\ub3d9\uae30 \ucc98\ub9ac",id:"\ube44\ub3d9\uae30-\ucc98\ub9ac",level:2},{value:"\ube44\ub3d9\uae30 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc124\uc815",level:3},{value:"@Async \uc801\uc6a9",id:"async-\uc801\uc6a9",level:3},{value:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810",id:"\ube44\ub3d9\uae30-\ucc98\ub9ac\uc2dc-\ubb38\uc81c\uc810",level:3},{value:"\uc774\ubca4\ud2b8 \uc0ac\uc6a9",id:"\uc774\ubca4\ud2b8-\uc0ac\uc6a9",level:2},{value:"\uc774\ubca4\ud2b8 \ubc1c\ud589",id:"\uc774\ubca4\ud2b8-\ubc1c\ud589",level:3},{value:"\uc774\ubca4\ud2b8 \uad6c\ub3c5",id:"\uc774\ubca4\ud2b8-\uad6c\ub3c5",level:3},{value:"\ud14c\uc2a4\ud2b8",id:"\ud14c\uc2a4\ud2b8",level:3},{value:"\uacb0\uacfc",id:"\uacb0\uacfc",level:2},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",mermaid:"mermaid",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"\uc774\uc804-\uae00",children:"\uc774\uc804 \uae00"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"./route-image-intro",children:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"./route-image-implementation",children:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604"})]}),"\n",(0,r.jsx)(n.h2,{id:"\uac1c\uc694",children:"\uac1c\uc694"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac \uc5ec\ud589\uc744 \ub9c8\uce58\ub294 \uacbd\uc6b0, \uac10\uc0c1\uc744 \uc0dd\uc131\ud558\ub294 \uacbd\uc6b0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \uc704\uce58 \uc815\ubcf4\uc758 \uac1c\uc218\uc5d0 \uc815\ube44\ub840\ud558\uc5ec \uc0dd\uc131 \uc2dc\uac04\uc774 \uc99d\uac00\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ube44\ub3d9\uae30\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uc5ec \uc0ac\uc6a9\uc790\uc758 \uacbd\ud5d8\uc744 \uac1c\uc120\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc8fc\uae30\ub2a5\uc758-\uc751\ub2f5\uc18d\ub3c4-\uac1c\uc120",children:"\uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120"}),"\n",(0,r.jsxs)(n.p,{children:["\uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc774 \uc8fc\uae30\ub2a5\uc774\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ubd80\uae30\ub2a5\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \ud604\uc7ac \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc758 \uc751\ub2f5 \uc18d\ub3c4\uac00 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uc5ec\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc18c\uc694 \uc2dc\uac04\uc774 1\ucd08 \uc774\uc0c1 \uac78\ub9ac\ub294 \uacbd\uc6b0\uac00 \uc874\uc7ac\ud558\uae30\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uace0 \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131 \uae30\ub2a5\uc758 \uc751\ub2f5 \uc2dc\uac04\uc744 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc911\uc694\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ud655\uc7a5\uc131-\ub300\ube44",children:"\ud655\uc7a5\uc131 \ub300\ube44"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac 10\ubd84 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc11c\ubc84\uc5d0 \uc800\uc7a5\ud558\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc870\uae08 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uadf8\ub9ac\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 \uc5ec\ud589\uc5d0 \ub9ce\uc740 \uc704\uce58 \uc815\ubcf4\uac00 \uc800\uc7a5\ub420 \uc218\ubc16\uc5d0 \uc5c6\uace0 \ub530\ub77c\uc11c \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uac78\ub9ac\ub294 \uc2dc\uac04\uc774 \ub354 \uae38\uc5b4\uc9c8 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ucd94\ud6c4\uc5d0 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0\ub97c \ub300\ube44\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \ud569\ub2f9\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ube44\ub3d9\uae30-\ucc98\ub9ac",children:"\ube44\ub3d9\uae30 \ucc98\ub9ac"}),"\n",(0,r.jsx)(n.p,{children:"@Async\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uba54\uc11c\ub4dc\ub97c \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ub9cc\ub4e4 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\uc124\uc815",children:"\ube44\ub3d9\uae30 \uc124\uc815"}),"\n",(0,r.jsxs)(n.p,{children:["\uc0ac\uc6a9\ud558\uae30 \uc804\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c EnableAsync \uc124\uc815\uc744 \ud574\uc57c\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc124\uc815\uc744 \uc801\uc6a9\ud558\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc\uc5d0 @Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uae30\ub9cc \ud558\uba74 \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="AsyncConfig"',children:"@EnableAsync\n@Configuration\npublic class AsyncConfig {\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud560 \ub54c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ub808\ub4dc \ud480 \uc124\uc815\uc744 \ub530\ub85c \ud574\uc918\uc57c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ThreadPoolTaskExecutor\ub97c \ub530\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \uae30\ubcf8\uc801\uc73c\ub85c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uac00 \uc0dd\uc131\uc744 \ub3c4\uc640\uc900\ub2e4."}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.\n7.7. Task Execution and Scheduling, Spring Boot Docs"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"async-\uc801\uc6a9",children:"@Async \uc801\uc6a9"}),"\n",(0,r.jsx)(n.p,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\uc5d0 Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud55c\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="RouteImageGenerator"',children:"@Async\npublic void generate(\n List latitudes,\n List longitudes,\n List pointedLatitudes,\n List pointedLongitudes,\n Long tripId\n) {\n // \uc774\ubbf8\uc9c0 \uc0dd\uc131\n RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);\n Coordinates coordinates = Coordinates.of(latitudes, longitudes);\n Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);\n drawImage(coordinates, routeImageDrawer, pointedCoordinates);\n\n // \uc774\ubbf8\uc9c0 \uc800\uc7a5\n String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());\n\n // \uc790\uc6d0 \ud560\ub2f9 \ud574\uc81c\n routeImageDrawer.dispose();\n\n // \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac12 \ubcc0\uacbd\n Trip trip = tripRepository.findById(tripId)\n .orElseThrow();\n trip.changeRouteImageUrl(imageUrl);\n tripRepository.save(trip);\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\ucc98\ub9ac\uc2dc-\ubb38\uc81c\uc810",children:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810"}),"\n",(0,r.jsxs)(n.p,{children:["\ud604\uc7ac \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uace0 \uc800\uc7a5 \ud6c4, \uc800\uc7a5 \uacbd\ub85c\ub97c DB\uc5d0 \ubc18\uc601\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ud615\ud0dc\uac00 \ub418\uba70 \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n trip[trip: \uc5ec\ud589 \uad00\ub828 \ud328\ud0a4\uc9c0] --\x3e draw[draw: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294 \ud328\ud0a4\uc9c0]\n draw --\x3e trip"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uacfc \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph draw\n\t\tdirection LR\n\t\tRG[RouteImageGenerator] -- DB \ubc18\uc601 \uc694\uccad --\x3e ILR[ImageLinkTripRepository]\n\tend\n subgraph trip\n\t\tdirection LR\n\t\tTS[TripService] -- \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e RG\n\t\tILRI[ImageLinkTripRepositoryImpl] -- \uad6c\ud604 --\x3e ILR\n\tend\n\n\ttrip --\x3e draw"}),"\n",(0,r.jsxs)(n.p,{children:["\ud328\ud0a4\uc9c0 \uac04 \uc758\uc874\uc131\uc740 \ud574\uacb0\ub418\uc5c8\uc9c0\ub9cc, \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5\uc744 \uc704\ud574 tripId\ub97c \ubc1b\uc544\uc57c\ud558\ub294 \ub4f1\uc758 \ub17c\ub9ac\uc801\uc778 \uc758\uc874\uc131\uc740 \uc544\uc9c1 \ud574\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uc774\ubca4\ud2b8-\uc0ac\uc6a9",children:"\uc774\ubca4\ud2b8 \uc0ac\uc6a9"}),"\n",(0,r.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uba74 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ube44\uad00\uc2ec\uc0ac(ex. \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131)\uc744 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\uc774\ubca4\ud2b8-\ubc1c\ud589",children:"\uc774\ubca4\ud2b8 \ubc1c\ud589"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 ApplicationEventPublisher \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c ApplicationContext\uac00 \uad6c\ud604\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="TripService & TripUpdateEvent"',children:"public void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {\n ...\n\n // \uc774\ubca4\ud2b8 \ubc1c\ud589\n applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));\n}\n\npublic record TripUpdateEvent(Long tripId) {\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \ub54c \ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc774 \uc911\uc694\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\ub294 \ub3c4\uba54\uc778\uc758 \ud589\uc704\ub97c \ub2f4\uace0 \uc788\ub294 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589(ex. RouteImageGenerateEvent)\ud55c\ub2e4\uba74 \ub17c\ub9ac\uc801\uc778 \uc758\uc874 \uad00\uacc4\uac00 \ub0a8\uc544\uc788\uae30\uc5d0 \uc774\ubca4\ud2b8\ub97c \uc801\uc808\ud788 \uc0ac\uc6a9\ud588\ub2e4\uace0 \ubcf4\uae30 \uc5b4\ub835\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc740 \uc8fc\uae30\ub2a5\uc774 \uc5b4\ub5a4 \ud589\uc704(ex. TripUpdateEvent)\ub97c \ud588\ub294\uc9c0\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 \uc774\ubca4\ud2b8\uba85\uc73c\ub85c \ubc1c\ud589\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc774\ubca4\ud2b8-\uad6c\ub3c5",children:"\uc774\ubca4\ud2b8 \uad6c\ub3c5"}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc2e4\ud589\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\uae30 \uc704\ud558\uc5ec ",(0,r.jsx)(n.code,{children:"@Async"})," \uc560\ub108\ud14c\uc774\uc158\uc744 \uc801\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ubca4\ud2b8\uc758 \uad6c\ub3c5\uc740 \uc5ec\ud589\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc\ub420 \ub54c \uc5ec\ud589\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 ",(0,r.jsx)(n.code,{children:"@TransactionalEventListener"}),"\ub97c \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,r.jsxs)(n.admonition,{title:"TransactionPhase \uc124\uc815",type:"note",children:[(0,r.jsx)(n.p,{children:"TransactionPhase\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \uc774\ubca4\ud2b8\ub97c \uc5b4\ub5a4 \ub2e8\uacc4\uc5d0\uc11c \uc218\uc2e0\ud558\uace0 \ucc98\ub9ac\ud560\uc9c0\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),(0,r.jsxs)(n.p,{children:["AFTER_COMMIT(\uae30\ubcf8\uac12): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ucee4\ubc0b \ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","AFTER_ROLLBACK: \ud2b8\ub79c\uc7ad\uc158\uc774 \ub864\ubc31\ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","AFTER_COMPLETION: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub610\ub294 \ub864\ubc31 \ub418\uc5c8\uc744 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589",(0,r.jsx)(n.br,{}),"\n","BEFORE_COMMIT: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub418\uae30 \uc804 \uc774\ubca4\ud2b8 \uc2e4\ud589"]})]}),"\n",(0,r.jsx)(n.p,{children:"\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uae30 \uc704\ud574 @Transactional \uc560\ub108\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",metastring:'title="TripUpdateEventHandler"',children:"@Component\npublic class TripUpdateEventHandler {\n\n private final RouteImageGenerator routeImageGenerator;\n private final TripRepository tripRepository;\n\n public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {\n this.routeImageGenerator = routeImageGenerator;\n this.tripRepository = tripRepository;\n }\n\n @Async\n @TransactionalEventListener(phase = AFTER_COMMIT)\n public void handle(TripUpdateEvent tripUpdateEvent) {\n Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());\n\n String imageUrl = routeImageGenerator.generate(\n trip.getLatitudes(),\n trip.getLongitudes(),\n trip.getPointedLatitudes(),\n trip.getPointedLongitudes()\n );\n\n trip.changeRouteImageUrl(imageUrl);\n tripRepository.save(trip);\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c\uc368 \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ubb38\uc81c\uac00 \ub2e4\uc74c\uacfc \uac19\uc774 \ud574\uacb0\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c \uc8fc\uae30\ub2a5\uacfc \ubd80\uae30\ub2a5\uc744 \ubd84\ub9ac\ud568\uc73c\ub85c\uc368 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uc5c8\ub2e4."]}),"\n",(0,r.jsx)(n.mermaid,{value:"graph LR\n subgraph trip\n TripServcie -- \ubc1c\ud589 --\x3e TripUpdateEvent\n TripRepository\n end\n\n subgraph draw\n TripUpdateEventHandler -- \uad6c\ub3c5 \ud6c4 \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e TripUpdateEvent\n TripUpdateEventHandler -- \uc0dd\uc131\ub41c \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5 --\x3e TripRepository\n end"}),"\n",(0,r.jsx)(n.h3,{id:"\ud14c\uc2a4\ud2b8",children:"\ud14c\uc2a4\ud2b8"}),"\n",(0,r.jsx)(n.p,{children:"\ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \ubc29\ubc95\uc774 \uc788\ub2e4."}),"\n","\n","\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(s.Z,{value:"\ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \uc885\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30 \ud6c4 \uac80\uc99d",label:"\ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \uc885\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30 \ud6c4 \uac80\uc99d",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@SpringBootTest\npublic class TripUpdateEventHandlerIntegrationTest {\n\n ...\n\n @Test\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\n // given\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\n .willReturn(\uc5ec\ud589());\n\n // when\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\n\n // then\n then(routeImageGenerator)\n .should(Mockito.timeout(5000).times(1))\n .generate(any(), any(), any(), any());\n }\n}\n"})})}),(0,r.jsx)(s.Z,{value:"\ud14c\uc2a4\ud2b8 \ud560 \ub54c\ub9cc \ube44\ub3d9\uae30\ub97c \ub3d9\uae30\ub85c \ubcc0\uacbd\ud558\uc5ec \uac80\uc99d",label:"\ud14c\uc2a4\ud2b8 \ud560 \ub54c\ub9cc \ube44\ub3d9\uae30\ub97c \ub3d9\uae30\ub85c \ubcc0\uacbd\ud558\uc5ec \uac80\uc99d",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@ContextConfiguration(classes = TestSyncConfig.class)\n@SpringBootTest\npublic class TripUpdateEventHandlerIntegrationTest {\n\n ...\n\n @Test\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\n // given\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\n .willReturn(\uc5ec\ud589());\n\n // when\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\n\n // then\n then(routeImageGenerator)\n .should(times(1))\n .generate(any(), any(), any(), any());\n }\n}\n"})})})]}),"\n",(0,r.jsxs)(n.p,{children:["\ucc98\uc74c\uc5d0\ub294 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub9cc \ub3d9\uae30\ub85c \uc124\uc815 \ud6c4 \uac80\uc99d\ud558\ub824\uace0 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud1b5\ud569 \ud14c\uc2a4\ud2b8\uc5d0\uc120 ",(0,r.jsx)(n.code,{children:"\ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1 \uc885\ub8cc\ub418\uc5c8\uc744 \ub54c \ube44\ub3d9\uae30\ub85c \uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0"})," \uac80\uc99d\uc774 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc885\uc801\uc73c\ub85c ",(0,r.jsx)(n.code,{children:"Mockito.timeout"})," \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \ud1b5\uacfc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uacb0\uacfc",children:"\uacb0\uacfc"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"./time.png",src:t(89297).Z+"",width:"1682",height:"678"})}),"\n",(0,r.jsxs)(n.p,{children:["\uc704 \uc751\ub2f5 \uc2dc\uac04\uc740 \uc704\uce58 \uc815\ubcf4 1000\uac1c\ub97c \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud55c \uac12\uc774\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc751\ub2f5 \uc2dc\uac04\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ud3ec\ud568\ub418\uc9c0 \uc54a\uc544\uc11c \uc131\ub2a5\uc774 \uac1c\uc120\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.task-execution-and-scheduling",children:"7.7. Task Execution and Scheduling, Spring Boot Docs"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.baeldung.com/spring-events",children:"Spring Events, Baeldung"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://techblog.woowahan.com/7835/",children:"\ud68c\uc6d0\uc2dc\uc2a4\ud15c \uc774\ubca4\ud2b8\uae30\ubc18 \uc544\ud0a4\ud14d\ucc98 \uad6c\ucd95\ud558\uae30"})]})]})}function h(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),c=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),p=c(t),h=a,g=p["".concat(l,".").concat(h)]||p[h]||u[h]||i;return t?r.createElement(g,s(s({ref:n},d),{},{components:t})):r.createElement(g,s({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>s});t(67294);var r=t(86010);const a={tabItem:"tabItem_Ymn6"};var i=t(85893);function s(e){let{children:n,hidden:t,className:s}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.Z)(a.tabItem,s),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>T});var r=t(67294),a=t(86010),i=t(12466),s=t(16550),o=t(20469),l=t(91980),c=t(67392),u=t(50012);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:a}}=e;return{value:n,label:t,attributes:r,default:a}}))}(t);return function(e){const n=(0,c.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function g(e){let{queryString:n=!1,groupId:t}=e;const a=(0,s.k6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function m(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=p(e),[s,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[c,d]=g({queryString:t,groupId:a}),[m,b]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,u.Nk)(t);return[a,(0,r.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),v=(()=>{const e=c??m;return h({value:e,tabValues:i})?e:null})();(0,o.Z)((()=>{v&&l(v)}),[v]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!h({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),b(e)}),[d,b,i]),tabValues:i}}var b=t(72389);const v={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=t(85893);function j(e){let{className:n,block:t,selectedValue:r,selectValue:s,tabValues:o}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,i.o5)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),a=o[t].value;a!==r&&(c(n),s(a))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...i,className:(0,a.Z)("tabs__item",v.tabItem,i?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function f(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function y(e){const n=m(e);return(0,x.jsxs)("div",{className:(0,a.Z)("tabs-container",v.tabList),children:[(0,x.jsx)(j,{...e,...n}),(0,x.jsx)(f,{...e,...n})]})}function T(e){const n=(0,b.Z)();return(0,x.jsx)(y,{...e,children:d(e.children)},String(n))}},89297:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/time-8bef9a6cf2dcace85f12ae5624da94f5.png"}}]); \ No newline at end of file diff --git a/assets/js/d7955594.3de2f6cf.js b/assets/js/d7955594.5a25bd6d.js similarity index 98% rename from assets/js/d7955594.3de2f6cf.js rename to assets/js/d7955594.5a25bd6d.js index b10e33471..46be370e7 100644 --- a/assets/js/d7955594.3de2f6cf.js +++ b/assets/js/d7955594.5a25bd6d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[588],{18751:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>c,default:()=>m,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var r=t(85893),a=t(3905),i=t(74866),l=t(85162);const o={title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",slug:"custom-jdbc-template",tags:["JDBC","Java"]},c=void 0,s={permalink:"/custom-jdbc-template",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",source:"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",description:"\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.",date:"2023-04-02T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 2\uc77c",tags:[{label:"JDBC",permalink:"/tags/jdbc"},{label:"Java",permalink:"/tags/java"}],readingTime:9.025,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",slug:"custom-jdbc-template",tags:["JDBC","Java"]},unlisted:!1,prevItem:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",permalink:"/java-class-file"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",permalink:"/woowacourse-level1-retrospective"}},u={authorsImageUrls:[]},p=[{value:"\uae30\uc874 \ucf54\ub4dc",id:"\uae30\uc874-\ucf54\ub4dc",level:3},{value:"SELECT, DELETE \uc911\ubcf5 \uc81c\uac70",id:"select-delete-\uc911\ubcf5-\uc81c\uac70",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---1-\ucf5c\ubc31\uc744-\uc704\ud55c-\uc778\ud130\ud398\uc774\uc2a4-\uc815\uc758",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---2-\ub2e8\uac74-\uc870\ud68c",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---3-\ub2e4\uac74-\uc870\ud68c",level:3},{value:"\uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30",id:"\uc81c\ub124\ub9ad-\uc0ac\uc6a9\ud558\uae30",level:3},{value:"\uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30",id:"\uba54\uc11c\ub4dc-\ubd84\ub9ac\ud55c-\ubd80\ubd84-\ud074\ub798\uc2a4\ub85c-\ubd84\ub9ac\ud558\uae30--optional-\uc0ac\uc6a9\ud558\uae30",level:3}];function d(e){const n={admonition:"admonition",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774 \ub54c JDBC\ub97c \uc0ac\uc6a9\ud560 \ub54c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ucee4\ub125\uc158\uc744 \uc5bb\uace0, try-with-resource\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc774 \ubc18\ubcf5\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc774\uc6a9\ud558\uc5ec \ub098\ub9cc\uc758 JdbcTemplate\uc744 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uae30\uc874-\ucf54\ub4dc",children:"\uae30\uc874 \ucf54\ub4dc"}),"\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(l.Z,{value:"User",label:"User",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public class User {\n private final int id;\n private final String name;\n\n public User(final int id, final String name) {\n this.id = id;\n this.name = name;\n }\n\n public int getId() {\n return id;\n }\n\n public String getName() {\n return name;\n }\n}\n"})})}),(0,r.jsx)(l.Z,{value:"UserDao",label:"UserDao",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class UserDao {\n private final ConnectionPool connectionPool;\n\n public UserDao(final ConnectionPool connectionPool) {\n this.connectionPool = connectionPool;\n }\n\n public void insert(final String name) {\n final Connection connection = connectionPool.getConnection();\n final String query = "INSERT INTO User (name) VALUES (?)";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setString(1, name);\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public void delete(final int userId) {\n final Connection connection = connectionPool.getConnection();\n final String query = "DELETE FROM user WHERE id = ?";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setInt(1, userId);\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public User findById(final int userId) {\n final Connection connection = connectionPool.getConnection();\n final String query = "SELECT * FROM user WHERE id = ?";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setInt(1, userId);\n final ResultSet resultSet = preparedStatement.executeQuery();\n if (resultSet.next()) {\n return new User(\n resultSet.getInt("id"),\n resultSet.getString("name")\n );\n }\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n return null;\n }\n\n public List findAll() {\n final Connection connection = connectionPool.getConnection();\n final String query = "SELECT * FROM user";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n final ResultSet resultSet = preparedStatement.executeQuery();\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(new User(\n resultSet.getInt("id"),\n resultSet.getString("name")\n ));\n }\n return result;\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n}\n'})})}),(0,r.jsx)(l.Z,{value:"ConnectionPool",label:"ConnectionPool",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class ConnectionPool {\n private static final String SERVER = "localhost:13306";\n private static final String DATABASE = "chess";\n private static final String OPTION = "?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";\n private static final String URL = "jdbc:mysql://" + SERVER + "/" + DATABASE + OPTION;\n private static final String USERNAME = "root";\n private static final String PASSWORD = "root";\n\n private final AtomicInteger index = new AtomicInteger();\n private final List connections;\n\n public ConnectionPool(final int connectionCount) {\n connections = generateConnections(connectionCount);\n }\n\n private List generateConnections(final int connectionCount) {\n return Stream.generate(this::generateConnection)\n .limit(connectionCount)\n .collect(toList());\n }\n\n private Connection generateConnection() {\n try {\n return DriverManager.getConnection(URL, USERNAME, PASSWORD);\n } catch (SQLException e) {\n throw new IllegalStateException("\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.");\n }\n }\n\n public Connection getConnection() {\n int currentIndex = index.getAndIncrement();\n return connections.get(currentIndex % connections.size());\n }\n}\n'})})})]}),"\n",(0,r.jsx)(n.h3,{id:"select-delete-\uc911\ubcf5-\uc81c\uac70",children:"SELECT, DELETE \uc911\ubcf5 \uc81c\uac70"}),"\n",(0,r.jsxs)(n.p,{children:["\ubcc0\ud558\uc9c0 \uc54a\ub294 \ubd80\ubd84: try-with-resource, preparedStatement\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84, executeUpdate\ub85c \uc2e4\ud589 \ub4f1\ub4f1",(0,r.jsx)(n.br,{}),"\n","\ubcc0\ud558\ub294 \ubd80\ubd84: SQL Query, \ub9e4\uac1c\ubcc0\uc218"]}),"\n",(0,r.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\ub294 \ubd80\ubd84\uc744 \ubd84\ub9ac\ud558\uace0 \uac00\ubcc0\uc778\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 SELECT\uc640 DELETE\uc758 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public void insert(final String name) {\n final String query = "INSERT INTO User (name) VALUES (?)";\n executeUpdate(query, name);\n}\n\npublic void delete(final int userId) {\n final String query = "DELETE FROM user WHERE user_id = ?";\n executeUpdate(query, userId);\n}\n\nprivate void executeUpdate(final String query, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---1-\ucf5c\ubc31\uc744-\uc704\ud55c-\uc778\ud130\ud398\uc774\uc2a4-\uc815\uc758",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758"}),"\n",(0,r.jsxs)(n.p,{children:["\uc870\ud68c\ub294 INSERT, DELETE\uc640 \ub2ec\ub9ac \uac12\uc744 \ubc18\ud658\ubc1b\uc544\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0 \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774 \ub54c \ucf5c\ubc31\uc774\ub77c\ub294 \uac83\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsxs)(n.admonition,{title:"\ucf5c\ubc31(Callback)",type:"note",children:[(0,r.jsxs)(n.p,{children:["\ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \ucf5c\ubc31\uc740 \ub2e4\ub978 \ucf54\ub4dc\uc758 \uc778\uc218\ub85c \ub118\uaca8\uc8fc\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ucf54\ub4dc\ub97c \ub73b\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\ubc14\uc5d0\uc11c\ub294 \ub78c\ub2e4\ub098 \uc775\uba85 \ud074\ub798\uc2a4\ub97c \ub118\uaca8\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),(0,r.jsx)(n.mermaid,{value:"flowchart LR\n \ud074\ub77c\uc774\uc5b8\ud2b8 -- \ucf5c\ubc31\uc804\ub2ec --\x3e \uba54\uc11c\ub4dc\n \uba54\uc11c\ub4dc -- \ub0b4\ubd80\ud638\ucd9c --\x3e \uc804\ub2ec\ubc1b\uc740\ucf5c\ubc31"})]}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uc870\ud68c\ud558\uace0, \ud574\ub2f9 \uac12\uc744 \uac1d\uccb4\ub85c \ub9e4\ud551\ud558\uc5ec \uac12\uc744 \ubc18\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","executeQuery\ub85c \uc870\ud68c\ud55c \uac12\uc740 ResultSet \uc548\uc5d0 \ub4e4\uc5b4\uac00\uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ub97c \uc6d0\ud558\ub294 \ud0c0\uc785\uc758 \uac12\uc73c\ub85c \ubcc0\ud658\ud574\uc57c\ud558\ub2c8 \uc77c\ub2e8 \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface RowMapper {\n User mapRow(final ResultSet resultSet) throws SQLException;\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---2-\ub2e8\uac74-\uc870\ud68c",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c"}),"\n",(0,r.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c \uc815\uc758\ud55c RowMapper\ub97c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c?",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc774 SQL \ucffc\ub9ac, RowMapper, \ud30c\ub77c\ubbf8\ud130\ub97c \ubd84\ub9ac\ud55c \uba54\uc11c\ub4dc\uc5d0 \ub118\uaca8\uc8fc\uace0 \ucffc\ub9ac \uc2e4\ud589 \ud6c4 \ub9e4\ud551\ud55c \uac12\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public User findById(final int userId) {\n final String query = "SELECT * FROM user WHERE id = ?";\n return queryForSingleResult(query, resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n }, userId);\n}\n\nprivate User queryForSingleResult(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n if (resultSet.next()) {\n return rowMapper.mapRow(resultSet);\n }\n return null;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n\nprivate ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---3-\ub2e4\uac74-\uc870\ud68c",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c"}),"\n",(0,r.jsx)(n.p,{children:"\ub2e8\uac74 \uc870\ud68c\uc640 \uc720\uc0ac\ud558\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public List findAll() {\n final String query = "SELECT * FROM user";\n return query(query, resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n });\n}\n\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(rowMapper.mapRow(resultSet));\n }\n return result;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n\nprivate ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc81c\ub124\ub9ad-\uc0ac\uc6a9\ud558\uae30",children:"\uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30"}),"\n",(0,r.jsxs)(n.p,{children:["\uc704\uc758 \ucf54\ub4dc\ub294 User\ub97c \uc870\ud68c\ud560 \ub54c\ub9cc \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc774 \uc81c\ub124\ub9ad\uc744 \uc801\uc6a9\ud558\uc5ec \ub2e4\ub978 Dao\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface RowMapper {\n T mapRow(final ResultSet resultSet) throws SQLException;\n}\n\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {...}\nprivate T queryForSingleResult(final String query, final RowMapper rowMapper, final Object... parameters) {...}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\uba54\uc11c\ub4dc-\ubd84\ub9ac\ud55c-\ubd80\ubd84-\ud074\ub798\uc2a4\ub85c-\ubd84\ub9ac\ud558\uae30--optional-\uc0ac\uc6a9\ud558\uae30",children:"\uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30"}),"\n",(0,r.jsxs)(n.p,{children:["\uba54\uc11c\ub4dc\ub85c \ubd84\ub9ac\ud55c \ubd80\ubd84\uc744 JdbcTemplate\uc774\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc62e\uae34\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c null\uc744 \ubc18\ud658\ud558\uae30 \ubcf4\ub2e8 Optional\ub85c \uac10\uc2f8\uc11c \ubc18\ud658\ud558\ub3c4\ub85d \ubcc0\uacbd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd5c\uc885\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uac00 \uc644\uc131\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(l.Z,{value:"UserDao",label:"UserDao",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class UserDao {\n private final RowMapper rowMapper = resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n };\n private final JdbcTemplate jdbcTemplate;\n\n public UserDao(final JdbcTemplate jdbcTemplate) {\n this.jdbcTemplate = jdbcTemplate;\n }\n\n public void insert(final String name) {\n final String query = "INSERT INTO User (name) VALUES (?)";\n jdbcTemplate.executeUpdate(query, name);\n }\n\n public void delete(final int userId) {\n final String query = "DELETE FROM user WHERE user_id = ?";\n jdbcTemplate.executeUpdate(query, userId);\n }\n\n public Optional findById(final int userId) {\n final String query = "SELECT * FROM user WHERE id = ?";\n return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);\n }\n\n public List findAll() {\n final String query = "SELECT * FROM user";\n return jdbcTemplate.query(query, rowMapper);\n }\n}\n'})})}),(0,r.jsx)(l.Z,{value:"JdbcTemplate",label:"JdbcTemplate",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public class JdbcTemplate {\n private final ConnectionPool connectionPool;\n\n public JdbcTemplate(final ConnectionPool connectionPool) {\n this.connectionPool = connectionPool;\n }\n\n public void executeUpdate(final String query, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public Optional queryForSingleResult(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n ) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n if (resultSet.next()) {\n return Optional.of(rowMapper.mapRow(resultSet));\n }\n return Optional.empty();\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n private ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters\n ) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n }\n\n public List query(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n ) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(rowMapper.mapRow(resultSet));\n }\n return result;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n}\n"})})})]})]})}function m(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>s});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=r.createContext({}),s=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),d=s(t),m=a,f=d["".concat(c,".").concat(m)]||d[m]||u[m]||i;return t?r.createElement(f,l(l({ref:n},p),{},{components:t})):r.createElement(f,l({ref:n},p))}));p.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>l});t(67294);var r=t(86010);const a={tabItem:"tabItem_Ymn6"};var i=t(85893);function l(e){let{children:n,hidden:t,className:l}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.Z)(a.tabItem,l),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>j});var r=t(67294),a=t(86010),i=t(12466),l=t(16550),o=t(20469),c=t(91980),s=t(67392),u=t(50012);function p(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function d(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return p(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:a}}=e;return{value:n,label:t,attributes:r,default:a}}))}(t);return function(e){const n=(0,s.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function m(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function f(e){let{queryString:n=!1,groupId:t}=e;const a=(0,l.k6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,c._X)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function S(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=d(e),[l,c]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!m({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[s,p]=f({queryString:t,groupId:a}),[S,g]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,u.Nk)(t);return[a,(0,r.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),b=(()=>{const e=s??S;return m({value:e,tabValues:i})?e:null})();(0,o.Z)((()=>{b&&c(b)}),[b]);return{selectedValue:l,selectValue:(0,r.useCallback)((e=>{if(!m({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),p(e),g(e)}),[p,g,i]),tabValues:i}}var g=t(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var h=t(85893);function x(e){let{className:n,block:t,selectedValue:r,selectValue:l,tabValues:o}=e;const c=[],{blockElementScrollPositionUntilNextRender:s}=(0,i.o5)(),u=e=>{const n=e.currentTarget,t=c.indexOf(n),a=o[t].value;a!==r&&(s(n),l(a))},p=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=c.indexOf(e.currentTarget)+1;n=c[t]??c[0];break}case"ArrowLeft":{const t=c.indexOf(e.currentTarget)-1;n=c[t]??c[c.length-1];break}}n?.focus()};return(0,h.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,h.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>c.push(e),onKeyDown:p,onClick:u,...i,className:(0,a.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function y(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,h.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function v(e){const n=S(e);return(0,h.jsxs)("div",{className:(0,a.Z)("tabs-container",b.tabList),children:[(0,h.jsx)(x,{...e,...n}),(0,h.jsx)(y,{...e,...n})]})}function j(e){const n=(0,g.Z)();return(0,h.jsx)(v,{...e,children:p(e.children)},String(n))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[588],{18751:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>c,default:()=>m,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var r=t(85893),a=t(3905),i=t(74866),l=t(85162);const o={title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",slug:"custom-jdbc-template",tags:["JDBC","Java"]},c=void 0,s={permalink:"/custom-jdbc-template",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",source:"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",description:"\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.",date:"2023-04-02T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 2\uc77c",tags:[{label:"JDBC",permalink:"/tags/jdbc"},{label:"Java",permalink:"/tags/java"}],readingTime:9.025,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",slug:"custom-jdbc-template",tags:["JDBC","Java"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0",permalink:"/woowacourse-level1-retrospective"},nextItem:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",permalink:"/java-class-file"}},u={authorsImageUrls:[]},p=[{value:"\uae30\uc874 \ucf54\ub4dc",id:"\uae30\uc874-\ucf54\ub4dc",level:3},{value:"SELECT, DELETE \uc911\ubcf5 \uc81c\uac70",id:"select-delete-\uc911\ubcf5-\uc81c\uac70",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---1-\ucf5c\ubc31\uc744-\uc704\ud55c-\uc778\ud130\ud398\uc774\uc2a4-\uc815\uc758",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---2-\ub2e8\uac74-\uc870\ud68c",level:3},{value:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c",id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---3-\ub2e4\uac74-\uc870\ud68c",level:3},{value:"\uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30",id:"\uc81c\ub124\ub9ad-\uc0ac\uc6a9\ud558\uae30",level:3},{value:"\uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30",id:"\uba54\uc11c\ub4dc-\ubd84\ub9ac\ud55c-\ubd80\ubd84-\ud074\ub798\uc2a4\ub85c-\ubd84\ub9ac\ud558\uae30--optional-\uc0ac\uc6a9\ud558\uae30",level:3}];function d(e){const n={admonition:"admonition",br:"br",code:"code",h3:"h3",mermaid:"mermaid",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774 \ub54c JDBC\ub97c \uc0ac\uc6a9\ud560 \ub54c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ucee4\ub125\uc158\uc744 \uc5bb\uace0, try-with-resource\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc774 \ubc18\ubcf5\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc774\uc6a9\ud558\uc5ec \ub098\ub9cc\uc758 JdbcTemplate\uc744 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uae30\uc874-\ucf54\ub4dc",children:"\uae30\uc874 \ucf54\ub4dc"}),"\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(l.Z,{value:"User",label:"User",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public class User {\n private final int id;\n private final String name;\n\n public User(final int id, final String name) {\n this.id = id;\n this.name = name;\n }\n\n public int getId() {\n return id;\n }\n\n public String getName() {\n return name;\n }\n}\n"})})}),(0,r.jsx)(l.Z,{value:"UserDao",label:"UserDao",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class UserDao {\n private final ConnectionPool connectionPool;\n\n public UserDao(final ConnectionPool connectionPool) {\n this.connectionPool = connectionPool;\n }\n\n public void insert(final String name) {\n final Connection connection = connectionPool.getConnection();\n final String query = "INSERT INTO User (name) VALUES (?)";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setString(1, name);\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public void delete(final int userId) {\n final Connection connection = connectionPool.getConnection();\n final String query = "DELETE FROM user WHERE id = ?";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setInt(1, userId);\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public User findById(final int userId) {\n final Connection connection = connectionPool.getConnection();\n final String query = "SELECT * FROM user WHERE id = ?";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n preparedStatement.setInt(1, userId);\n final ResultSet resultSet = preparedStatement.executeQuery();\n if (resultSet.next()) {\n return new User(\n resultSet.getInt("id"),\n resultSet.getString("name")\n );\n }\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n return null;\n }\n\n public List findAll() {\n final Connection connection = connectionPool.getConnection();\n final String query = "SELECT * FROM user";\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n final ResultSet resultSet = preparedStatement.executeQuery();\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(new User(\n resultSet.getInt("id"),\n resultSet.getString("name")\n ));\n }\n return result;\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n}\n'})})}),(0,r.jsx)(l.Z,{value:"ConnectionPool",label:"ConnectionPool",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class ConnectionPool {\n private static final String SERVER = "localhost:13306";\n private static final String DATABASE = "chess";\n private static final String OPTION = "?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";\n private static final String URL = "jdbc:mysql://" + SERVER + "/" + DATABASE + OPTION;\n private static final String USERNAME = "root";\n private static final String PASSWORD = "root";\n\n private final AtomicInteger index = new AtomicInteger();\n private final List connections;\n\n public ConnectionPool(final int connectionCount) {\n connections = generateConnections(connectionCount);\n }\n\n private List generateConnections(final int connectionCount) {\n return Stream.generate(this::generateConnection)\n .limit(connectionCount)\n .collect(toList());\n }\n\n private Connection generateConnection() {\n try {\n return DriverManager.getConnection(URL, USERNAME, PASSWORD);\n } catch (SQLException e) {\n throw new IllegalStateException("\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.");\n }\n }\n\n public Connection getConnection() {\n int currentIndex = index.getAndIncrement();\n return connections.get(currentIndex % connections.size());\n }\n}\n'})})})]}),"\n",(0,r.jsx)(n.h3,{id:"select-delete-\uc911\ubcf5-\uc81c\uac70",children:"SELECT, DELETE \uc911\ubcf5 \uc81c\uac70"}),"\n",(0,r.jsxs)(n.p,{children:["\ubcc0\ud558\uc9c0 \uc54a\ub294 \ubd80\ubd84: try-with-resource, preparedStatement\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84, executeUpdate\ub85c \uc2e4\ud589 \ub4f1\ub4f1",(0,r.jsx)(n.br,{}),"\n","\ubcc0\ud558\ub294 \ubd80\ubd84: SQL Query, \ub9e4\uac1c\ubcc0\uc218"]}),"\n",(0,r.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\ub294 \ubd80\ubd84\uc744 \ubd84\ub9ac\ud558\uace0 \uac00\ubcc0\uc778\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 SELECT\uc640 DELETE\uc758 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public void insert(final String name) {\n final String query = "INSERT INTO User (name) VALUES (?)";\n executeUpdate(query, name);\n}\n\npublic void delete(final int userId) {\n final String query = "DELETE FROM user WHERE user_id = ?";\n executeUpdate(query, userId);\n}\n\nprivate void executeUpdate(final String query, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---1-\ucf5c\ubc31\uc744-\uc704\ud55c-\uc778\ud130\ud398\uc774\uc2a4-\uc815\uc758",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758"}),"\n",(0,r.jsxs)(n.p,{children:["\uc870\ud68c\ub294 INSERT, DELETE\uc640 \ub2ec\ub9ac \uac12\uc744 \ubc18\ud658\ubc1b\uc544\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0 \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774 \ub54c \ucf5c\ubc31\uc774\ub77c\ub294 \uac83\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsxs)(n.admonition,{title:"\ucf5c\ubc31(Callback)",type:"note",children:[(0,r.jsxs)(n.p,{children:["\ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \ucf5c\ubc31\uc740 \ub2e4\ub978 \ucf54\ub4dc\uc758 \uc778\uc218\ub85c \ub118\uaca8\uc8fc\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ucf54\ub4dc\ub97c \ub73b\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\ubc14\uc5d0\uc11c\ub294 \ub78c\ub2e4\ub098 \uc775\uba85 \ud074\ub798\uc2a4\ub97c \ub118\uaca8\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),(0,r.jsx)(n.mermaid,{value:"flowchart LR\n \ud074\ub77c\uc774\uc5b8\ud2b8 -- \ucf5c\ubc31\uc804\ub2ec --\x3e \uba54\uc11c\ub4dc\n \uba54\uc11c\ub4dc -- \ub0b4\ubd80\ud638\ucd9c --\x3e \uc804\ub2ec\ubc1b\uc740\ucf5c\ubc31"})]}),"\n",(0,r.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uc870\ud68c\ud558\uace0, \ud574\ub2f9 \uac12\uc744 \uac1d\uccb4\ub85c \ub9e4\ud551\ud558\uc5ec \uac12\uc744 \ubc18\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","executeQuery\ub85c \uc870\ud68c\ud55c \uac12\uc740 ResultSet \uc548\uc5d0 \ub4e4\uc5b4\uac00\uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ub97c \uc6d0\ud558\ub294 \ud0c0\uc785\uc758 \uac12\uc73c\ub85c \ubcc0\ud658\ud574\uc57c\ud558\ub2c8 \uc77c\ub2e8 \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface RowMapper {\n User mapRow(final ResultSet resultSet) throws SQLException;\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---2-\ub2e8\uac74-\uc870\ud68c",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c"}),"\n",(0,r.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c \uc815\uc758\ud55c RowMapper\ub97c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c?",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc774 SQL \ucffc\ub9ac, RowMapper, \ud30c\ub77c\ubbf8\ud130\ub97c \ubd84\ub9ac\ud55c \uba54\uc11c\ub4dc\uc5d0 \ub118\uaca8\uc8fc\uace0 \ucffc\ub9ac \uc2e4\ud589 \ud6c4 \ub9e4\ud551\ud55c \uac12\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public User findById(final int userId) {\n final String query = "SELECT * FROM user WHERE id = ?";\n return queryForSingleResult(query, resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n }, userId);\n}\n\nprivate User queryForSingleResult(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n if (resultSet.next()) {\n return rowMapper.mapRow(resultSet);\n }\n return null;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n\nprivate ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc870\ud68c-\ubd84\ub9ac\ud558\uae30---3-\ub2e4\uac74-\uc870\ud68c",children:"\uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c"}),"\n",(0,r.jsx)(n.p,{children:"\ub2e8\uac74 \uc870\ud68c\uc640 \uc720\uc0ac\ud558\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public List findAll() {\n final String query = "SELECT * FROM user";\n return query(query, resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n });\n}\n\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(rowMapper.mapRow(resultSet));\n }\n return result;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n}\n\nprivate ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"\uc81c\ub124\ub9ad-\uc0ac\uc6a9\ud558\uae30",children:"\uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30"}),"\n",(0,r.jsxs)(n.p,{children:["\uc704\uc758 \ucf54\ub4dc\ub294 User\ub97c \uc870\ud68c\ud560 \ub54c\ub9cc \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\uc640 \uac19\uc774 \uc81c\ub124\ub9ad\uc744 \uc801\uc6a9\ud558\uc5ec \ub2e4\ub978 Dao\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface RowMapper {\n T mapRow(final ResultSet resultSet) throws SQLException;\n}\n\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {...}\nprivate T queryForSingleResult(final String query, final RowMapper rowMapper, final Object... parameters) {...}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\uba54\uc11c\ub4dc-\ubd84\ub9ac\ud55c-\ubd80\ubd84-\ud074\ub798\uc2a4\ub85c-\ubd84\ub9ac\ud558\uae30--optional-\uc0ac\uc6a9\ud558\uae30",children:"\uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30"}),"\n",(0,r.jsxs)(n.p,{children:["\uba54\uc11c\ub4dc\ub85c \ubd84\ub9ac\ud55c \ubd80\ubd84\uc744 JdbcTemplate\uc774\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc62e\uae34\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub610\ud55c null\uc744 \ubc18\ud658\ud558\uae30 \ubcf4\ub2e8 Optional\ub85c \uac10\uc2f8\uc11c \ubc18\ud658\ud558\ub3c4\ub85d \ubcc0\uacbd\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd5c\uc885\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uac00 \uc644\uc131\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(i.Z,{children:[(0,r.jsx)(l.Z,{value:"UserDao",label:"UserDao",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public class UserDao {\n private final RowMapper rowMapper = resultSet -> {\n final int id = resultSet.getInt("id");\n final String name = resultSet.getString("name");\n return new User(id, name);\n };\n private final JdbcTemplate jdbcTemplate;\n\n public UserDao(final JdbcTemplate jdbcTemplate) {\n this.jdbcTemplate = jdbcTemplate;\n }\n\n public void insert(final String name) {\n final String query = "INSERT INTO User (name) VALUES (?)";\n jdbcTemplate.executeUpdate(query, name);\n }\n\n public void delete(final int userId) {\n final String query = "DELETE FROM user WHERE user_id = ?";\n jdbcTemplate.executeUpdate(query, userId);\n }\n\n public Optional findById(final int userId) {\n final String query = "SELECT * FROM user WHERE id = ?";\n return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);\n }\n\n public List findAll() {\n final String query = "SELECT * FROM user";\n return jdbcTemplate.query(query, rowMapper);\n }\n}\n'})})}),(0,r.jsx)(l.Z,{value:"JdbcTemplate",label:"JdbcTemplate",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public class JdbcTemplate {\n private final ConnectionPool connectionPool;\n\n public JdbcTemplate(final ConnectionPool connectionPool) {\n this.connectionPool = connectionPool;\n }\n\n public void executeUpdate(final String query, final Object... parameters) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n preparedStatement.executeUpdate();\n } catch (final SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n public Optional queryForSingleResult(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n ) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n if (resultSet.next()) {\n return Optional.of(rowMapper.mapRow(resultSet));\n }\n return Optional.empty();\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n\n private ResultSet executeQuery(\n final PreparedStatement preparedStatement,\n final Object[] parameters\n ) throws SQLException {\n for (int i = 1; i <= parameters.length; i++) {\n preparedStatement.setObject(i, parameters[i - 1]);\n }\n return preparedStatement.executeQuery();\n }\n\n public List query(\n final String query,\n final RowMapper rowMapper,\n final Object... parameters\n ) {\n final Connection connection = connectionPool.getConnection();\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\n final List result = new ArrayList<>();\n while (resultSet.next()) {\n result.add(rowMapper.mapRow(resultSet));\n }\n return result;\n } catch (SQLException e) {\n throw new IllegalArgumentException(e.getMessage());\n }\n }\n}\n"})})})]})]})}function m(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>s});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=r.createContext({}),s=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),d=s(t),m=a,f=d["".concat(c,".").concat(m)]||d[m]||u[m]||i;return t?r.createElement(f,l(l({ref:n},p),{},{components:t})):r.createElement(f,l({ref:n},p))}));p.displayName="MDXCreateElement"},85162:(e,n,t)=>{t.d(n,{Z:()=>l});t(67294);var r=t(86010);const a={tabItem:"tabItem_Ymn6"};var i=t(85893);function l(e){let{children:n,hidden:t,className:l}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.Z)(a.tabItem,l),hidden:t,children:n})}},74866:(e,n,t)=>{t.d(n,{Z:()=>j});var r=t(67294),a=t(86010),i=t(12466),l=t(16550),o=t(20469),c=t(91980),s=t(67392),u=t(50012);function p(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function d(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return p(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:a}}=e;return{value:n,label:t,attributes:r,default:a}}))}(t);return function(e){const n=(0,s.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function m(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function f(e){let{queryString:n=!1,groupId:t}=e;const a=(0,l.k6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,c._X)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function S(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=d(e),[l,c]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!m({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[s,p]=f({queryString:t,groupId:a}),[S,g]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,u.Nk)(t);return[a,(0,r.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),b=(()=>{const e=s??S;return m({value:e,tabValues:i})?e:null})();(0,o.Z)((()=>{b&&c(b)}),[b]);return{selectedValue:l,selectValue:(0,r.useCallback)((e=>{if(!m({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),p(e),g(e)}),[p,g,i]),tabValues:i}}var g=t(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var h=t(85893);function x(e){let{className:n,block:t,selectedValue:r,selectValue:l,tabValues:o}=e;const c=[],{blockElementScrollPositionUntilNextRender:s}=(0,i.o5)(),u=e=>{const n=e.currentTarget,t=c.indexOf(n),a=o[t].value;a!==r&&(s(n),l(a))},p=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=c.indexOf(e.currentTarget)+1;n=c[t]??c[0];break}case"ArrowLeft":{const t=c.indexOf(e.currentTarget)-1;n=c[t]??c[c.length-1];break}}n?.focus()};return(0,h.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,h.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>c.push(e),onKeyDown:p,onClick:u,...i,className:(0,a.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function y(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,h.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function v(e){const n=S(e);return(0,h.jsxs)("div",{className:(0,a.Z)("tabs-container",b.tabList),children:[(0,h.jsx)(x,{...e,...n}),(0,h.jsx)(y,{...e,...n})]})}function j(e){const n=(0,g.Z)();return(0,h.jsx)(v,{...e,children:p(e.children)},String(n))}}}]); \ No newline at end of file diff --git a/assets/js/d8775059.f37a361d.js b/assets/js/d8775059.db70e9eb.js similarity index 98% rename from assets/js/d8775059.f37a361d.js rename to assets/js/d8775059.db70e9eb.js index 2655d0b3e..7a96d6afe 100644 --- a/assets/js/d8775059.f37a361d.js +++ b/assets/js/d8775059.db70e9eb.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6387],{33604:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=t(85893),c=t(3905);const a={title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",slug:"tecochat-retrospective-1",tags:["TecoChat","Retrospective"]},s=void 0,i={permalink:"/tecochat-retrospective-1",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",source:"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",description:"4\uc6d4 21\uc77c \uae08\uc694\uc77c",date:"2023-04-22T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 22\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.68,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",slug:"tecochat-retrospective-1",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"Jenkins\ub85c CI/CD \uc124\uc815",permalink:"/jenkins"},nextItem:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",permalink:"/book-leadership-and-self-deception"}},o={authorsImageUrls:[]},l=[{value:"4\uc6d4 21\uc77c \uae08\uc694\uc77c",id:"4\uc6d4-21\uc77c-\uae08\uc694\uc77c",level:3},{value:"\ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?",id:"\ub3c4\uba54\uc778-\uad6c\uc785-\uc131\uacf5",level:3},{value:"\ub9d0\ub791\uc758 DM",id:"\ub9d0\ub791\uc758-dm",level:3},{value:"\ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec",id:"\ub3c4\uba54\uc778-\uc124\uc815-\ubc0f-\ubc30\ud3ec",level:3},{value:"GPT",id:"gpt",level:3},{value:"Sonarcloud",id:"sonarcloud",level:3},{value:"Tiptap",id:"tiptap",level:3},{value:"\ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9",id:"\ud3f0\ud2b8-\ubc0f-favicon-\uc801\uc6a9",level:3}];function p(e){const n={br:"br",code:"code",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"4\uc6d4-21\uc77c-\uae08\uc694\uc77c",children:"4\uc6d4 21\uc77c \uae08\uc694\uc77c"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ubca8 2\ub97c \uc2dc\uc791\ud55c \ub4a4 \ub0b4\uac00 \ud559\uc2b5\uc5d0 \ub300\ud55c \ubc29\ud5a5\uc744 \uc783\uc5b4\ubc84\ub838\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub808\ubca8 3, 4\uc5d0\uc11c \ub098\ub9cc\uc758 \uac15\uc810\uc744 \uac00\uc9c0\uace0 \uc2f6\uc5b4 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e8\uc21c\ud788 \uc2a4\ud504\ub9c1\uc744 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ud6a8\uc728\uc774 \ub9ce\uc774 \ub5a8\uc5b4\uc9c4\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae00\uc4f0\uae30 \uc218\uc0c1\uc73c\ub85c \ubc1b\uc740 \ucfe0\ud3f0\uc744 \uc0ac\uc6a9\ud574 \ube0c\ub77c\uc6b4\uc5d0\uac8c \ucee4\ud53c\ucc57\uc744 \uc2e0\uccad\ud588\uace0, \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud574\ubcf4\ub77c\ub294 \ub2f5\uc744 \ubc1b\uc558\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub098\ub294 \uc544\uc774\ub514\uc5b4\ub97c \ubabb\ub0b4\ub294 \ud3b8\uc778\ub370 \ube0c\ub77c\uc6b4\uc774 \uc544\uc774\ub514\uc5b4\uae4c\uc9c0 \ub358\uc838\uc8fc\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"Chat-GPT \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uace0, \ud574\ub2f9 \ud06c\ub8e8\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc744 \uacf5\uc720\ud560 \uc218 \uc788\ub294 \uac74 \uc5b4\ub5a4\uc9c0?"})]}),"\n",(0,r.jsxs)(n.p,{children:["\uae30\uc220\uc774 \ubaa9\uc801\uc778 \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4\ub294 \ub2f5\ubcc0\uc744 \ub4e4\uc5c8\uace0, \ud63c\uc790 \uc544\ub2c8\uba74 \ud398\uc5b4\ud560 \uc218 \uc788\uc744 \uc815\ub3c4\uc758 \uc778\uc6d0\uc73c\ub85c \uc9c4\ud589\ud558\uba74 \uc88b\uaca0\ub2e4\uace0 \ud558\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud504\ub860\ud2b8\ub791 \uac04\ub2e8\ud558\uac8c \ubc30\ud3ec\uae4c\uc9c0 \ud574\ubcf8 \uacbd\ud5d8\uc774 \uc788\uc5b4\uc11c \ud63c\uc790\ud574\ub3c4 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc744 \uac83 \uac19\uc544\uc11c \ud63c\uc790 \ud558\uae30\ub85c \ub9c8\uc74c\uc744 \uba39\uc5c8\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uac74 \ubabb\ucc38\uc9c0"}),"\n",(0,r.jsx)(n.h3,{id:"\ub3c4\uba54\uc778-\uad6c\uc785-\uc131\uacf5",children:"\ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?"}),"\n",(0,r.jsxs)(n.p,{children:["\ucee4\ud53c\ucc57\uc774 \ub05d\ub098\uace0 \uc9d1\uc73c\ub85c \ub3cc\uc544\uac00\ub294 \uae38\uc5d0 \ubc14\ub85c \ub3c4\uba54\uc778\uc744 \uad6c\ub9e4\ud558\ub824\uace0 namecheap\uc5d0\uc11c \uc801\ub2f9\ud55c \ub3c4\uba54\uc778\uc774 \uc5c6\uc744\uae4c \uac80\uc0c9\uc744 \uacc4\uc18d\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9c8\uce58 \uc5b4\ub9b4 \ub54c \ud588\ub358 \uac8c\uc784 \ub2c9\ub124\uc784 \uc815\ud558\ub294 \uac83\ucc98\ub7fc \uc2dc\uac04\uc774 \uc624\ub798 \uac78\ub838\ub2e4.",(0,r.jsx)(n.br,{}),"\n","dev, io, chat \ub3c4\uba54\uc778\uc774 \ud6c4\ubcf4\uc600\uace0 \uc9d1 \uac00\ub294 \uae38\uc5d0 \uacb0\uc815\ub9cc \ud558\ub2e4\uac00 \uad6c\ub9e4\ud558\uc9c0 \ubabb\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ub9d0\ub791\uc758-dm",children:"\ub9d0\ub791\uc758 DM"}),"\n",(0,r.jsxs)(n.p,{children:["\uc9d1\uc5d0 \uac00\uc11c \ubc25\uc744 \uba39\uace0 \ub9d0\ub791\uc774\ub791 DM \ud558\ub2e4 \ud504\ub85c\uc81d\ud2b8\ub97c \uac19\uc774 \ud558\uc790\ub294 \uc774\uc57c\uae30\uac00 \ub098\uc654\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6b0\ud14c\ucf54 \ucd5c\uace0 \uace0\uc218 \ub9d0\ub791\uc758 \uc694\uad6c\ub77c \uc218\ub77d\ud558\uc9c0 \uc54a\uc73c\uba74 \ud6c4\ud3ed\ud48d\uc744 \uac10\ub2f9\ud560 \uc218 \uc5c6\uc5c8\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ub7f0\uc800\ub7f0 \ub300\ud654\ub97c \ub098\ub204\ub2e4\uac00 \ub09c \ube60\ub974\uac8c \ud504\ub85c\ud1a0\ud0c0\uc785\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uace0 \uc2f6\uc5b4\uc11c \ud504\ub860\ud2b8\ub97c \uad6c\ud604\ud55c\ub2e4\uace0 \ud588\uace0, \ub9d0\ub791\uc740 GPT api\ub97c \uc870\uc0ac\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ub3c4\uba54\uc778\uc5d0 \uad00\ud55c \uc774\uc57c\uae30\ub97c \ud558\ub2e4\uac00 woowachat\uc774 \uc5b8\uae09\ub418\uc5c8\uace0, namecheap\uc5d0\uc11c chat \ub3c4\uba54\uc778\uc744 \uc0ac\uc6a9\ud55c woowa.chat\uc73c\ub85c \uad6c\ub9e4\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ud6c4\uc5d0 teco.chat\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4!"]}),"\n",(0,r.jsx)(n.h3,{id:"\ub3c4\uba54\uc778-\uc124\uc815-\ubc0f-\ubc30\ud3ec",children:"\ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec"}),"\n",(0,r.jsxs)(n.p,{children:["\ud1a0\uc694\uc77c\uc5d0 \uad6c\ub9e4\ud55c \ub3c4\uba54\uc778\uc744 CDN, \ubcf4\uc548 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 Cloudflare\uc5d0 \ub3c4\uba54\uc778 \ub4f1\ub85d\uc744 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc5d0\uac8c \uc775\uc219\ud55c Nuxt3\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\uace0, Cloudflare Pages\ub97c \uc774\uc6a9\ud558\uc5ec \ubc30\ud3ec\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"gpt",children:"GPT"}),"\n",(0,r.jsxs)(n.p,{children:["\ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud558\ub2c8 api limit\uc774 \uc788\uc5b4 \ubd84\ub2f9 3\ubc88\ubc16\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc77c\ub2e8 \ubc31\uc5d4\ub4dc\ub97c \uad6c\ucd95\ud558\uae30 \uc804\uc5d0\ub294 \ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud560 \uc0dd\uac01\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"sonarcloud",children:"Sonarcloud"}),"\n",(0,r.jsxs)(n.p,{children:["\uc815\uc801 \ucf54\ub4dc \ubd84\uc11d \ub3c4\uad6c\ub85c Sonarcloud\ub97c \uc801\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Sonarcloud\ub294 SonarQube\uc758 SaaS \ubc84\uc804\uc774\uace0 \uc0ac\uc6a9\uc774 \ub9e4\uc6b0 \ud3b8\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608\uc804\uc5d0 Sonarcloud\ub97c \uc0ac\uc6a9\ud560 \ub550 \ubc84\ud2bc \uba87 \ubc88 \ub204\ub974\uba74 \uc801\uc6a9\ud560 \uc218 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \ubc14\ub85c github action\uc744 \uc0ac\uc6a9\ud558\ub77c\ub294 \uc548\ub0b4 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Sonarcloud\uac00 \uc790\uccb4\uc801\uc73c\ub85c github repository\uc5d0 push \ud558\uba74 \uc815\uc801 \ubd84\uc11d\uc744 \ud574\uc8fc\ub294 \uae30\ub2a5\uc744 \uc6d0\ud588\uace0, Administration -> Analysis Method\uc5d0 Automatic Analysis\ub97c \uc124\uc815\ud558\ub2c8 \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub108\ubb34 \uaf41\uaf41 \uc228\uaca8\uc838\uc788\ub124"]}),"\n",(0,r.jsx)(n.h3,{id:"tiptap",children:"Tiptap"}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ub4dc \ud558\uc774\ub77c\uc774\ud305 \uae30\ub2a5\uc744 \ub123\uace0 \uc2f6\uc5b4\uc11c Tiptap\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Tiptap\uc740 Headless WYSIWYG \uc5d0\ub514\ud130\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uae30\ub2a5\uc5d0 \ud2b9\ud654\ub418\uc5b4\uc788\ub294 \uc5d0\ub514\ud130\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\uc9c1 Tiptap\uc774 \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uae30\ub2a5\uc744 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc0ac\uc6a9\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc CodeBlockLowlight \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucf54\ub4dc \ube14\ub85d\uc744 \uc608\uc058\uac8c \ucd9c\ub825\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","api \ubc18\ud658\uac12 \uadf8\ub300\ub85c tiptap\uc758 content\uc5d0 \uc124\uc815\ud588\ub354\ub2c8 \ucf54\ub4dc \ube14\ub85d\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc544\uc11c \ubc31 \ud2f1 3\uac1c\ub97c ",(0,r.jsx)(n.code,{children:"
"}),"\ub85c \ubcc0\ud658\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ub744\uc5b4\uc4f0\uae30\ub3c4 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc544\uc11c ",(0,r.jsx)(n.code,{children:"\\n"}),"\ub97c ",(0,r.jsx)(n.code,{children:"
"}),"\ud0dc\uadf8\ub85c \ubcc0\ud658\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubcc0\ud658\ud558\ub294 \ub85c\uc9c1\uc740 GPT\uc758 \ub3c4\uc6c0\uc744 \ub9ce\uc774 \ubc1b\uc558\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:'const replaceCodeFences = (input: String) => {\n const codeFencesRegex = /```([\\w-]*)\\n([\\s\\S]*?)\\n```/g;\n return input\n .replace(codeFencesRegex, (match, p1, p2) => {\n const languageClass = p1 ? ` class="language-${p1}"` : "";\n return `
${p2}
`;\n })\n .replace(/\\n/g, "
");\n};\n'})}),"\n",(0,r.jsx)(n.p,{children:"Tiptap\uc744 \uc801\uc6a9\ud558\ub2c8 \ub2e4\uc74c\uacfc \uac19\uc774 \uae54\ub054\ud55c \ucf54\ub4dc \ube14\ub85d\uc744 \ubcfc \uc218 \uc788\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"tecochat",src:t(49124).Z+"",width:"2388",height:"1500"})}),"\n",(0,r.jsx)(n.h3,{id:"\ud3f0\ud2b8-\ubc0f-favicon-\uc801\uc6a9",children:"\ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9"}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc774\ud2c0\uc740 \ubc30\ub2ec\uc758\ubbfc\uc871 \ub3c4\ud604\uccb4, \ub0b4\uc6a9\uc740 IBM Plex Sans\ub97c \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c favicon\ub3c4 \uac04\ub2e8\ud558\uac8c \uc801\uc6a9\ud574\uc11c \ub9cc\uc871\uc2a4\ub7ec\uc6e0\ub2e4."]})]})}function d(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>l});var r=t(67294);function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(c[t]=e[t]);return c}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(c[t]=e[t])}return c}var o=r.createContext({}),l=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,c=e.mdxType,a=e.originalType,o=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),h=l(t),u=c,j=h["".concat(o,".").concat(u)]||h[u]||p[u]||a;return t?r.createElement(j,s(s({ref:n},d),{},{components:t})):r.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"},49124:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/teco-chat-6b4f31b3d961878efc5c506fc167df1f.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6387],{33604:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=t(85893),c=t(3905);const a={title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",slug:"tecochat-retrospective-1",tags:["TecoChat","Retrospective"]},s=void 0,i={permalink:"/tecochat-retrospective-1",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",source:"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",description:"4\uc6d4 21\uc77c \uae08\uc694\uc77c",date:"2023-04-22T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 22\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.68,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",slug:"tecochat-retrospective-1",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",permalink:"/book-leadership-and-self-deception"},nextItem:{title:"Jenkins\ub85c CI/CD \uc124\uc815",permalink:"/jenkins"}},o={authorsImageUrls:[]},l=[{value:"4\uc6d4 21\uc77c \uae08\uc694\uc77c",id:"4\uc6d4-21\uc77c-\uae08\uc694\uc77c",level:3},{value:"\ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?",id:"\ub3c4\uba54\uc778-\uad6c\uc785-\uc131\uacf5",level:3},{value:"\ub9d0\ub791\uc758 DM",id:"\ub9d0\ub791\uc758-dm",level:3},{value:"\ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec",id:"\ub3c4\uba54\uc778-\uc124\uc815-\ubc0f-\ubc30\ud3ec",level:3},{value:"GPT",id:"gpt",level:3},{value:"Sonarcloud",id:"sonarcloud",level:3},{value:"Tiptap",id:"tiptap",level:3},{value:"\ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9",id:"\ud3f0\ud2b8-\ubc0f-favicon-\uc801\uc6a9",level:3}];function p(e){const n={br:"br",code:"code",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"4\uc6d4-21\uc77c-\uae08\uc694\uc77c",children:"4\uc6d4 21\uc77c \uae08\uc694\uc77c"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ubca8 2\ub97c \uc2dc\uc791\ud55c \ub4a4 \ub0b4\uac00 \ud559\uc2b5\uc5d0 \ub300\ud55c \ubc29\ud5a5\uc744 \uc783\uc5b4\ubc84\ub838\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub808\ubca8 3, 4\uc5d0\uc11c \ub098\ub9cc\uc758 \uac15\uc810\uc744 \uac00\uc9c0\uace0 \uc2f6\uc5b4 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e8\uc21c\ud788 \uc2a4\ud504\ub9c1\uc744 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ud6a8\uc728\uc774 \ub9ce\uc774 \ub5a8\uc5b4\uc9c4\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae00\uc4f0\uae30 \uc218\uc0c1\uc73c\ub85c \ubc1b\uc740 \ucfe0\ud3f0\uc744 \uc0ac\uc6a9\ud574 \ube0c\ub77c\uc6b4\uc5d0\uac8c \ucee4\ud53c\ucc57\uc744 \uc2e0\uccad\ud588\uace0, \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud574\ubcf4\ub77c\ub294 \ub2f5\uc744 \ubc1b\uc558\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub098\ub294 \uc544\uc774\ub514\uc5b4\ub97c \ubabb\ub0b4\ub294 \ud3b8\uc778\ub370 \ube0c\ub77c\uc6b4\uc774 \uc544\uc774\ub514\uc5b4\uae4c\uc9c0 \ub358\uc838\uc8fc\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"Chat-GPT \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uace0, \ud574\ub2f9 \ud06c\ub8e8\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc744 \uacf5\uc720\ud560 \uc218 \uc788\ub294 \uac74 \uc5b4\ub5a4\uc9c0?"})]}),"\n",(0,r.jsxs)(n.p,{children:["\uae30\uc220\uc774 \ubaa9\uc801\uc778 \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4\ub294 \ub2f5\ubcc0\uc744 \ub4e4\uc5c8\uace0, \ud63c\uc790 \uc544\ub2c8\uba74 \ud398\uc5b4\ud560 \uc218 \uc788\uc744 \uc815\ub3c4\uc758 \uc778\uc6d0\uc73c\ub85c \uc9c4\ud589\ud558\uba74 \uc88b\uaca0\ub2e4\uace0 \ud558\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud504\ub860\ud2b8\ub791 \uac04\ub2e8\ud558\uac8c \ubc30\ud3ec\uae4c\uc9c0 \ud574\ubcf8 \uacbd\ud5d8\uc774 \uc788\uc5b4\uc11c \ud63c\uc790\ud574\ub3c4 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc744 \uac83 \uac19\uc544\uc11c \ud63c\uc790 \ud558\uae30\ub85c \ub9c8\uc74c\uc744 \uba39\uc5c8\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uac74 \ubabb\ucc38\uc9c0"}),"\n",(0,r.jsx)(n.h3,{id:"\ub3c4\uba54\uc778-\uad6c\uc785-\uc131\uacf5",children:"\ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?"}),"\n",(0,r.jsxs)(n.p,{children:["\ucee4\ud53c\ucc57\uc774 \ub05d\ub098\uace0 \uc9d1\uc73c\ub85c \ub3cc\uc544\uac00\ub294 \uae38\uc5d0 \ubc14\ub85c \ub3c4\uba54\uc778\uc744 \uad6c\ub9e4\ud558\ub824\uace0 namecheap\uc5d0\uc11c \uc801\ub2f9\ud55c \ub3c4\uba54\uc778\uc774 \uc5c6\uc744\uae4c \uac80\uc0c9\uc744 \uacc4\uc18d\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9c8\uce58 \uc5b4\ub9b4 \ub54c \ud588\ub358 \uac8c\uc784 \ub2c9\ub124\uc784 \uc815\ud558\ub294 \uac83\ucc98\ub7fc \uc2dc\uac04\uc774 \uc624\ub798 \uac78\ub838\ub2e4.",(0,r.jsx)(n.br,{}),"\n","dev, io, chat \ub3c4\uba54\uc778\uc774 \ud6c4\ubcf4\uc600\uace0 \uc9d1 \uac00\ub294 \uae38\uc5d0 \uacb0\uc815\ub9cc \ud558\ub2e4\uac00 \uad6c\ub9e4\ud558\uc9c0 \ubabb\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ub9d0\ub791\uc758-dm",children:"\ub9d0\ub791\uc758 DM"}),"\n",(0,r.jsxs)(n.p,{children:["\uc9d1\uc5d0 \uac00\uc11c \ubc25\uc744 \uba39\uace0 \ub9d0\ub791\uc774\ub791 DM \ud558\ub2e4 \ud504\ub85c\uc81d\ud2b8\ub97c \uac19\uc774 \ud558\uc790\ub294 \uc774\uc57c\uae30\uac00 \ub098\uc654\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6b0\ud14c\ucf54 \ucd5c\uace0 \uace0\uc218 \ub9d0\ub791\uc758 \uc694\uad6c\ub77c \uc218\ub77d\ud558\uc9c0 \uc54a\uc73c\uba74 \ud6c4\ud3ed\ud48d\uc744 \uac10\ub2f9\ud560 \uc218 \uc5c6\uc5c8\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ub7f0\uc800\ub7f0 \ub300\ud654\ub97c \ub098\ub204\ub2e4\uac00 \ub09c \ube60\ub974\uac8c \ud504\ub85c\ud1a0\ud0c0\uc785\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uace0 \uc2f6\uc5b4\uc11c \ud504\ub860\ud2b8\ub97c \uad6c\ud604\ud55c\ub2e4\uace0 \ud588\uace0, \ub9d0\ub791\uc740 GPT api\ub97c \uc870\uc0ac\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ub3c4\uba54\uc778\uc5d0 \uad00\ud55c \uc774\uc57c\uae30\ub97c \ud558\ub2e4\uac00 woowachat\uc774 \uc5b8\uae09\ub418\uc5c8\uace0, namecheap\uc5d0\uc11c chat \ub3c4\uba54\uc778\uc744 \uc0ac\uc6a9\ud55c woowa.chat\uc73c\ub85c \uad6c\ub9e4\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ud6c4\uc5d0 teco.chat\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4!"]}),"\n",(0,r.jsx)(n.h3,{id:"\ub3c4\uba54\uc778-\uc124\uc815-\ubc0f-\ubc30\ud3ec",children:"\ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec"}),"\n",(0,r.jsxs)(n.p,{children:["\ud1a0\uc694\uc77c\uc5d0 \uad6c\ub9e4\ud55c \ub3c4\uba54\uc778\uc744 CDN, \ubcf4\uc548 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 Cloudflare\uc5d0 \ub3c4\uba54\uc778 \ub4f1\ub85d\uc744 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc5d0\uac8c \uc775\uc219\ud55c Nuxt3\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\uace0, Cloudflare Pages\ub97c \uc774\uc6a9\ud558\uc5ec \ubc30\ud3ec\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"gpt",children:"GPT"}),"\n",(0,r.jsxs)(n.p,{children:["\ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud558\ub2c8 api limit\uc774 \uc788\uc5b4 \ubd84\ub2f9 3\ubc88\ubc16\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc77c\ub2e8 \ubc31\uc5d4\ub4dc\ub97c \uad6c\ucd95\ud558\uae30 \uc804\uc5d0\ub294 \ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud560 \uc0dd\uac01\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"sonarcloud",children:"Sonarcloud"}),"\n",(0,r.jsxs)(n.p,{children:["\uc815\uc801 \ucf54\ub4dc \ubd84\uc11d \ub3c4\uad6c\ub85c Sonarcloud\ub97c \uc801\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Sonarcloud\ub294 SonarQube\uc758 SaaS \ubc84\uc804\uc774\uace0 \uc0ac\uc6a9\uc774 \ub9e4\uc6b0 \ud3b8\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608\uc804\uc5d0 Sonarcloud\ub97c \uc0ac\uc6a9\ud560 \ub550 \ubc84\ud2bc \uba87 \ubc88 \ub204\ub974\uba74 \uc801\uc6a9\ud560 \uc218 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \ubc14\ub85c github action\uc744 \uc0ac\uc6a9\ud558\ub77c\ub294 \uc548\ub0b4 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Sonarcloud\uac00 \uc790\uccb4\uc801\uc73c\ub85c github repository\uc5d0 push \ud558\uba74 \uc815\uc801 \ubd84\uc11d\uc744 \ud574\uc8fc\ub294 \uae30\ub2a5\uc744 \uc6d0\ud588\uace0, Administration -> Analysis Method\uc5d0 Automatic Analysis\ub97c \uc124\uc815\ud558\ub2c8 \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub108\ubb34 \uaf41\uaf41 \uc228\uaca8\uc838\uc788\ub124"]}),"\n",(0,r.jsx)(n.h3,{id:"tiptap",children:"Tiptap"}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ub4dc \ud558\uc774\ub77c\uc774\ud305 \uae30\ub2a5\uc744 \ub123\uace0 \uc2f6\uc5b4\uc11c Tiptap\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Tiptap\uc740 Headless WYSIWYG \uc5d0\ub514\ud130\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uae30\ub2a5\uc5d0 \ud2b9\ud654\ub418\uc5b4\uc788\ub294 \uc5d0\ub514\ud130\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\uc9c1 Tiptap\uc774 \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uae30\ub2a5\uc744 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc0ac\uc6a9\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc CodeBlockLowlight \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucf54\ub4dc \ube14\ub85d\uc744 \uc608\uc058\uac8c \ucd9c\ub825\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","api \ubc18\ud658\uac12 \uadf8\ub300\ub85c tiptap\uc758 content\uc5d0 \uc124\uc815\ud588\ub354\ub2c8 \ucf54\ub4dc \ube14\ub85d\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc544\uc11c \ubc31 \ud2f1 3\uac1c\ub97c ",(0,r.jsx)(n.code,{children:"
"}),"\ub85c \ubcc0\ud658\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ub744\uc5b4\uc4f0\uae30\ub3c4 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc544\uc11c ",(0,r.jsx)(n.code,{children:"\\n"}),"\ub97c ",(0,r.jsx)(n.code,{children:"
"}),"\ud0dc\uadf8\ub85c \ubcc0\ud658\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubcc0\ud658\ud558\ub294 \ub85c\uc9c1\uc740 GPT\uc758 \ub3c4\uc6c0\uc744 \ub9ce\uc774 \ubc1b\uc558\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:'const replaceCodeFences = (input: String) => {\n const codeFencesRegex = /```([\\w-]*)\\n([\\s\\S]*?)\\n```/g;\n return input\n .replace(codeFencesRegex, (match, p1, p2) => {\n const languageClass = p1 ? ` class="language-${p1}"` : "";\n return `
${p2}
`;\n })\n .replace(/\\n/g, "
");\n};\n'})}),"\n",(0,r.jsx)(n.p,{children:"Tiptap\uc744 \uc801\uc6a9\ud558\ub2c8 \ub2e4\uc74c\uacfc \uac19\uc774 \uae54\ub054\ud55c \ucf54\ub4dc \ube14\ub85d\uc744 \ubcfc \uc218 \uc788\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"tecochat",src:t(49124).Z+"",width:"2388",height:"1500"})}),"\n",(0,r.jsx)(n.h3,{id:"\ud3f0\ud2b8-\ubc0f-favicon-\uc801\uc6a9",children:"\ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9"}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc774\ud2c0\uc740 \ubc30\ub2ec\uc758\ubbfc\uc871 \ub3c4\ud604\uccb4, \ub0b4\uc6a9\uc740 IBM Plex Sans\ub97c \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c favicon\ub3c4 \uac04\ub2e8\ud558\uac8c \uc801\uc6a9\ud574\uc11c \ub9cc\uc871\uc2a4\ub7ec\uc6e0\ub2e4."]})]})}function d(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>l});var r=t(67294);function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(c[t]=e[t]);return c}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(c[t]=e[t])}return c}var o=r.createContext({}),l=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,c=e.mdxType,a=e.originalType,o=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),h=l(t),u=c,j=h["".concat(o,".").concat(u)]||h[u]||p[u]||a;return t?r.createElement(j,s(s({ref:n},d),{},{components:t})):r.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"},49124:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/teco-chat-6b4f31b3d961878efc5c506fc167df1f.png"}}]); \ No newline at end of file diff --git a/assets/js/daff1d93.268aa82a.js b/assets/js/daff1d93.59c68117.js similarity index 97% rename from assets/js/daff1d93.268aa82a.js rename to assets/js/daff1d93.59c68117.js index ed20363de..6f142b0b8 100644 --- a/assets/js/daff1d93.268aa82a.js +++ b/assets/js/daff1d93.59c68117.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1659],{99239:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>i,toc:()=>a});var t=r(85893),s=r(3905);const l={title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",slug:"book-leadership-and-self-deception",tags:["Book"]},o=void 0,i={permalink:"/book-leadership-and-self-deception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",source:"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",description:"\ucc45 \uc815\ubcf4",date:"2023-04-08T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 8\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:5.16,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",slug:"book-leadership-and-self-deception",tags:["Book"]},unlisted:!1,prevItem:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",permalink:"/tecochat-retrospective-1"},nextItem:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/innodb-lock"}},c={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18",id:"\uc790\uae30\uae30\ub9cc\uacfc-\uc790\uae30\ubc30\ubc18",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function b(e){const n={blockquote:"blockquote",br:"br",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",(0,t.jsx)(n.br,{}),"\n","\uc544\ube48\uc800\uc5f0\uad6c\uc18c"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc790\uae30\uae30\ub9cc\uacfc-\uc790\uae30\ubc30\ubc18",children:"\uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18"}),"\n",(0,t.jsx)(n.p,{children:"\ucc45\uc5d0\uc11c\ub294 \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc744 \ub2e4\ub8ec\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc790\uae30\uae30\ub9cc: \uc790\uc2e0\uc758 \ubb38\uc81c\ub97c \uc778\uc815\ud558\uc9c0 \uc54a\ub294 \uac83"}),"\n",(0,t.jsx)(n.li,{children:"\uc790\uae30\ubc30\ubc18: \ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ubb34\uc5b8\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uc744 \ubc18\ud558\ub294 \ud589\uc704"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc790\uae30\ubc30\ubc18\uc744 \ud55c\ub2e4\uba74 \uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uc5d0 \ube60\uc9c0\ub294 \uac83\uc744 \ucc45\uc5d0\uc11c\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac04\ub2e4\uace0 \ud45c\ud604\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\ucd5c\uadfc\uc5d0 \uc77d\uc740 \ucc45 \uc911 \uac00\uc7a5 \ub9c8\uc74c\uc774 \ubd88\ud3b8\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub807\uae30\uc5d0 \ub354\ub354\uc6b1 \ub098\uc5d0\uac8c \ud544\uc694\ud55c \ub0b4\uc6a9\uc774 \ub2f4\uaca8\uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\uc0b4\uba74\uc11c \ub9ce\uc740 \uc120\ud0dd\uc758 \uc21c\uac04\uc774 \uc874\uc7ac\ud588\uace0, \uadf8 \uc21c\uac04\ub9c8\ub2e4 \uc790\uae30\ubc30\ubc18\uc744 \ud0dd\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc791\uac8c\ub294 \uc9d1\uc548\uc77c\uc744 \ud574\uc57c \ud558\ub294\ub370 \ubab8\uc774 \uc870\uae08 \ud798\ub4e4\ub2e4\uace0 \ud558\uc9c0 \uc54a\uac70\ub098",(0,t.jsx)(n.br,{}),"\n","\ud06c\uac8c\ub294 \uc798\ubabb\uc744 \uc778\uc815\ud574\uc57c \ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uadf8\ub7ec\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub7f0 \uc0c1\ud669\uc774 \ubc18\ubcf5\ub418\uc5b4 \uacb0\uad6d \uc0c1\uc790 \uc548\uc5d0 \ub098 \uc790\uc2e0\uc744 \uac00\ub450\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ub354 \ub098\uc740 \uc0b6\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \uc9c0\uc18d\uc801\uc73c\ub85c \ud655\uc778\ud558\uace0, \uc0c1\uc790 \ubc16\uc73c\ub85c \ub098\uac00\ub824\ub294 \uc5f0\uc2b5\uc744 \ud574\uc57c\uaca0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub113\uc740 \uc2dc\uc120\uc744 \uac00\uc9c0\uace0, \ud56d\uc0c1 \ub0b4\uac00 \ud2c0\ub9b4 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc0dd\uac01\ud558\uace0 \uc0b4\uc544\uac00\uc790."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uc758 \uc0dd\uac01\uc740 \uc9c0\uc2dd\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc9c0\uc2dd\uc740 \uc0ac\ub791\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc0ac\ub791\uc740 \uc874\uc7ac\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc0dd\uac01\ud558\ub294 \ub098\ub294 \uc2e4\uc81c\uc758 \ub098\ubcf4\ub2e4 \uadf8\ub9cc\ud07c \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","R. D. \ub7ad",(0,t.jsx)(n.br,{}),"\n","p.19"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uac00 \uc678\uc801\uc73c\ub85c \uc5b4\ub5a4 \ud589\ub3d9\uc744 \ud558\ub4e0\uc9c0 \uac04\uc5d0, \uc0ac\ub78c\ub4e4\uc740 \uc6b0\ub9ac \ub9c8\uc74c\uc5d0\uc11c \uadf8\ub4e4\uc744 \uc5b4\ub5bb\uac8c \ub300\ud558\uace0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \uc8fc\ub85c \ubc18\uc751\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uac00 \uc0ac\ub78c\ub4e4\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \ub290\ub07c\uac8c \ub418\ub294\uc9c0\ub294 \uc6b0\ub9ac\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \ud639\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c0\uac8c \ub429\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.66"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ube44\ub09c\uc740 \uac10\uc815\uc5d0 \uc18d\ud558\uace0 \ub099\uad00\uc740 \uc758\uc9c0\uc5d0 \uc18d\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc778\uac04\uc740 \uac10\uc815\ubcf4\ub2e4 \ub354 \ud070 \uc874\uc7ac\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc54c\ub7ad, \ud0c1\ub2db\ud55c",(0,t.jsx)(n.br,{}),"\n","p.103"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uac00 \uc790\uc2e0\uc5d0\uac8c\ub9cc \uc9d1\uc911\ud558\uace0 \uc788\ub294 \ud55c, \ud63c\uc790\uc11c \uc77c\ud558\ub294 \uac83 \uc774\uc0c1\uc758 \ucc3d\uc870\uc801\uc778 \uacb0\uacfc\ub098 \ud611\ub825\uc744 \uc774\ub04c\uc5b4 \ub0b8\ub2e4\ub294 \uac83\uc740 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub298\ub0a0 \uacbd\uc81c \ud658\uacbd\uc5d0\uc11c\ub294 \ud63c\uc790\uc11c\ub294 \uc77c\uc758 \uacb0\uacfc\ub97c \ud0c1\uc6d4\ud558\uac8c \ub9cc\ub4e4\uc5b4 \ub0b4\uae30\uac00 \uc5b4\ub835\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub0b4\uac00 \uc911\uc2ec\uc774\uc5b4\uc57c \ub41c\ub2e4\ub294 \ud3d0\uc1c4\uc801\uc778 \uc0ac\uace0\ub294 \ud568\uaed8 \uc77c\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uc5f4\uc815\uc744 \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.175"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc194\uc9c1\ud568\uc740 \uc6b0\ub9ac\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\ub294 \uc5f4\uc1e0\uc785\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\uc740 \uc790\uc2e0\uc758 \ud589\ub3d9\uacfc \uad00\ub828\ub41c \uc0ac\ub78c\uc5d0 \ub300\ud574 \uae30\uaebc\uc774 \uc0ac\uacfc\ub97c \ud558\ub294 \uac83\uc785\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\ub9cc\uc774 \uc2e4\ud0c0\ub798\ucc98\ub7fc \uc5c9\ud0a8 \uad00\uacc4\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\uc8e0.",(0,t.jsx)(n.br,{}),"\n","p.188"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ub204\uad70\uac00\ub97c \ub098\uc640 \uac19\uc774 \ub3d9\uc77c\ud55c \uac00\uce58\ub97c \uc9c0\ub2cc \ud55c \uc778\uac04\uc73c\ub85c \uc0dd\uac01\ud574\uc11c \uadf8 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \ubc16\uc5d0 \uacc4\uc18d \uba38\ubb34\ub974\uace0 \uc2f6\uc740 \uc5f4\ub9dd\uc774 \uc0dd\uae38 \ub54c, \ub098\ub294 \uc774\ubbf8 \uadf8 \uc0ac\ub78c\uc5d0 \ub300\ud574 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.214"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ub300\ubd80\ubd84\uc758 \uc0ac\ub78c\ub4e4\uc774 \uad00\uacc4 \uae30\uc220\uc744 \uac00\uc9c0\uace0 \uadf8\ub4e4\uc774 \uacaa\uace0 \uc788\ub294 \ubb38\uc81c\ub97c \ubc14\ub85c\uc7a1\uc73c\ub824\uace0 \ud558\ub294 \ub178\ub825\uc774 \uacb0\uc2e4\uc744 \uc5bb\uc9c0 \ubabb\ud558\ub294 \uac83\uc740 \uacb0\ucf54 \uadf8\ub7ec\ud55c \uae30\uc220 \ubd80\uc871 \ub54c\ubb38\uc5d0 \uc0dd\uae30\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\ub4e4\uc740 \uc790\uae30\ubc30\ubc18 \ub54c\ubb38\uc5d0 \uc0dd\uaca8\ub0a9\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.224"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\ub294 \ud568\uaed8 \uc77c\ud558\uace0 \uc6b0\ub9ac\uc640 \ud568\uaed8 \uc0b4\uc544\uac00\ub294 \uc0ac\ub78c\uc774 \uc9c4\uc815\uc73c\ub85c \ub204\uad6c\uc778\uc9c0 \uc54c\uc9c0 \ubabb\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uac00 \uadf8\ub4e4\uacfc \uc9c4\uc815\uc73c\ub85c \ud568\uaed8 \uc18c\ud1b5\ud558\uae30 \uc804\uae4c\uc9c0\ub294 \uc6b0\ub9ac\ub294 \uadf8\ub4e4\uc758 \uac00\uce58\ub97c \uc798 \ubaa8\ub985\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc704\ub300\ud568\uc774\ub780 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc704\ub300\ud55c \uc810\uc744 \ubc1c\uacac\ud574 \uc8fc\ub294 \uac83\uc5d0 \uc788\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.280"]}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(b,{...e})}):b(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var c=t.createContext({}),a=function(e){var n=t.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},b={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,l=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),j=a(r),d=s,x=j["".concat(c,".").concat(d)]||j[d]||b[d]||l;return r?t.createElement(x,o(o({ref:n},p),{},{components:r})):t.createElement(x,o({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1659],{99239:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>i,toc:()=>a});var t=r(85893),s=r(3905);const l={title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",slug:"book-leadership-and-self-deception",tags:["Book"]},o=void 0,i={permalink:"/book-leadership-and-self-deception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",source:"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",description:"\ucc45 \uc815\ubcf4",date:"2023-04-08T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 8\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:5.16,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",slug:"book-leadership-and-self-deception",tags:["Book"]},unlisted:!1,prevItem:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/innodb-lock"},nextItem:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",permalink:"/tecochat-retrospective-1"}},c={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18",id:"\uc790\uae30\uae30\ub9cc\uacfc-\uc790\uae30\ubc30\ubc18",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function b(e){const n={blockquote:"blockquote",br:"br",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",(0,t.jsx)(n.br,{}),"\n","\uc544\ube48\uc800\uc5f0\uad6c\uc18c"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc790\uae30\uae30\ub9cc\uacfc-\uc790\uae30\ubc30\ubc18",children:"\uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18"}),"\n",(0,t.jsx)(n.p,{children:"\ucc45\uc5d0\uc11c\ub294 \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc744 \ub2e4\ub8ec\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc790\uae30\uae30\ub9cc: \uc790\uc2e0\uc758 \ubb38\uc81c\ub97c \uc778\uc815\ud558\uc9c0 \uc54a\ub294 \uac83"}),"\n",(0,t.jsx)(n.li,{children:"\uc790\uae30\ubc30\ubc18: \ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ubb34\uc5b8\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uc744 \ubc18\ud558\ub294 \ud589\uc704"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc790\uae30\ubc30\ubc18\uc744 \ud55c\ub2e4\uba74 \uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uc5d0 \ube60\uc9c0\ub294 \uac83\uc744 \ucc45\uc5d0\uc11c\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac04\ub2e4\uace0 \ud45c\ud604\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\ucd5c\uadfc\uc5d0 \uc77d\uc740 \ucc45 \uc911 \uac00\uc7a5 \ub9c8\uc74c\uc774 \ubd88\ud3b8\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub807\uae30\uc5d0 \ub354\ub354\uc6b1 \ub098\uc5d0\uac8c \ud544\uc694\ud55c \ub0b4\uc6a9\uc774 \ub2f4\uaca8\uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\uc0b4\uba74\uc11c \ub9ce\uc740 \uc120\ud0dd\uc758 \uc21c\uac04\uc774 \uc874\uc7ac\ud588\uace0, \uadf8 \uc21c\uac04\ub9c8\ub2e4 \uc790\uae30\ubc30\ubc18\uc744 \ud0dd\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc791\uac8c\ub294 \uc9d1\uc548\uc77c\uc744 \ud574\uc57c \ud558\ub294\ub370 \ubab8\uc774 \uc870\uae08 \ud798\ub4e4\ub2e4\uace0 \ud558\uc9c0 \uc54a\uac70\ub098",(0,t.jsx)(n.br,{}),"\n","\ud06c\uac8c\ub294 \uc798\ubabb\uc744 \uc778\uc815\ud574\uc57c \ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uadf8\ub7ec\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uac00 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ub7f0 \uc0c1\ud669\uc774 \ubc18\ubcf5\ub418\uc5b4 \uacb0\uad6d \uc0c1\uc790 \uc548\uc5d0 \ub098 \uc790\uc2e0\uc744 \uac00\ub450\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ub354 \ub098\uc740 \uc0b6\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \uc9c0\uc18d\uc801\uc73c\ub85c \ud655\uc778\ud558\uace0, \uc0c1\uc790 \ubc16\uc73c\ub85c \ub098\uac00\ub824\ub294 \uc5f0\uc2b5\uc744 \ud574\uc57c\uaca0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub113\uc740 \uc2dc\uc120\uc744 \uac00\uc9c0\uace0, \ud56d\uc0c1 \ub0b4\uac00 \ud2c0\ub9b4 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc0dd\uac01\ud558\uace0 \uc0b4\uc544\uac00\uc790."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uc758 \uc0dd\uac01\uc740 \uc9c0\uc2dd\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc9c0\uc2dd\uc740 \uc0ac\ub791\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc0ac\ub791\uc740 \uc874\uc7ac\ubcf4\ub2e4 \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc0dd\uac01\ud558\ub294 \ub098\ub294 \uc2e4\uc81c\uc758 \ub098\ubcf4\ub2e4 \uadf8\ub9cc\ud07c \uc791\ub2e4.",(0,t.jsx)(n.br,{}),"\n","R. D. \ub7ad",(0,t.jsx)(n.br,{}),"\n","p.19"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uac00 \uc678\uc801\uc73c\ub85c \uc5b4\ub5a4 \ud589\ub3d9\uc744 \ud558\ub4e0\uc9c0 \uac04\uc5d0, \uc0ac\ub78c\ub4e4\uc740 \uc6b0\ub9ac \ub9c8\uc74c\uc5d0\uc11c \uadf8\ub4e4\uc744 \uc5b4\ub5bb\uac8c \ub300\ud558\uace0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \uc8fc\ub85c \ubc18\uc751\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uac00 \uc0ac\ub78c\ub4e4\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \ub290\ub07c\uac8c \ub418\ub294\uc9c0\ub294 \uc6b0\ub9ac\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \ud639\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c0\uac8c \ub429\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.66"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ube44\ub09c\uc740 \uac10\uc815\uc5d0 \uc18d\ud558\uace0 \ub099\uad00\uc740 \uc758\uc9c0\uc5d0 \uc18d\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc778\uac04\uc740 \uac10\uc815\ubcf4\ub2e4 \ub354 \ud070 \uc874\uc7ac\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc54c\ub7ad, \ud0c1\ub2db\ud55c",(0,t.jsx)(n.br,{}),"\n","p.103"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\uac00 \uc790\uc2e0\uc5d0\uac8c\ub9cc \uc9d1\uc911\ud558\uace0 \uc788\ub294 \ud55c, \ud63c\uc790\uc11c \uc77c\ud558\ub294 \uac83 \uc774\uc0c1\uc758 \ucc3d\uc870\uc801\uc778 \uacb0\uacfc\ub098 \ud611\ub825\uc744 \uc774\ub04c\uc5b4 \ub0b8\ub2e4\ub294 \uac83\uc740 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc624\ub298\ub0a0 \uacbd\uc81c \ud658\uacbd\uc5d0\uc11c\ub294 \ud63c\uc790\uc11c\ub294 \uc77c\uc758 \uacb0\uacfc\ub97c \ud0c1\uc6d4\ud558\uac8c \ub9cc\ub4e4\uc5b4 \ub0b4\uae30\uac00 \uc5b4\ub835\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub0b4\uac00 \uc911\uc2ec\uc774\uc5b4\uc57c \ub41c\ub2e4\ub294 \ud3d0\uc1c4\uc801\uc778 \uc0ac\uace0\ub294 \ud568\uaed8 \uc77c\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uc5f4\uc815\uc744 \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.175"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc194\uc9c1\ud568\uc740 \uc6b0\ub9ac\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\ub294 \uc5f4\uc1e0\uc785\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\uc740 \uc790\uc2e0\uc758 \ud589\ub3d9\uacfc \uad00\ub828\ub41c \uc0ac\ub78c\uc5d0 \ub300\ud574 \uae30\uaebc\uc774 \uc0ac\uacfc\ub97c \ud558\ub294 \uac83\uc785\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\ub9cc\uc774 \uc2e4\ud0c0\ub798\ucc98\ub7fc \uc5c9\ud0a8 \uad00\uacc4\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\uc8e0.",(0,t.jsx)(n.br,{}),"\n","p.188"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ub204\uad70\uac00\ub97c \ub098\uc640 \uac19\uc774 \ub3d9\uc77c\ud55c \uac00\uce58\ub97c \uc9c0\ub2cc \ud55c \uc778\uac04\uc73c\ub85c \uc0dd\uac01\ud574\uc11c \uadf8 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \ubc16\uc5d0 \uacc4\uc18d \uba38\ubb34\ub974\uace0 \uc2f6\uc740 \uc5f4\ub9dd\uc774 \uc0dd\uae38 \ub54c, \ub098\ub294 \uc774\ubbf8 \uadf8 \uc0ac\ub78c\uc5d0 \ub300\ud574 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.214"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\ub300\ubd80\ubd84\uc758 \uc0ac\ub78c\ub4e4\uc774 \uad00\uacc4 \uae30\uc220\uc744 \uac00\uc9c0\uace0 \uadf8\ub4e4\uc774 \uacaa\uace0 \uc788\ub294 \ubb38\uc81c\ub97c \ubc14\ub85c\uc7a1\uc73c\ub824\uace0 \ud558\ub294 \ub178\ub825\uc774 \uacb0\uc2e4\uc744 \uc5bb\uc9c0 \ubabb\ud558\ub294 \uac83\uc740 \uacb0\ucf54 \uadf8\ub7ec\ud55c \uae30\uc220 \ubd80\uc871 \ub54c\ubb38\uc5d0 \uc0dd\uae30\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\uac83\ub4e4\uc740 \uc790\uae30\ubc30\ubc18 \ub54c\ubb38\uc5d0 \uc0dd\uaca8\ub0a9\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.224"]}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uc6b0\ub9ac\ub294 \ud568\uaed8 \uc77c\ud558\uace0 \uc6b0\ub9ac\uc640 \ud568\uaed8 \uc0b4\uc544\uac00\ub294 \uc0ac\ub78c\uc774 \uc9c4\uc815\uc73c\ub85c \ub204\uad6c\uc778\uc9c0 \uc54c\uc9c0 \ubabb\ud569\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uac00 \uadf8\ub4e4\uacfc \uc9c4\uc815\uc73c\ub85c \ud568\uaed8 \uc18c\ud1b5\ud558\uae30 \uc804\uae4c\uc9c0\ub294 \uc6b0\ub9ac\ub294 \uadf8\ub4e4\uc758 \uac00\uce58\ub97c \uc798 \ubaa8\ub985\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\ub9ac\uc758 \uc704\ub300\ud568\uc774\ub780 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc704\ub300\ud55c \uc810\uc744 \ubc1c\uacac\ud574 \uc8fc\ub294 \uac83\uc5d0 \uc788\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","p.280"]}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,s.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(b,{...e})}):b(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function s(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(s[r]=e[r]);return s}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(s[r]=e[r])}return s}var c=t.createContext({}),a=function(e){var n=t.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},b={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,s=e.mdxType,l=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),j=a(r),d=s,x=j["".concat(c,".").concat(d)]||j[d]||b[d]||l;return r?t.createElement(x,o(o({ref:n},p),{},{components:r})):t.createElement(x,o({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/db86613e.2f8f2d5c.js b/assets/js/db86613e.1dbc4bdd.js similarity index 97% rename from assets/js/db86613e.2f8f2d5c.js rename to assets/js/db86613e.1dbc4bdd.js index 803d1a903..bc75742d7 100644 --- a/assets/js/db86613e.2f8f2d5c.js +++ b/assets/js/db86613e.1dbc4bdd.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9458],{82549:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>i});var t=r(85893),l=r(3905);const a={title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"mysql-lock",tags:["DataBase","Lock","MySQL"]},c=void 0,s={permalink:"/mysql-lock",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",source:"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",description:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",date:"2023-04-06T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 6\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Lock",permalink:"/tags/lock"},{label:"MySQL",permalink:"/tags/my-sql"}],readingTime:4.405,hasTruncateMarker:!1,authors:[],frontMatter:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"mysql-lock",tags:["DataBase","Lock","MySQL"]},unlisted:!1,prevItem:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/innodb-lock"},nextItem:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",permalink:"/transaction-and-isolation"}},o={authorsImageUrls:[]},i=[{value:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",id:"mysql-\uc5d4\uc9c4\uc758-\uc7a0\uae08",level:2},{value:"\uae00\ub85c\ubc8c \ub77d(Global lock)",id:"\uae00\ub85c\ubc8c-\ub77dglobal-lock",level:3},{value:"\ud14c\uc774\ube14 \ub77d(Table lock)",id:"\ud14c\uc774\ube14-\ub77dtable-lock",level:3},{value:"\ub124\uc784\ub4dc \ub77d(Named lock)",id:"\ub124\uc784\ub4dc-\ub77dnamed-lock",level:3},{value:"\uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)",id:"\uba54\ud0c0\ub370\uc774\ud130-\ub77dmetadata-lock",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"mysql-\uc5d4\uc9c4\uc758-\uc7a0\uae08",children:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08"}),"\n",(0,t.jsxs)(n.p,{children:["MySQL\uc5d0\uc11c\uc758 \ub77d\uc740 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub808\ubca8\uacfc, MySQL \uc5d4\uc9c4 \ub808\ubca8\ub85c \ub098\ub20c \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL \uc5d4\uc9c4 \ub808\ubca8\uc758 \uc7a0\uae08\uc740 \ubaa8\ub4e0 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce5c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uae00\ub85c\ubc8c-\ub77dglobal-lock",children:"\uae00\ub85c\ubc8c \ub77d(Global lock)"}),"\n",(0,t.jsx)(n.p,{children:"MySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08 \uc911 \uac00\uc7a5 \ub113\uc740 \ubc94\uc704\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc7a0\uae08\uc774\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc601\ud5a5\uc744 \ubbf8\uce58\ub294 \ubc94\uc704\ub294 \ud574\ub2f9 \uc11c\ubc84 \uc804\uccb4\uc774\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc791\uc5c5 \ub300\uc0c1 \ud14c\uc774\ube14, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0c1\uad00 \uc5c6\uc774 \ub3d9\uc77c\ud558\uac8c \uc601\ud5a5\uc744 \ubc1b\ub294\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \uc138\uc158\uc5d0\uc11c \uae00\ub85c\ubc8c \ub77d\uc744 \ud68d\ub4dd\ud558\uba74 \ud574\uc81c \ub420 \ub54c \uae4c\uc9c0 \uc870\ud68c\ub97c \uc81c\uc678\ud55c \ub300\ubd80\ubd84\uc758 \uba85\ub839\uc774 \ub300\uae30 \uc0c1\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc874\uc7ac\ud558\ub294 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \ubc31\uc5c5\uc744 \ubc1b\uc544\uc57c\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c\ub294 \ubc31\uc5c5 \uc2dc \uc870\uae08 \ub354 \uac00\ubcbc\uc6b4 \ubc31\uc5c5 \ub77d\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- GLOBAL LOCK\nFLUSH TABLES WITH READ LOCK;\n-- UNLOCK\nUNLOCK TABLES;\n\n-- BACKUP LOCK\nLOCK INSTANCE FOR BACKUP;\n-- UNLOCK\nUNLOCK INSTANCE;\n"})}),"\n",(0,t.jsx)(n.admonition,{title:"MyISAM",type:"note",children:(0,t.jsxs)(n.p,{children:["MySQL 5.5 \ubc84\uc804 \uc774\uc804\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, SELECT \uc791\uc5c5 \uc18d\ub3c4\uac00 \ube60\ub974\ub2e4."]})}),"\n",(0,t.jsx)(n.h3,{id:"\ud14c\uc774\ube14-\ub77dtable-lock",children:"\ud14c\uc774\ube14 \ub77d(Table lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\uac1c\ubcc4 \ud14c\uc774\ube14 \ub2e8\uc704\ub85c \uc124\uc815\ub418\ub294 \uc7a0\uae08\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba85\uc2dc\uc801 \ub610\ub294 \ubb35\uc2dc\uc801\uc73c\ub85c \ud2b9\uc815 \ud14c\uc774\ube14\uc758 \ub77d\uc744 \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubb35\uc2dc\uc801 \ub77d\uc740 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub294 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uba74 \ubc1c\uc0dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB \ud14c\uc774\ube14\uc5d0\ub294 DML \ucffc\ub9ac\ub294 \ubb34\uc2dc\ub418\uace0 DDL \uc77c \uacbd\uc6b0\uc5d0\ub9cc \ubb35\uc2dc\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- TABLE LOCK\nLOCK TABLES table_name [ READ | WRITE ]\n\n-- UNLOCK\nUNLOCK TABLES;\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ub124\uc784\ub4dc-\ub77dnamed-lock",children:"\ub124\uc784\ub4dc \ub77d(Named lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc784\uc758\uc758 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc7a0\uae08\uc73c\ub85c \uc720\uc800 \ub808\ubca8 \ub77d\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc5ec\ub7ec \uc2a4\ub808\ub4dc\ub098 \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc77c\ud55c \ub370\uc774\ud130\ub97c \uc218\uc815\ud558\ub824\ub294 \uacbd\uc6b0, \ub3d9\uc2dc\uc5d0 \uc218\uc815\ud558\uc9c0 \ubabb\ud558\ub3c4\ub85d \ubcf4\ud638\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- aGVyYg== \ub77c\ub294 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08 \ud68d\ub4dd, \uc774\ubbf8 \uc7a0\uae08\uc744 \uc0ac\uc6a9\uc911\uc778 \uacbd\uc6b0 1\ucd08 \ub3d9\uc548\ub9cc \ub300\uae30\nSELECT GET_LOCK('aGVyYg==', 1);\n\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc774 \uc124\uc815\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.\nSELECT IS_FREE_LOCK('aGVyYg==');\n\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4.\nSELECT RELEASE_LOCK('aGVyYg==');\n\n-- \uc704 3\uac1c \ud568\uc218 \ubaa8\ub450 \uc815\uc0c1\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud558\uac70\ub098 \ud574\uc81c\ud55c \uacbd\uc6b0\uc5d0 1\uc744, \uc544\ub2c8\uba74 0\uc744 \ubc18\ud658\ud55c\ub2e4.\n\n-- \ubaa8\ub4e0 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4. \ud574\uc81c\ub41c \uc7a0\uae08\uc758 \uac1c\uc218\ub97c \ubc18\ud658\ud55c\ub2e4.\nSELECT RELEASE_ALL_LOCKS();\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uba54\ud0c0\ub370\uc774\ud130-\ub77dmetadata-lock",children:"\uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac1d\uccb4\uc758 \uc774\ub984\uc774\ub098 \uad6c\uc870\ub97c \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \ud68d\ub4dd\ud558\ub294 \uc7a0\uae08\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba85\uc2dc\uc801\uc73c\ub85c \ud68d\ub4dd \ub610\ub294 \ud574\uc81c \ud560 \uc218 \uc5c6\uc9c0\ub9cc \ud14c\uc774\ube14\uc758 \uc774\ub984\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubcf4\ud1b5 \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ud14c\uc774\ube14\uc744 \ubc14\uafd4\uc57c\ud558\ub294 \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ubcc4\ub3c4\uc758 \uc784\uc2dc \ud14c\uc774\ube14\uc5d0 \uc11c\ube44\uc2a4\uc6a9 \ub7ad\ud0b9 \ub370\uc774\ud130 \uc0dd\uc131 \ud6c4 \uae30\uc874 \ud14c\uc774\ube14\uc744 \ubc31\uc5c5\ud558\ub294 \uacbd\uc6b0\n-- \uc544\ub798 \uad6c\ubb38 \uc2e4\ud589 \uc2dc \uba54\ud0c0\ub370\uc774\ud130 \ub77d\uc744 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.\nRENAME TABLE rank TO rank_backup, rank_new TO rank;\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://gywn.net/2013/12/mysql-user-level-lock/",children:"MySQL\uc758 User Level Lock\ub97c \ud65c\uc6a9\ud55c\ub2e4\uba74?, gywndi"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html#function_release-all-locks",children:"Locking Functions, MySQL 5.7 Reference"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks",children:"Locking Functions, MySQL 8.0 Reference"})]})]})}function p(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>i});var t=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function c(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var o=t.createContext({}),i=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):c(c({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,l=e.mdxType,a=e.originalType,o=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=i(r),m=l,h=u["".concat(o,".").concat(m)]||u[m]||d[m]||a;return r?t.createElement(h,c(c({ref:n},p),{},{components:r})):t.createElement(h,c({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9458],{82549:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>i});var t=r(85893),l=r(3905);const a={title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"mysql-lock",tags:["DataBase","Lock","MySQL"]},c=void 0,s={permalink:"/mysql-lock",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",source:"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",description:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",date:"2023-04-06T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 6\uc77c",tags:[{label:"DataBase",permalink:"/tags/data-base"},{label:"Lock",permalink:"/tags/lock"},{label:"MySQL",permalink:"/tags/my-sql"}],readingTime:4.405,hasTruncateMarker:!1,authors:[],frontMatter:{title:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",slug:"mysql-lock",tags:["DataBase","Lock","MySQL"]},unlisted:!1,prevItem:{title:"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900",permalink:"/transaction-and-isolation"},nextItem:{title:"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08",permalink:"/innodb-lock"}},o={authorsImageUrls:[]},i=[{value:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08",id:"mysql-\uc5d4\uc9c4\uc758-\uc7a0\uae08",level:2},{value:"\uae00\ub85c\ubc8c \ub77d(Global lock)",id:"\uae00\ub85c\ubc8c-\ub77dglobal-lock",level:3},{value:"\ud14c\uc774\ube14 \ub77d(Table lock)",id:"\ud14c\uc774\ube14-\ub77dtable-lock",level:3},{value:"\ub124\uc784\ub4dc \ub77d(Named lock)",id:"\ub124\uc784\ub4dc-\ub77dnamed-lock",level:3},{value:"\uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)",id:"\uba54\ud0c0\ub370\uc774\ud130-\ub77dmetadata-lock",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"mysql-\uc5d4\uc9c4\uc758-\uc7a0\uae08",children:"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08"}),"\n",(0,t.jsxs)(n.p,{children:["MySQL\uc5d0\uc11c\uc758 \ub77d\uc740 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub808\ubca8\uacfc, MySQL \uc5d4\uc9c4 \ub808\ubca8\ub85c \ub098\ub20c \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","MySQL \uc5d4\uc9c4 \ub808\ubca8\uc758 \uc7a0\uae08\uc740 \ubaa8\ub4e0 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce5c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\uae00\ub85c\ubc8c-\ub77dglobal-lock",children:"\uae00\ub85c\ubc8c \ub77d(Global lock)"}),"\n",(0,t.jsx)(n.p,{children:"MySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08 \uc911 \uac00\uc7a5 \ub113\uc740 \ubc94\uc704\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc7a0\uae08\uc774\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc601\ud5a5\uc744 \ubbf8\uce58\ub294 \ubc94\uc704\ub294 \ud574\ub2f9 \uc11c\ubc84 \uc804\uccb4\uc774\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"\uc791\uc5c5 \ub300\uc0c1 \ud14c\uc774\ube14, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0c1\uad00 \uc5c6\uc774 \ub3d9\uc77c\ud558\uac8c \uc601\ud5a5\uc744 \ubc1b\ub294\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud55c \uc138\uc158\uc5d0\uc11c \uae00\ub85c\ubc8c \ub77d\uc744 \ud68d\ub4dd\ud558\uba74 \ud574\uc81c \ub420 \ub54c \uae4c\uc9c0 \uc870\ud68c\ub97c \uc81c\uc678\ud55c \ub300\ubd80\ubd84\uc758 \uba85\ub839\uc774 \ub300\uae30 \uc0c1\ud0dc\uac00 \ub41c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc874\uc7ac\ud558\ub294 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \ubc31\uc5c5\uc744 \ubc1b\uc544\uc57c\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c\ub294 \ubc31\uc5c5 \uc2dc \uc870\uae08 \ub354 \uac00\ubcbc\uc6b4 \ubc31\uc5c5 \ub77d\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- GLOBAL LOCK\nFLUSH TABLES WITH READ LOCK;\n-- UNLOCK\nUNLOCK TABLES;\n\n-- BACKUP LOCK\nLOCK INSTANCE FOR BACKUP;\n-- UNLOCK\nUNLOCK INSTANCE;\n"})}),"\n",(0,t.jsx)(n.admonition,{title:"MyISAM",type:"note",children:(0,t.jsxs)(n.p,{children:["MySQL 5.5 \ubc84\uc804 \uc774\uc804\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud2b8\ub79c\uc7ad\uc158\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, SELECT \uc791\uc5c5 \uc18d\ub3c4\uac00 \ube60\ub974\ub2e4."]})}),"\n",(0,t.jsx)(n.h3,{id:"\ud14c\uc774\ube14-\ub77dtable-lock",children:"\ud14c\uc774\ube14 \ub77d(Table lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\uac1c\ubcc4 \ud14c\uc774\ube14 \ub2e8\uc704\ub85c \uc124\uc815\ub418\ub294 \uc7a0\uae08\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba85\uc2dc\uc801 \ub610\ub294 \ubb35\uc2dc\uc801\uc73c\ub85c \ud2b9\uc815 \ud14c\uc774\ube14\uc758 \ub77d\uc744 \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubb35\uc2dc\uc801 \ub77d\uc740 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub294 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uba74 \ubc1c\uc0dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","InnoDB \ud14c\uc774\ube14\uc5d0\ub294 DML \ucffc\ub9ac\ub294 \ubb34\uc2dc\ub418\uace0 DDL \uc77c \uacbd\uc6b0\uc5d0\ub9cc \ubb35\uc2dc\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- TABLE LOCK\nLOCK TABLES table_name [ READ | WRITE ]\n\n-- UNLOCK\nUNLOCK TABLES;\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ub124\uc784\ub4dc-\ub77dnamed-lock",children:"\ub124\uc784\ub4dc \ub77d(Named lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\uc784\uc758\uc758 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc7a0\uae08\uc73c\ub85c \uc720\uc800 \ub808\ubca8 \ub77d\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc5ec\ub7ec \uc2a4\ub808\ub4dc\ub098 \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc77c\ud55c \ub370\uc774\ud130\ub97c \uc218\uc815\ud558\ub824\ub294 \uacbd\uc6b0, \ub3d9\uc2dc\uc5d0 \uc218\uc815\ud558\uc9c0 \ubabb\ud558\ub3c4\ub85d \ubcf4\ud638\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- aGVyYg== \ub77c\ub294 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08 \ud68d\ub4dd, \uc774\ubbf8 \uc7a0\uae08\uc744 \uc0ac\uc6a9\uc911\uc778 \uacbd\uc6b0 1\ucd08 \ub3d9\uc548\ub9cc \ub300\uae30\nSELECT GET_LOCK('aGVyYg==', 1);\n\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc774 \uc124\uc815\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.\nSELECT IS_FREE_LOCK('aGVyYg==');\n\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4.\nSELECT RELEASE_LOCK('aGVyYg==');\n\n-- \uc704 3\uac1c \ud568\uc218 \ubaa8\ub450 \uc815\uc0c1\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud558\uac70\ub098 \ud574\uc81c\ud55c \uacbd\uc6b0\uc5d0 1\uc744, \uc544\ub2c8\uba74 0\uc744 \ubc18\ud658\ud55c\ub2e4.\n\n-- \ubaa8\ub4e0 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4. \ud574\uc81c\ub41c \uc7a0\uae08\uc758 \uac1c\uc218\ub97c \ubc18\ud658\ud55c\ub2e4.\nSELECT RELEASE_ALL_LOCKS();\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\uba54\ud0c0\ub370\uc774\ud130-\ub77dmetadata-lock",children:"\uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)"}),"\n",(0,t.jsxs)(n.p,{children:["\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac1d\uccb4\uc758 \uc774\ub984\uc774\ub098 \uad6c\uc870\ub97c \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \ud68d\ub4dd\ud558\ub294 \uc7a0\uae08\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uba85\uc2dc\uc801\uc73c\ub85c \ud68d\ub4dd \ub610\ub294 \ud574\uc81c \ud560 \uc218 \uc5c6\uc9c0\ub9cc \ud14c\uc774\ube14\uc758 \uc774\ub984\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubcf4\ud1b5 \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ud14c\uc774\ube14\uc744 \ubc14\uafd4\uc57c\ud558\ub294 \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"-- \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ubcc4\ub3c4\uc758 \uc784\uc2dc \ud14c\uc774\ube14\uc5d0 \uc11c\ube44\uc2a4\uc6a9 \ub7ad\ud0b9 \ub370\uc774\ud130 \uc0dd\uc131 \ud6c4 \uae30\uc874 \ud14c\uc774\ube14\uc744 \ubc31\uc5c5\ud558\ub294 \uacbd\uc6b0\n-- \uc544\ub798 \uad6c\ubb38 \uc2e4\ud589 \uc2dc \uba54\ud0c0\ub370\uc774\ud130 \ub77d\uc744 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.\nRENAME TABLE rank TO rank_backup, rank_new TO rank;\n"})}),"\n",(0,t.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:["Real My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://gywn.net/2013/12/mysql-user-level-lock/",children:"MySQL\uc758 User Level Lock\ub97c \ud65c\uc6a9\ud55c\ub2e4\uba74?, gywndi"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html#function_release-all-locks",children:"Locking Functions, MySQL 5.7 Reference"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks",children:"Locking Functions, MySQL 8.0 Reference"})]})]})}function p(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>i});var t=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function c(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var o=t.createContext({}),i=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):c(c({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,l=e.mdxType,a=e.originalType,o=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=i(r),m=l,h=u["".concat(o,".").concat(m)]||u[m]||d[m]||a;return r?t.createElement(h,c(c({ref:n},p),{},{components:r})):t.createElement(h,c({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/dca6a1e3.52680b40.js b/assets/js/dca6a1e3.e9780e39.js similarity index 97% rename from assets/js/dca6a1e3.52680b40.js rename to assets/js/dca6a1e3.e9780e39.js index 251dcc185..53ff2c9d8 100644 --- a/assets/js/dca6a1e3.52680b40.js +++ b/assets/js/dca6a1e3.e9780e39.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3239],{25386:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var n=t(85893),o=t(3905);const i={title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",slug:"level2-interview-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,s={permalink:"/level2-interview-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",description:"\ub808\ubca8 \uc778\ud130\ubdf0",date:"2023-06-08T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 8\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.435,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",slug:"level2-interview-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",permalink:"/woowacourse-level2-retrospective"},nextItem:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",permalink:"/order-retrospective"}},a={authorsImageUrls:[]},l=[{value:"\ub808\ubca8 \uc778\ud130\ubdf0",id:"\ub808\ubca8-\uc778\ud130\ubdf0",level:3},{value:"API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd",id:"api-\ubb38\uc11c-\ub3c4\uad6c-\uc120\ud0dd",level:3},{value:"PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158",id:"put\uacfc-patch--\ud1a0\ud070\uacfc-\uc138\uc158",level:3},{value:"\uadf8 \uc678 \uac1c\uc120\ud560 \uc810",id:"\uadf8-\uc678-\uac1c\uc120\ud560-\uc810",level:3}];function p(e){const r={blockquote:"blockquote",br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.h3,{id:"\ub808\ubca8-\uc778\ud130\ubdf0",children:"\ub808\ubca8 \uc778\ud130\ubdf0"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 1 \ub54c\ub294 \uc900\ube44\ud574\ub454 \ub0b4\uc6a9\uc73c\ub85c \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud574\uc11c \uadf8\ub807\uac8c \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc774 \uc5c6\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \ub808\ubca8 1 \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0\ub294 \ub808\ubca8 1 \ud68c\uace0\ub97c \uc791\uc131\ud560 \ub54c \ub07c\uc6cc\ub123\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \ubc94\uc704\ub3c4 \uc81c\ud55c\ub418\uc5b4 \uc788\uc5b4 \uc5b4\ub5bb\uac8c \uc900\ube44\ud574\uc57c \ud560\uc9c0 \ub2f9\ud669\ud588\uace0, \ub2f5\ubcc0\uc5d0\ub3c4 \ubd80\uc871\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uae30\uc5b5\uc774 \uc0ac\ub77c\uc9c0\uae30 \uc804\uc5d0 \ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\ud55c \ub0b4\uc6a9\uc744 \uc81c\uc678\ud558\uace0, \uae30\uc5b5 \ub0a8\ub294 \uac83 \uc704\uc8fc\ub85c \uc791\uc131\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"api-\ubb38\uc11c-\ub3c4\uad6c-\uc120\ud0dd",children:"API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd"}),"\n",(0,n.jsxs)(r.p,{children:["\ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\uc744 \ud588\ub294\ub370 \uc55e\uc73c\ub85c\ub3c4 \ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \ud558\uba74\uc11c \ub3c4\uc6c0 \ub420 \uac83 \uac19\uc740 \ub0b4\uc6a9\uc774 \uc788\uc5b4\uc11c \ub0a8\uaca8\ub450\ub824\uace0 \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc31\uc5d4\ub4dc \ud300\uc6d0\uc774 \ud568\uaed8 \uc758\uc0ac\uacb0\uc815\uc744 \ud588\uace0, \ubbf8\uc158 \uae30\uac04\uc774 \uc9e7\uc740 \ub9cc\ud07c \ud300 \ucc28\uc6d0\uc5d0\uc11c \ube44\uad50\uc801 \ud559\uc2b5\ud558\uae30 \uc26c\uc6b4 Swagger\ub97c \uc120\ud0dd\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ucd94\uac00\ub85c \ub4e4\uc5b4\uac00\ub294 \uc2dc\uac04 \ub300\ube44 \ud558\uc774 \ub9ac\ud134\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4\uace0 \ub2f5\ubcc0\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ud300 \ucc28\uc6d0\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uc5b8\uae09\ud574\uc11c, \ub2e4\uc74c\uacfc \uac19\uc740 \uc88b\uc740 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4."}),"\n",(0,n.jsxs)(r.blockquote,{children:["\n",(0,n.jsxs)(r.p,{children:["\ud2b9\ud788 \ud300\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\ud558\ub294 \uacfc\uc815\uc744 \uacf5\uc720\ud574 \uc900 \uc810\uc774 \uc88b\uc558\uace0 \uae30\uc220\uc801 \uc758\uc0ac\uacb0\uc815 \uacfc\uc815\uc5d0\uc11c \ud300\uc758 \ud559\uc2b5\ube44\uc6a9\uc744 \uace0\ub824\ud55c \uc810\uc774 \uc88b\uc558\uc74c.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c\ub3c4 \ud559\uc2b5 \ube44\uc6a9\uc740 \uc8fc\uc694\ud558\uac8c \uace0\ub824\ud574\uc57c \ud560 \uc0ac\ud56d"]}),"\n"]}),"\n",(0,n.jsx)(r.h3,{id:"put\uacfc-patch--\ud1a0\ud070\uacfc-\uc138\uc158",children:"PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["PUT\uacfc PATCH \ucc28\uc774\ub97c \uc124\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c\ub294 PATCH\ub97c \uc0ac\uc6a9\ud560 \ub54c \ud398\uc774\ub85c\ub4dc\uac00 \uc801\uc5b4\uc9c4\ub2e4\ub294 \ub0b4\uc6a9\uc744 \ube7c\uba39\uace0 \ub2f5\ubcc0\uc744 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud1a0\ud070\uacfc \uc138\uc158\uc758 \uacbd\uc6b0 \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud574\ub2ec\ub77c\ub294 \uc81c\uc57d\uc870\uac74\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ud574\ub2f9 \ub0b4\uc6a9\uc744 \ub2f5\ubcc0\ud558\uba74\uc11c \uae30\uc220\uc801\uc778 \uae4a\uc774\uac00 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc2e4\uc81c\ub85c \ub808\ubca8 2 \ub54c \uc774\ub860\uc801\uc778 \ud559\uc2b5 \uc2dc\uac04\uc774 \ub9e4\uc6b0 \uc801\uc5c8\uace0, \uc9d1\uc911\ub825\ub3c4 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc5b4\ub5bb\uac8c \uae4a\uc774\ub97c \ucc44\uc6b8\uc9c0 \uace0\ubbfc\uc744 \ud560 \uc218 \uc788\ub294 \uc9c8\ubb38\ub4e4\uc774\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ucd94\uac00\ub85c \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud558\ub294 \uac00\uc815\uc744 \ub450\uace0 \ud559\uc2b5\uc744 \ud55c\ub2e4\uba74 \ud070 \ub3c4\uc6c0\uc774 \ub420 \uac70\ub77c\ub294 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4."}),"\n",(0,n.jsx)(r.h3,{id:"\uadf8-\uc678-\uac1c\uc120\ud560-\uc810",children:"\uadf8 \uc678 \uac1c\uc120\ud560 \uc810"}),"\n",(0,n.jsxs)(r.p,{children:["\uc778\ud130\ubdf0\ud560 \ub54c \ud2b9\uc720\uc758 \ub9d0\ubc84\ub987\uc744 \uac1c\uc120\ud558\uae30",(0,n.jsx)(r.br,{}),"\n",'\uc0dd\uac01\ud560 \uc2dc\uac04\uc744 \uac00\uc84c\uc744 \ub54c "\ub2e4\uc2dc \ub9d0\uc500\ub4dc\ub824\ub3c4 \ub420\uae4c\uc694?"\ub77c\uace0 \ub9d0\ud558\uace0 \ub2f5\ubcc0\uc744 \uc774\uc5b4\ub098\uac00\uae30',(0,n.jsx)(r.br,{}),"\n","\uae30\uc220\uc801\uc73c\ub85c \uae4a\uc774\uac00 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5b4\uc11c \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\uae30",(0,n.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0 \uacf5\ubd80\ud588\ub358\uac70 \ub418\ub3cc\uc544 \ubcf4\ub294 \uc2dc\uac04 \uac00\uc9c0\uae30"]})]})}function u(e={}){const{wrapper:r}={...(0,o.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,a=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),b=l(t),h=o,d=b["".concat(a,".").concat(h)]||b[h]||p[h]||i;return t?n.createElement(d,c(c({ref:r},u),{},{components:t})):n.createElement(d,c({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3239],{25386:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var n=t(85893),o=t(3905);const i={title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",slug:"level2-interview-retrospective",tags:["Woowahan Techcourse","Retrospective"]},c=void 0,s={permalink:"/level2-interview-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",source:"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",description:"\ub808\ubca8 \uc778\ud130\ubdf0",date:"2023-06-08T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 8\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:3.435,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0",slug:"level2-interview-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0",permalink:"/order-retrospective"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0",permalink:"/woowacourse-level2-retrospective"}},a={authorsImageUrls:[]},l=[{value:"\ub808\ubca8 \uc778\ud130\ubdf0",id:"\ub808\ubca8-\uc778\ud130\ubdf0",level:3},{value:"API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd",id:"api-\ubb38\uc11c-\ub3c4\uad6c-\uc120\ud0dd",level:3},{value:"PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158",id:"put\uacfc-patch--\ud1a0\ud070\uacfc-\uc138\uc158",level:3},{value:"\uadf8 \uc678 \uac1c\uc120\ud560 \uc810",id:"\uadf8-\uc678-\uac1c\uc120\ud560-\uc810",level:3}];function p(e){const r={blockquote:"blockquote",br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.h3,{id:"\ub808\ubca8-\uc778\ud130\ubdf0",children:"\ub808\ubca8 \uc778\ud130\ubdf0"}),"\n",(0,n.jsxs)(r.p,{children:["\ub808\ubca8 1 \ub54c\ub294 \uc900\ube44\ud574\ub454 \ub0b4\uc6a9\uc73c\ub85c \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud574\uc11c \uadf8\ub807\uac8c \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc774 \uc5c6\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ub530\ub77c\uc11c \ub808\ubca8 1 \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0\ub294 \ub808\ubca8 1 \ud68c\uace0\ub97c \uc791\uc131\ud560 \ub54c \ub07c\uc6cc\ub123\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc774\ubc88\uc5d0\ub294 \ubc94\uc704\ub3c4 \uc81c\ud55c\ub418\uc5b4 \uc788\uc5b4 \uc5b4\ub5bb\uac8c \uc900\ube44\ud574\uc57c \ud560\uc9c0 \ub2f9\ud669\ud588\uace0, \ub2f5\ubcc0\uc5d0\ub3c4 \ubd80\uc871\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uae30\uc5b5\uc774 \uc0ac\ub77c\uc9c0\uae30 \uc804\uc5d0 \ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\ud55c \ub0b4\uc6a9\uc744 \uc81c\uc678\ud558\uace0, \uae30\uc5b5 \ub0a8\ub294 \uac83 \uc704\uc8fc\ub85c \uc791\uc131\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,n.jsx)(r.h3,{id:"api-\ubb38\uc11c-\ub3c4\uad6c-\uc120\ud0dd",children:"API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd"}),"\n",(0,n.jsxs)(r.p,{children:["\ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\uc744 \ud588\ub294\ub370 \uc55e\uc73c\ub85c\ub3c4 \ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \ud558\uba74\uc11c \ub3c4\uc6c0 \ub420 \uac83 \uac19\uc740 \ub0b4\uc6a9\uc774 \uc788\uc5b4\uc11c \ub0a8\uaca8\ub450\ub824\uace0 \ud55c\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ubc31\uc5d4\ub4dc \ud300\uc6d0\uc774 \ud568\uaed8 \uc758\uc0ac\uacb0\uc815\uc744 \ud588\uace0, \ubbf8\uc158 \uae30\uac04\uc774 \uc9e7\uc740 \ub9cc\ud07c \ud300 \ucc28\uc6d0\uc5d0\uc11c \ube44\uad50\uc801 \ud559\uc2b5\ud558\uae30 \uc26c\uc6b4 Swagger\ub97c \uc120\ud0dd\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ucd94\uac00\ub85c \ub4e4\uc5b4\uac00\ub294 \uc2dc\uac04 \ub300\ube44 \ud558\uc774 \ub9ac\ud134\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4\uace0 \ub2f5\ubcc0\ud588\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ud300 \ucc28\uc6d0\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uc5b8\uae09\ud574\uc11c, \ub2e4\uc74c\uacfc \uac19\uc740 \uc88b\uc740 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4."}),"\n",(0,n.jsxs)(r.blockquote,{children:["\n",(0,n.jsxs)(r.p,{children:["\ud2b9\ud788 \ud300\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\ud558\ub294 \uacfc\uc815\uc744 \uacf5\uc720\ud574 \uc900 \uc810\uc774 \uc88b\uc558\uace0 \uae30\uc220\uc801 \uc758\uc0ac\uacb0\uc815 \uacfc\uc815\uc5d0\uc11c \ud300\uc758 \ud559\uc2b5\ube44\uc6a9\uc744 \uace0\ub824\ud55c \uc810\uc774 \uc88b\uc558\uc74c.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c\ub3c4 \ud559\uc2b5 \ube44\uc6a9\uc740 \uc8fc\uc694\ud558\uac8c \uace0\ub824\ud574\uc57c \ud560 \uc0ac\ud56d"]}),"\n"]}),"\n",(0,n.jsx)(r.h3,{id:"put\uacfc-patch--\ud1a0\ud070\uacfc-\uc138\uc158",children:"PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158"}),"\n",(0,n.jsxs)(r.p,{children:["PUT\uacfc PATCH \ucc28\uc774\ub97c \uc124\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c\ub294 PATCH\ub97c \uc0ac\uc6a9\ud560 \ub54c \ud398\uc774\ub85c\ub4dc\uac00 \uc801\uc5b4\uc9c4\ub2e4\ub294 \ub0b4\uc6a9\uc744 \ube7c\uba39\uace0 \ub2f5\ubcc0\uc744 \ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\ud1a0\ud070\uacfc \uc138\uc158\uc758 \uacbd\uc6b0 \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud574\ub2ec\ub77c\ub294 \uc81c\uc57d\uc870\uac74\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."]}),"\n",(0,n.jsxs)(r.p,{children:["\ud574\ub2f9 \ub0b4\uc6a9\uc744 \ub2f5\ubcc0\ud558\uba74\uc11c \uae30\uc220\uc801\uc778 \uae4a\uc774\uac00 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc2e4\uc81c\ub85c \ub808\ubca8 2 \ub54c \uc774\ub860\uc801\uc778 \ud559\uc2b5 \uc2dc\uac04\uc774 \ub9e4\uc6b0 \uc801\uc5c8\uace0, \uc9d1\uc911\ub825\ub3c4 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4.",(0,n.jsx)(r.br,{}),"\n","\uc55e\uc73c\ub85c \uc5b4\ub5bb\uac8c \uae4a\uc774\ub97c \ucc44\uc6b8\uc9c0 \uace0\ubbfc\uc744 \ud560 \uc218 \uc788\ub294 \uc9c8\ubb38\ub4e4\uc774\uc5c8\ub2e4."]}),"\n",(0,n.jsx)(r.p,{children:"\ucd94\uac00\ub85c \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud558\ub294 \uac00\uc815\uc744 \ub450\uace0 \ud559\uc2b5\uc744 \ud55c\ub2e4\uba74 \ud070 \ub3c4\uc6c0\uc774 \ub420 \uac70\ub77c\ub294 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4."}),"\n",(0,n.jsx)(r.h3,{id:"\uadf8-\uc678-\uac1c\uc120\ud560-\uc810",children:"\uadf8 \uc678 \uac1c\uc120\ud560 \uc810"}),"\n",(0,n.jsxs)(r.p,{children:["\uc778\ud130\ubdf0\ud560 \ub54c \ud2b9\uc720\uc758 \ub9d0\ubc84\ub987\uc744 \uac1c\uc120\ud558\uae30",(0,n.jsx)(r.br,{}),"\n",'\uc0dd\uac01\ud560 \uc2dc\uac04\uc744 \uac00\uc84c\uc744 \ub54c "\ub2e4\uc2dc \ub9d0\uc500\ub4dc\ub824\ub3c4 \ub420\uae4c\uc694?"\ub77c\uace0 \ub9d0\ud558\uace0 \ub2f5\ubcc0\uc744 \uc774\uc5b4\ub098\uac00\uae30',(0,n.jsx)(r.br,{}),"\n","\uae30\uc220\uc801\uc73c\ub85c \uae4a\uc774\uac00 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5b4\uc11c \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\uae30",(0,n.jsx)(r.br,{}),"\n","\uc774\uc804\uc5d0 \uacf5\ubd80\ud588\ub358\uac70 \ub418\ub3cc\uc544 \ubcf4\ub294 \uc2dc\uac04 \uac00\uc9c0\uae30"]})]})}function u(e={}){const{wrapper:r}={...(0,o.ah)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},3905:(e,r,t)=>{t.d(r,{ah:()=>l});var n=t(67294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var a=n.createContext({}),l=function(e){var r=n.useContext(a),t=r;return e&&(t="function"==typeof e?e(r):c(c({},r),e)),t},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,a=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),b=l(t),h=o,d=b["".concat(a,".").concat(h)]||b[h]||p[h]||i;return t?n.createElement(d,c(c({ref:r},u),{},{components:t})):n.createElement(d,c({ref:r},u))}));u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/df147deb.ff087a25.js b/assets/js/df147deb.fd934096.js similarity index 98% rename from assets/js/df147deb.ff087a25.js rename to assets/js/df147deb.fd934096.js index dc020866d..4baa86d14 100644 --- a/assets/js/df147deb.ff087a25.js +++ b/assets/js/df147deb.fd934096.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5103],{43420:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>x,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var t=r(85893),a=r(3905);const s={title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",slug:"ladder-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,l={permalink:"/ladder-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-ladder/pull/97",date:"2023-02-26T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 26\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:10.285,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",slug:"ladder-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",permalink:"/blackjack-retrospective"},nextItem:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",permalink:"/racing-car-retrospective"}},o={authorsImageUrls:[]},d=[{value:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30",id:"\uc0ac\ub2e4\ub9ac-\ud0c0\uae30",level:3},{value:"Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95",id:"position-\uae30\uc900\uc73c\ub85c-\uc0ac\ub2e4\ub9ac-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",level:3},{value:"Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95",id:"player\uc5d0\uac8c-ladder\ub97c-\uc804\ub2ec\ud558\uc5ec-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function c(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",del:"del",h3:"h3",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/java-ladder/pull/97",children:"https://github.com/woowacourse/java-ladder/pull/97"}),(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/java-ladder/pull/234",children:"https://github.com/woowacourse/java-ladder/pull/234"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc0ac\ub2e4\ub9ac-\ud0c0\uae30",children:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc6b0\uac00\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uc804 \ubbf8\uc158\uacfc \ub2ec\ub9ac TDD\ub85c \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ud544\uc218\uc600\uae30 \ub54c\ubb38\uc5d0 \uc775\uc219\ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, \uc6b0\uac00\uc640 \ubbf8\uc158\uc5d0 \uad00\ud55c \uc18c\ud1b5\uc774 \uc798 \ub418\uc5b4\uc11c \ud070 \ubb38\uc81c \uc5c6\uc774 \ubbf8\uc158\uc744 \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uc6b0\uac00\uc640 \uc774\uc57c\uae30\uac00 \uc798 \ud1b5\ud574\uc11c \uadf8\ub7f0\uc9c0 1\ub2e8\uacc4\ub294 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub294\ub370, 2\ub2e8\uacc4\uc5d0\uc11c \ub9ce\uc774 \uace0\uc804\ud55c \uac83 \uac19\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"2\ub2e8\uacc4\uc5d0\uc11c\ub294 2\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ud574\ubd24\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"LadderGame\uc5d0\uc11c Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.li,{children:"Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c Ladder\uc5d0\uac8c Position\uc744 \ub118\uaca8\uc8fc\uba70 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"position-\uae30\uc900\uc73c\ub85c-\uc0ac\ub2e4\ub9ac-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",children:"Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsxs)(n.p,{children:["\uc0ac\uc2e4\uc0c1 index\ub97c Ladder\uc5d0\uac8c \ub118\uaca8\uc8fc\uace0, \ud574\ub2f9 index\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc1b\ub294 \ubc29\ubc95\uacfc \uc720\uc0ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uad6c\ud604\ud558\uace0 \ub098\ub2c8 \ub2e4\ub978 \ud074\ub798\uc2a4\ub4e4\uc774 Position\uc5d0 \ub300\ud55c \uc758\uc874\ub3c4\uac00 \ub108\ubb34 \ub192\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c Players\uac00 \ubcc4\ub2e4\ub978 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\ub2e4\uace0 \ub290\uaf08\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph TD\n\n LadderGameController --\x3e LadderGame\n LadderGame --\x3e Ladder\n LadderGame --\x3e Players\n LadderGame --\x3e Items\n\n Ladder --\x3e Line\n Line --\x3e LineStatus\n\n LadderGame --\x3e Position\n Ladder --\x3e Position\n Items --\x3e Position\n Line --\x3e Position\n Players --\x3e Position\n\n LadderGame --\x3e LadderGameResult\n\n Items --\x3e Item\n Players --\x3e Player\n\n LadderGameController --\x3e InputView\n LadderGameController --\x3e OutputView\n"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public LadderGameResult play() {\n final Map result = new LinkedHashMap<>();\n // \uc0ac\uc6a9\uc790 \uc218\ub9cc\ud07c Position\uc744 \uac00\uc838\uc640\uc11c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4.\n for (Position position : Position.range(players.count())) {\n final Position resultPosition = ladder.play(position);\n result.put(players.get(position), items.get(resultPosition));\n }\n return new LadderGameResult(result);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"player\uc5d0\uac8c-ladder\ub97c-\uc804\ub2ec\ud558\uc5ec-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",children:"Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsxs)(n.p,{children:["Position\uc5d0 \ub300\ud55c \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub294 Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c, Player\uac00 Ladder\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ubc29\ubc95\uc774 \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc704\ud574\uc11c \uac1d\uccb4\ub4e4\uc774 \uae34\ubc00\ud558\uac8c \ud611\ub825\ud558\uace0, \uc870\uae08 \ub354 \ucc45\uc784\uc758 \ubd84\ubc30\uac00 \uc798 \ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph TD\n\n LadderGameController --\x3e LadderGame\n LadderGame --\x3e Ladder\n LadderGame --\x3e Players\n LadderGame --\x3e Items\n\n Ladder --\x3e Line\n Line --\x3e LineStatus\n Line --\x3e Position\n\n Players --\x3e Ladder\n Player --\x3e Ladder\n\n Item --\x3e Position\n Player --\x3e Position\n\n\n LadderGame --\x3e LadderGameResult\n\n Items --\x3e Item --\x3e ItemName\n Players --\x3e Player --\x3e PlayerName\n\n LadderGameController --\x3e InputView\n LadderGameController --\x3e OutputView\n\n OutputView --\x3e LadderMessageGenerator"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public LadderGameResult play() {\n // \ucc38\uac00\uc790\ub4e4\uc5d0\uac8c \uc0ac\ub2e4\ub9ac\ub97c \uc804\ub2ec\ud574\uc11c \uc0ac\ub2e4\ub9ac\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud55c\ub2e4.\n final Map playResult = players.play(ladder);\n\n final Map result = new LinkedHashMap<>();\n for (Player player : playResult.keySet()) {\n result.put(player, toItem(playResult.get(player)));\n }\n return new LadderGameResult(result);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\uc5d0 \uc2dc\uac04\uc744 \ub4e4\uc774\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc815\ud558\ub294\ub370 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ub4e4\uc5ec\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0ac\ub2e4\ub9ac \ud0c0\uae30\uc758 \uc2e4\ud589 \uacb0\uacfc\ub97c Item\uc73c\ub85c \uc9d3\ub2e4\ub2c8.. \ubb54\uac00 \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uc804 \ubbf8\uc158\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c, \uba85\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \ubd80\uc871\ud568\uc744 \ub9ce\uc774 \ub290\uaf08\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\ud398\uc5b4\uc640 \uc870\uae08 \ub354 \uce5c\ud574\uc9c0\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uccab\ub0a0\uc740 \ud398\uc5b4\uc640 \uce5c\ud574\uc9c0\ub294 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \uac00\uc838\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\uac00\ub791 \ud68c\uace0\ud560 \ub54c \ub0b4\uac00 \uc2dc\uc791\ud558\uc790\ub9c8\uc790 \ucee8\ubca4\uc158 \uc815\ud558\uc790\uace0 \ud574\uc11c \ub9ce\uc774 \ub2f9\ud669\uc2a4\ub7ec\uc6e0\ub2e4\uace0 \ud55c\ub2e4. \uc6b0\uac00 \ubbf8\uc548.. \ud83e\udd72"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"README\ub97c \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c"}),(0,t.jsx)(n.br,{}),"\n","\uc774\uc0c1\ud558\uac8c \ucf54\ub529\uc5d0 \uc9d1\uc911\ud558\uba74 README\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uba74\uc11c \uac19\uc774 \ucee4\ubc0b \ud558\ub294 \uac78 \ud56d\uc0c1 \uae4c\uba39\ub294\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\uc5d0\ub294 \uc870\uae08 \ub354 \uc2e0\uacbd \uc368\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc88b\uc740 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uccab PR\ub54c \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \uc9c8\ubb38\uc744 \ub0a8\uae30\uc9c0 \ubabb\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9ac\ubdf0\uc5b4\uc640\uc758 \uc2dc\uac04\uc774 \uc18c\uc911\ud55c \uc2dc\uac04\uc774\ub77c\ub294 \uac83\uc744 \uae4c\uba39\uc9c0 \ub9d0\uace0, \ub098\uc758 \uc131\uc7a5\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"PR \ud6c4\uc5d0\ub3c4 \uaf3c\uaf3c\ud558\uac8c \ud655\uc778\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\ubd84\uba85 \uc54c\uace0 \uc788\ub294 \ubd80\ubd84\uc774\uc9c0\ub9cc, \ub193\uce5c \ubd80\ubd84\uc774 \ub9ce\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","PR \ud558\uae30 \uc804\uc5d0\ub3c4 \uacc4\uc18d \ud655\uc778\uc744 \ud588\uc9c0\ub9cc, \uc544\ubb34\ub798\ub3c4 IntelliJ\uc5d0\uc11c \ubcf4\ub2c8 \ucf54\ub4dc\uc5d0 \uc775\uc219\ud574\uc838\uc11c \uadf8\ub7f0\uc9c0 \ubcc0\uacbd\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc798 \uc548\ubcf4\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","github pr\uc5d0\uc11c\ub294 \uc804\uccb4 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\ub2c8 PR \ud6c4\uc5d0\ub3c4 \uaf2d \ud655\uc778\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc801\uadf9\uc801\uc73c\ub85c \ub098\uc758 \uc758\uacac\uc744 \ub9d0\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ud398\uc5b4\uc758 \uc758\uacac\uc774 \uad1c\ucc2e\ub2e4\uace0 \uc0dd\uac01\ud558\uba74 \uc218\uc6a9 \ud6c4 \uac1c\uc120\uc744 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\uc5c8\ub294\ub370, \uc870\uae08 \ub354 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ud5a5\uc774 \uc788\ub2e4\uba74 \ub098\ub3c4 \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub9d0\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub098\ub3c4 \uc124\ub4dd\ud558\ub294 \ud798\uc744 \uae30\ub974\uace0, \ud398\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc744 \uc54c \uc218 \uc788\uace0, \uacb0\uacfc\ubb3c\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub098\uc624\uc9c0 \uc54a\uc744\uae4c? (\uace0\ubbfc \ub4e4\uc5b4\uc8fc\uc2e0 \ub9ac\ubdf0\uc5b4 \ud130\ud2c0\ud83d\udc22 \uac10\uc0ac\ud569\ub2c8\ub2e4.)"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784"}),(0,t.jsx)(n.br,{}),"\n","Players\uac00 Position\uc744 \uc0dd\uc131\ud558\uace0 Player\uc758 \uc0dd\uc131\uc790\uc5d0 \ub123\uc5b4\uc8fc\uc5c8\ub2e4. \ud558\uc9c0\ub9cc \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ub828\ub41c \ucf54\uba58\ud2b8\uac00 \ub2ec\ub838\ub2e4.\n\uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uc0dd\uac01\ud574 \ubcf4\ub2c8 Position\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uac74 Player\uae30 \ub54c\ubb38\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 Player\uac00 \ub2f4\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud55c \ud328\ud134\uc73c\ub85c GRASP\uc758 Creator \ud328\ud134\uc774 \uc788\ub294\ub370 \ub2e4\uc74c\uc758 \uc694\uc18c\ub97c \ucd5c\ub300\ud55c \ub9cc\uc871\ud558\ub294 \ud074\ub798\uc2a4\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A\uc758 \ucd08\uae43\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc2e4\uc81c\ub85c \uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud574\uc11c \uae4a\uc774 \uc0dd\uac01\ud558\uba74\uc11c \ucf54\ub529\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc2dc\uc57c\uac00 \ub113\uc5b4\uc9c4 \uac83 \uac19\ub2e4."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\ud328\ud0a4\uc9c0 \ubd84\ub9ac \uae30\uc900"}),(0,t.jsx)(n.br,{}),"\n","\ud328\ud0a4\uc9c0 \ubd84\ub9ac\uc5d0 \ub300\ud55c \ub098\ub9cc\uc758 \uae30\uc900\uc774 \uc544\uc9c1 \uba85\ud655\ud558\uc9c0 \uc54a\uc544 \uc9c8\ubb38\uc774 \ub4e4\uc5b4\uc640\ub3c4 \uba85\ud655\ud558\uac8c \ub2f5\ubcc0\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9c8\uc9c0\ub9c9 \uc81c\ucd9c \uc804\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub97c \ubd84\ub9ac\ud574 \ubd24\ub294\ub370, \uae30\uc900\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \uc88b\uc9c0 \uc54a\uc740 \uc120\ud0dd\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.\n\ud604\uc7ac \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ud06c\uae30\uac00 \uadf8\ub807\uac8c \ud06c\uc9c0 \uc54a\uc73c\ub2c8, domain \ud328\ud0a4\uc9c0\uc5d0\uc11c \uc138\ubd80 \ud328\ud0a4\uc9c0\ub85c \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub420 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc0ac\uc6a9\ud558\ub294 \ucabd\uc5d0\uc11c \uc0dd\uac01\ud558\uae30 & \uc608\uce21\uac00\ub2a5\ud55c \ucf54\ub4dc \uc791\uc131\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","Position\uc5d0\uc11c \ub2e4\uc74c \uc704\uce58\ub098 \uc774\uc804 \uc704\uce58\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud5c8\uc6a9 \ubc94\uc704(0",(0,t.jsxs)(n.del,{children:["19)\uac00 \ubc97\uc5b4\ub09c\ub2e4\uba74, \uc758\ubbf8 \uc5c6\ub294 \uac12\uc774 \ub4e4\uc5b4\uac04 Position\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uac74 Position\uc744 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc744 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \ucf54\ub529\uc774\uc5c8\ub294\ub370, \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 0"]}),"19\uc758 \uac12\uc774 \ubcf4\uc7a5\ub418\uc5b4 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uac83\uc774\uae30 \ub54c\ubb38\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c hasNext, hasPrevious\ub77c\ub294 \uc774\uc804 \uac12, \uc774\ud6c4 \uac12\uc774 \ubc94\uc704 \ub0b4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud558\uace0, \uae30\uc874\uc758 \uac12\uc744 \uac00\uc838\uc624\ub294 \uba54\uc11c\ub4dc\ub294 \ubc94\uc704\uac00 \ubc97\uc5b4\ub098\uba74 \uc608\uc678\ub97c \ub358\uc9c0\ub294 \ubc29\ud5a5\uc73c\ub85c \ud574\uacb0\ud558\uc600\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:["\ubc1d\uc740 \uae30\uc6b4\uc744 \uac00\uc9c0\uace0 \uc788\uace0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \uce5c\ud654\ub825\uc774 \uc88b\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88\uc5d0 \ud398\uc5b4 \ud560 \ub54c \ucee8\ub514\uc158 \uad00\ub9ac\ub97c \uc81c\ub300\ub85c \ubabb\ud574\uc11c \ub9ce\uc774 \ubbf8\uc548\ud588\ub2e4. \ub2e4\uc74c\uc5d0\ub294 \ucd5c\uc0c1\uc758 \ucee8\ub514\uc158\uc73c\ub85c \ud398\uc5b4\ub97c \uc900\ube44\ud574 \ubd10\uc57c\uaca0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc6b0\uac00\ub791 \ud398\uc5b4\ub97c \ud558\uace0 \ub098\uc11c, \ub098\ub3c4 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \ub354 \uc798 \uc9c0\ub0b4\ubd10\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5b4 \uc870\uae08 \ub354 \uc6a9\uae30\ub97c \ub0b4 \uc7a1\ub2f4 \uc911\uc774\ub2e4!"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589\uc774 \uc798 \ub418\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ud398\uc5b4 \uc9c4\ud589\uc774 \ub290\ub9b0 \uac83 \uac19\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c \uc548\uc815\uc801\uc73c\ub85c \uc2dc\uac04 \uc548\uc5d0 \ubbf8\uc158\uc744 \uc644\ub8cc\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589 \uc18d\ub3c4\uc5d0 \ub300\ud574 \uc870\uae08 \ub354 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4!"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud56d\uc0c1 \uc9c0\ub098\uac08 \ub54c\ub9c8\ub2e4 \uc6c3\uc5b4\uc8fc\ub294\ub370, \ub098\ub3c4 \uc790\uc8fc \uc6c3\uc5b4\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6c3\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uc0ac\ub78c\uc774 \ubc1d\uc544 \ubcf4\uc5ec\uc11c \ub108\ubb34 \uc88b\uc740 \uac83 \uac19\ub2e4!"]})]})}function x(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>d});var t=r(67294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function s(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var o=t.createContext({}),d=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},c={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},x=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,s=e.originalType,o=e.parentName,x=l(e,["components","mdxType","originalType","parentName"]),p=d(r),u=a,j=p["".concat(o,".").concat(u)]||p[u]||c[u]||s;return r?t.createElement(j,i(i({ref:n},x),{},{components:r})):t.createElement(j,i({ref:n},x))}));x.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5103],{43420:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>x,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var t=r(85893),a=r(3905);const s={title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",slug:"ladder-retrospective",tags:["Woowahan Techcourse","Retrospective"]},i=void 0,l={permalink:"/ladder-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",description:"1\ub2e8\uacc4//github.com/woowacourse/java-ladder/pull/97",date:"2023-02-26T00:00:00.000Z",formattedDate:"2023\ub144 2\uc6d4 26\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:10.285,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0",slug:"ladder-retrospective",tags:["Woowahan Techcourse","Retrospective"]},unlisted:!1,prevItem:{title:"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0",permalink:"/racing-car-retrospective"},nextItem:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",permalink:"/blackjack-retrospective"}},o={authorsImageUrls:[]},d=[{value:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30",id:"\uc0ac\ub2e4\ub9ac-\ud0c0\uae30",level:3},{value:"Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95",id:"position-\uae30\uc900\uc73c\ub85c-\uc0ac\ub2e4\ub9ac-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",level:3},{value:"Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95",id:"player\uc5d0\uac8c-ladder\ub97c-\uc804\ub2ec\ud558\uc5ec-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",level:3},{value:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84",id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",level:3},{value:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84",id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",level:3},{value:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84",id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",level:3}];function c(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",del:"del",h3:"h3",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{title:"PR \ub9c1\ud06c",type:"note",children:(0,t.jsxs)(n.p,{children:["1\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/java-ladder/pull/97",children:"https://github.com/woowacourse/java-ladder/pull/97"}),(0,t.jsx)(n.br,{}),"\n","2\ub2e8\uacc4: ",(0,t.jsx)(n.a,{href:"https://github.com/woowacourse/java-ladder/pull/234",children:"https://github.com/woowacourse/java-ladder/pull/234"})]})}),"\n",(0,t.jsx)(n.h3,{id:"\uc0ac\ub2e4\ub9ac-\ud0c0\uae30",children:"\uc0ac\ub2e4\ub9ac \ud0c0\uae30"}),"\n",(0,t.jsxs)(n.p,{children:["\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc6b0\uac00\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uc804 \ubbf8\uc158\uacfc \ub2ec\ub9ac TDD\ub85c \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ud544\uc218\uc600\uae30 \ub54c\ubb38\uc5d0 \uc775\uc219\ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, \uc6b0\uac00\uc640 \ubbf8\uc158\uc5d0 \uad00\ud55c \uc18c\ud1b5\uc774 \uc798 \ub418\uc5b4\uc11c \ud070 \ubb38\uc81c \uc5c6\uc774 \ubbf8\uc158\uc744 \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uc6b0\uac00\uc640 \uc774\uc57c\uae30\uac00 \uc798 \ud1b5\ud574\uc11c \uadf8\ub7f0\uc9c0 1\ub2e8\uacc4\ub294 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub294\ub370, 2\ub2e8\uacc4\uc5d0\uc11c \ub9ce\uc774 \uace0\uc804\ud55c \uac83 \uac19\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"2\ub2e8\uacc4\uc5d0\uc11c\ub294 2\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ud574\ubd24\ub2e4."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"LadderGame\uc5d0\uc11c Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.li,{children:"Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c Ladder\uc5d0\uac8c Position\uc744 \ub118\uaca8\uc8fc\uba70 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"position-\uae30\uc900\uc73c\ub85c-\uc0ac\ub2e4\ub9ac-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",children:"Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsxs)(n.p,{children:["\uc0ac\uc2e4\uc0c1 index\ub97c Ladder\uc5d0\uac8c \ub118\uaca8\uc8fc\uace0, \ud574\ub2f9 index\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc1b\ub294 \ubc29\ubc95\uacfc \uc720\uc0ac\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uad6c\ud604\ud558\uace0 \ub098\ub2c8 \ub2e4\ub978 \ud074\ub798\uc2a4\ub4e4\uc774 Position\uc5d0 \ub300\ud55c \uc758\uc874\ub3c4\uac00 \ub108\ubb34 \ub192\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c Players\uac00 \ubcc4\ub2e4\ub978 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\ub2e4\uace0 \ub290\uaf08\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph TD\n\n LadderGameController --\x3e LadderGame\n LadderGame --\x3e Ladder\n LadderGame --\x3e Players\n LadderGame --\x3e Items\n\n Ladder --\x3e Line\n Line --\x3e LineStatus\n\n LadderGame --\x3e Position\n Ladder --\x3e Position\n Items --\x3e Position\n Line --\x3e Position\n Players --\x3e Position\n\n LadderGame --\x3e LadderGameResult\n\n Items --\x3e Item\n Players --\x3e Player\n\n LadderGameController --\x3e InputView\n LadderGameController --\x3e OutputView\n"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public LadderGameResult play() {\n final Map result = new LinkedHashMap<>();\n // \uc0ac\uc6a9\uc790 \uc218\ub9cc\ud07c Position\uc744 \uac00\uc838\uc640\uc11c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4.\n for (Position position : Position.range(players.count())) {\n final Position resultPosition = ladder.play(position);\n result.put(players.get(position), items.get(resultPosition));\n }\n return new LadderGameResult(result);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"player\uc5d0\uac8c-ladder\ub97c-\uc804\ub2ec\ud558\uc5ec-\uac8c\uc784\uc744-\uc9c4\ud589\ud558\ub294-\ubc29\ubc95",children:"Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsxs)(n.p,{children:["Position\uc5d0 \ub300\ud55c \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub294 Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c, Player\uac00 Ladder\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ubc29\ubc95\uc774 \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc704\ud574\uc11c \uac1d\uccb4\ub4e4\uc774 \uae34\ubc00\ud558\uac8c \ud611\ub825\ud558\uace0, \uc870\uae08 \ub354 \ucc45\uc784\uc758 \ubd84\ubc30\uac00 \uc798 \ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.mermaid,{value:"graph TD\n\n LadderGameController --\x3e LadderGame\n LadderGame --\x3e Ladder\n LadderGame --\x3e Players\n LadderGame --\x3e Items\n\n Ladder --\x3e Line\n Line --\x3e LineStatus\n Line --\x3e Position\n\n Players --\x3e Ladder\n Player --\x3e Ladder\n\n Item --\x3e Position\n Player --\x3e Position\n\n\n LadderGame --\x3e LadderGameResult\n\n Items --\x3e Item --\x3e ItemName\n Players --\x3e Player --\x3e PlayerName\n\n LadderGameController --\x3e InputView\n LadderGameController --\x3e OutputView\n\n OutputView --\x3e LadderMessageGenerator"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public LadderGameResult play() {\n // \ucc38\uac00\uc790\ub4e4\uc5d0\uac8c \uc0ac\ub2e4\ub9ac\ub97c \uc804\ub2ec\ud574\uc11c \uc0ac\ub2e4\ub9ac\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud55c\ub2e4.\n final Map playResult = players.play(ladder);\n\n final Map result = new LinkedHashMap<>();\n for (Player player : playResult.keySet()) {\n result.put(player, toItem(playResult.get(player)));\n }\n return new LadderGameResult(result);\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"\ubd80\uc871\ud588\ub358-\ubd80\ubd84",children:"\ubd80\uc871\ud588\ub358 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\uc5d0 \uc2dc\uac04\uc744 \ub4e4\uc774\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc815\ud558\ub294\ub370 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ub4e4\uc5ec\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc0ac\ub2e4\ub9ac \ud0c0\uae30\uc758 \uc2e4\ud589 \uacb0\uacfc\ub97c Item\uc73c\ub85c \uc9d3\ub2e4\ub2c8.. \ubb54\uac00 \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uc804 \ubbf8\uc158\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c, \uba85\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \ubd80\uc871\ud568\uc744 \ub9ce\uc774 \ub290\uaf08\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\ud398\uc5b4\uc640 \uc870\uae08 \ub354 \uce5c\ud574\uc9c0\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uccab\ub0a0\uc740 \ud398\uc5b4\uc640 \uce5c\ud574\uc9c0\ub294 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \uac00\uc838\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6b0\uac00\ub791 \ud68c\uace0\ud560 \ub54c \ub0b4\uac00 \uc2dc\uc791\ud558\uc790\ub9c8\uc790 \ucee8\ubca4\uc158 \uc815\ud558\uc790\uace0 \ud574\uc11c \ub9ce\uc774 \ub2f9\ud669\uc2a4\ub7ec\uc6e0\ub2e4\uace0 \ud55c\ub2e4. \uc6b0\uac00 \ubbf8\uc548.. \ud83e\udd72"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"README\ub97c \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c"}),(0,t.jsx)(n.br,{}),"\n","\uc774\uc0c1\ud558\uac8c \ucf54\ub529\uc5d0 \uc9d1\uc911\ud558\uba74 README\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uba74\uc11c \uac19\uc774 \ucee4\ubc0b \ud558\ub294 \uac78 \ud56d\uc0c1 \uae4c\uba39\ub294\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub2e4\uc74c \ubbf8\uc158\uc5d0\ub294 \uc870\uae08 \ub354 \uc2e0\uacbd \uc368\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc88b\uc740 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uccab PR\ub54c \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \uc9c8\ubb38\uc744 \ub0a8\uae30\uc9c0 \ubabb\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9ac\ubdf0\uc5b4\uc640\uc758 \uc2dc\uac04\uc774 \uc18c\uc911\ud55c \uc2dc\uac04\uc774\ub77c\ub294 \uac83\uc744 \uae4c\uba39\uc9c0 \ub9d0\uace0, \ub098\uc758 \uc131\uc7a5\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"PR \ud6c4\uc5d0\ub3c4 \uaf3c\uaf3c\ud558\uac8c \ud655\uc778\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\ubd84\uba85 \uc54c\uace0 \uc788\ub294 \ubd80\ubd84\uc774\uc9c0\ub9cc, \ub193\uce5c \ubd80\ubd84\uc774 \ub9ce\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","PR \ud558\uae30 \uc804\uc5d0\ub3c4 \uacc4\uc18d \ud655\uc778\uc744 \ud588\uc9c0\ub9cc, \uc544\ubb34\ub798\ub3c4 IntelliJ\uc5d0\uc11c \ubcf4\ub2c8 \ucf54\ub4dc\uc5d0 \uc775\uc219\ud574\uc838\uc11c \uadf8\ub7f0\uc9c0 \ubcc0\uacbd\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc798 \uc548\ubcf4\uc600\ub2e4.",(0,t.jsx)(n.br,{}),"\n","github pr\uc5d0\uc11c\ub294 \uc804\uccb4 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\ub2c8 PR \ud6c4\uc5d0\ub3c4 \uaf2d \ud655\uc778\ud574\uc57c\uaca0\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc801\uadf9\uc801\uc73c\ub85c \ub098\uc758 \uc758\uacac\uc744 \ub9d0\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ud398\uc5b4\uc758 \uc758\uacac\uc774 \uad1c\ucc2e\ub2e4\uace0 \uc0dd\uac01\ud558\uba74 \uc218\uc6a9 \ud6c4 \uac1c\uc120\uc744 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\uc5c8\ub294\ub370, \uc870\uae08 \ub354 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ud5a5\uc774 \uc788\ub2e4\uba74 \ub098\ub3c4 \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub9d0\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\uc774 \ub4e0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub098\ub3c4 \uc124\ub4dd\ud558\ub294 \ud798\uc744 \uae30\ub974\uace0, \ud398\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc744 \uc54c \uc218 \uc788\uace0, \uacb0\uacfc\ubb3c\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub098\uc624\uc9c0 \uc54a\uc744\uae4c? (\uace0\ubbfc \ub4e4\uc5b4\uc8fc\uc2e0 \ub9ac\ubdf0\uc5b4 \ud130\ud2c0\ud83d\udc22 \uac10\uc0ac\ud569\ub2c8\ub2e4.)"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc0c8\ub85c-\ud559\uc2b5\ud55c-\ubd80\ubd84",children:"\uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784"}),(0,t.jsx)(n.br,{}),"\n","Players\uac00 Position\uc744 \uc0dd\uc131\ud558\uace0 Player\uc758 \uc0dd\uc131\uc790\uc5d0 \ub123\uc5b4\uc8fc\uc5c8\ub2e4. \ud558\uc9c0\ub9cc \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ub828\ub41c \ucf54\uba58\ud2b8\uac00 \ub2ec\ub838\ub2e4.\n\uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uc0dd\uac01\ud574 \ubcf4\ub2c8 Position\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uac74 Player\uae30 \ub54c\ubb38\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 Player\uac00 \ub2f4\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsx)(n.p,{children:"\uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud55c \ud328\ud134\uc73c\ub85c GRASP\uc758 Creator \ud328\ud134\uc774 \uc788\ub294\ub370 \ub2e4\uc74c\uc758 \uc694\uc18c\ub97c \ucd5c\ub300\ud55c \ub9cc\uc871\ud558\ub294 \ud074\ub798\uc2a4\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.li,{children:"B\uac00 A\uc758 \ucd08\uae43\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc2e4\uc81c\ub85c \uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud574\uc11c \uae4a\uc774 \uc0dd\uac01\ud558\uba74\uc11c \ucf54\ub529\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc2dc\uc57c\uac00 \ub113\uc5b4\uc9c4 \uac83 \uac19\ub2e4."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\ud328\ud0a4\uc9c0 \ubd84\ub9ac \uae30\uc900"}),(0,t.jsx)(n.br,{}),"\n","\ud328\ud0a4\uc9c0 \ubd84\ub9ac\uc5d0 \ub300\ud55c \ub098\ub9cc\uc758 \uae30\uc900\uc774 \uc544\uc9c1 \uba85\ud655\ud558\uc9c0 \uc54a\uc544 \uc9c8\ubb38\uc774 \ub4e4\uc5b4\uc640\ub3c4 \uba85\ud655\ud558\uac8c \ub2f5\ubcc0\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub9c8\uc9c0\ub9c9 \uc81c\ucd9c \uc804\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub97c \ubd84\ub9ac\ud574 \ubd24\ub294\ub370, \uae30\uc900\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \uc88b\uc9c0 \uc54a\uc740 \uc120\ud0dd\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.\n\ud604\uc7ac \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ud06c\uae30\uac00 \uadf8\ub807\uac8c \ud06c\uc9c0 \uc54a\uc73c\ub2c8, domain \ud328\ud0a4\uc9c0\uc5d0\uc11c \uc138\ubd80 \ud328\ud0a4\uc9c0\ub85c \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub420 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"\uc0ac\uc6a9\ud558\ub294 \ucabd\uc5d0\uc11c \uc0dd\uac01\ud558\uae30 & \uc608\uce21\uac00\ub2a5\ud55c \ucf54\ub4dc \uc791\uc131\ud558\uae30"}),(0,t.jsx)(n.br,{}),"\n","Position\uc5d0\uc11c \ub2e4\uc74c \uc704\uce58\ub098 \uc774\uc804 \uc704\uce58\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud5c8\uc6a9 \ubc94\uc704(0",(0,t.jsxs)(n.del,{children:["19)\uac00 \ubc97\uc5b4\ub09c\ub2e4\uba74, \uc758\ubbf8 \uc5c6\ub294 \uac12\uc774 \ub4e4\uc5b4\uac04 Position\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\uac74 Position\uc744 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc744 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \ucf54\ub529\uc774\uc5c8\ub294\ub370, \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 0"]}),"19\uc758 \uac12\uc774 \ubcf4\uc7a5\ub418\uc5b4 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uac83\uc774\uae30 \ub54c\ubb38\uc774\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c hasNext, hasPrevious\ub77c\ub294 \uc774\uc804 \uac12, \uc774\ud6c4 \uac12\uc774 \ubc94\uc704 \ub0b4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud558\uace0, \uae30\uc874\uc758 \uac12\uc744 \uac00\uc838\uc624\ub294 \uba54\uc11c\ub4dc\ub294 \ubc94\uc704\uac00 \ubc97\uc5b4\ub098\uba74 \uc608\uc678\ub97c \ub358\uc9c0\ub294 \ubc29\ud5a5\uc73c\ub85c \ud574\uacb0\ud558\uc600\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ud398\uc5b4\uc5d0\uac8c-\ubc30\uc6b8-\ubd80\ubd84",children:"\ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84"}),"\n",(0,t.jsxs)(n.p,{children:["\ubc1d\uc740 \uae30\uc6b4\uc744 \uac00\uc9c0\uace0 \uc788\uace0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \uce5c\ud654\ub825\uc774 \uc88b\uc740 \uac83 \uac19\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774\ubc88\uc5d0 \ud398\uc5b4 \ud560 \ub54c \ucee8\ub514\uc158 \uad00\ub9ac\ub97c \uc81c\ub300\ub85c \ubabb\ud574\uc11c \ub9ce\uc774 \ubbf8\uc548\ud588\ub2e4. \ub2e4\uc74c\uc5d0\ub294 \ucd5c\uc0c1\uc758 \ucee8\ub514\uc158\uc73c\ub85c \ud398\uc5b4\ub97c \uc900\ube44\ud574 \ubd10\uc57c\uaca0\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uadf8\ub9ac\uace0 \uc6b0\uac00\ub791 \ud398\uc5b4\ub97c \ud558\uace0 \ub098\uc11c, \ub098\ub3c4 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \ub354 \uc798 \uc9c0\ub0b4\ubd10\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5b4 \uc870\uae08 \ub354 \uc6a9\uae30\ub97c \ub0b4 \uc7a1\ub2f4 \uc911\uc774\ub2e4!"]}),"\n",(0,t.jsxs)(n.p,{children:["\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589\uc774 \uc798 \ub418\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub610\ud55c \ud398\uc5b4 \uc9c4\ud589\uc774 \ub290\ub9b0 \uac83 \uac19\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c \uc548\uc815\uc801\uc73c\ub85c \uc2dc\uac04 \uc548\uc5d0 \ubbf8\uc158\uc744 \uc644\ub8cc\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589 \uc18d\ub3c4\uc5d0 \ub300\ud574 \uc870\uae08 \ub354 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4!"]}),"\n",(0,t.jsxs)(n.p,{children:["\ud56d\uc0c1 \uc9c0\ub098\uac08 \ub54c\ub9c8\ub2e4 \uc6c3\uc5b4\uc8fc\ub294\ub370, \ub098\ub3c4 \uc790\uc8fc \uc6c3\uc5b4\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc6c3\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uc0ac\ub78c\uc774 \ubc1d\uc544 \ubcf4\uc5ec\uc11c \ub108\ubb34 \uc88b\uc740 \uac83 \uac19\ub2e4!"]})]})}function x(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>d});var t=r(67294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function s(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var o=t.createContext({}),d=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},c={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},x=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,s=e.originalType,o=e.parentName,x=l(e,["components","mdxType","originalType","parentName"]),p=d(r),u=a,j=p["".concat(o,".").concat(u)]||p[u]||c[u]||s;return r?t.createElement(j,i(i({ref:n},x),{},{components:r})):t.createElement(j,i({ref:n},x))}));x.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/dfc7013c.f3d89c0c.js b/assets/js/dfc7013c.5b4d3dab.js similarity index 98% rename from assets/js/dfc7013c.f3d89c0c.js rename to assets/js/dfc7013c.5b4d3dab.js index 4f4c4e348..0d40ab2d4 100644 --- a/assets/js/dfc7013c.f3d89c0c.js +++ b/assets/js/dfc7013c.5b4d3dab.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5857],{10032:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>c,contentTitle:()=>d,default:()=>j,frontMatter:()=>l,metadata:()=>i,toc:()=>a});var r=n(85893),t=n(3905);const l={title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",slug:"java-class-file",tags:["Java","Class"]},d=void 0,i={permalink:"/java-class-file",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",source:"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",description:"\ud074\ub798\uc2a4 \ud30c\uc77c",date:"2023-04-03T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 3\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Class",permalink:"/tags/class"}],readingTime:5.63,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",slug:"java-class-file",tags:["Java","Class"]},unlisted:!1,prevItem:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",permalink:"/test-double"},nextItem:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",permalink:"/custom-jdbc-template"}},c={authorsImageUrls:[]},a=[{value:"\ud074\ub798\uc2a4 \ud30c\uc77c",id:"\ud074\ub798\uc2a4-\ud30c\uc77c",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd",id:"\ud074\ub798\uc2a4-\ud30c\uc77c\uc758-\ub370\uc774\ud130-\ud615\uc2dd",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\uad6c\uc870",level:3},{value:"\ub9e4\uc9c1\ub118\ubc84",id:"\ub9e4\uc9c1\ub118\ubc84",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud3ec\ub9f7-\ubc84\uc804",level:3},{value:"\uc0c1\uc218 \ud480",id:"\uc0c1\uc218-\ud480",level:3},{value:"\uc561\uc138\uc2a4 \ud50c\ub798\uadf8",id:"\uc561\uc138\uc2a4-\ud50c\ub798\uadf8",level:3},{value:"this_class",id:"this_class",level:3},{value:"super_class",id:"super_class",level:3},{value:"interface, field, method",id:"interface-field-method",level:3},{value:"attributes",id:"attributes",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud655\uc778\ud558\uba74\uc11c-\uc0ac\uc6a9\ud55c-\ud234",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function h(e){const s={a:"a",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c",children:"\ud074\ub798\uc2a4 \ud30c\uc77c"}),"\n",(0,r.jsxs)(s.p,{children:["\uc790\ubc14 \uc18c\uc2a4\ucf54\ub4dc\uac00 \uc2e4\ud589\uc774 \ub418\ub824\uba74 \uc790\ubc14 \ucef4\ud30c\uc77c\ub7ec(javac)\ub97c \ud1b5\ud574 \uc18c\uc2a4\ucf54\ub4dc\ub97c \ud074\ub798\uc2a4\ud30c\uc77c\ub85c \ubcc0\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ucef4\ud30c\uc77c\ub41c \ud074\ub798\uc2a4\ud30c\uc77c\uc740 \uc5b4\ub5a4 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744\uae4c?"]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c\uc758-\ub370\uc774\ud130-\ud615\uc2dd",children:"\ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd"}),"\n",(0,r.jsxs)(s.p,{children:["8\ube44\ud2b8 \ubc14\uc774\ud2b8\uc758 \uc2a4\ud2b8\ub9bc\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","16\ube44\ud2b8 \ubc0f 32\ube44\ud2b8\uc758 \ub370\uc774\ud130\ub294 \uac01\uac01 2\uac1c, 4\uac1c\uc758 \uc5f0\uc18d\ub41c 8\ube44\ud2b8\ub97c \uc77d\uc5b4\uc11c \uad6c\uc131\ub41c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uba40\ud2f0\ubc14\uc774\ud2b8\uc758 \uacbd\uc6b0 \ud56d\uc0c1 big endian \uc21c\uc11c\ub85c \uc800\uc7a5\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(s.p,{children:["u1 \u2192 unsigned 1byte",(0,r.jsx)(s.br,{}),"\n","u2 \u2192 unsigned 2byte",(0,r.jsx)(s.br,{}),"\n","u4 \u2192 unsigned 4byte"]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\uad6c\uc870",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{children:"ClassFile {\n u4 magic;\n u2 minor_version;\n u2 major_version;\n u2 constant_pool_count;\n cp_info constant_pool[constant_pool_count-1];\n u2 access_flags;\n u2 this_class;\n u2 super_class;\n u2 interfaces_count;\n u2 interfaces[interfaces_count];\n u2 fields_count;\n field_info fields[fields_count];\n u2 methods_count;\n method_info methods[methods_count];\n u2 attributes_count;\n attribute_info attributes[attributes_count];\n}\n"})}),"\n",(0,r.jsx)(s.h3,{id:"\ub9e4\uc9c1\ub118\ubc84",children:"\ub9e4\uc9c1\ub118\ubc84"}),"\n",(0,r.jsxs)(s.p,{children:["\ubaa8\ub4e0 \ud074\ub798\uc2a4 \ud30c\uc77c\uc740 0xCAFEBABE\ub77c\ub294 \ub9e4\uc9c1\ub118\ubc84\ub85c \uc2dc\uc791\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ubcf4\ud1b5 \ub9e4\uc9c1\ub118\ubc84\ub294 \ud30c\uc77c \uc885\ub958\ub97c \uc2dd\ubcc4\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud3ec\ub9f7-\ubc84\uc804",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804"}),"\n",(0,r.jsx)(s.p,{children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ubc84\uc804 \uac12\uc740 \ud074\ub798\uc2a4\ub85c\ub354\uc758 \ud638\ud658\uc131 \ubcf4\uc7a5\uc744 \uc704\ud574 \uaf2d \ud544\uc694\ud55c \uac12\uc774\ub2e4."}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Java 17 \ubc84\uc804\uc73c\ub85c \ube4c\ub4dc\ud55c\ub2e4\uba74 class version 61 ex) 00 00 00 3D"}),"\n"]}),"\n",(0,r.jsxs)(s.p,{children:["\ud638\ud658\ub418\uc9c0 \uc54a\ub294 \ubc84\uc804\uc758 \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \ub85c\ub529\ud558\ub824\uace0 \ud558\ub294 \uacbd\uc6b0 \ub7f0\ud0c0\uc784\uc5d0 ",(0,r.jsx)(s.code,{children:"UnsupportedClassVersionError"})," \uc608\uc678\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"class\xa0file format major versions"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Java SE"}),(0,r.jsx)(s.th,{children:"Released"}),(0,r.jsx)(s.th,{children:"Major"}),(0,r.jsx)(s.th,{children:"Supported majors"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"8"}),(0,r.jsx)(s.td,{children:"March 2014"}),(0,r.jsx)(s.td,{children:"52"}),(0,r.jsx)(s.td,{children:"45 .. 52"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"9"}),(0,r.jsx)(s.td,{children:"September 2017"}),(0,r.jsx)(s.td,{children:"53"}),(0,r.jsx)(s.td,{children:"45 .. 53"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"10"}),(0,r.jsx)(s.td,{children:"March 2018"}),(0,r.jsx)(s.td,{children:"54"}),(0,r.jsx)(s.td,{children:"45 .. 54"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"11"}),(0,r.jsx)(s.td,{children:"September 2018"}),(0,r.jsx)(s.td,{children:"55"}),(0,r.jsx)(s.td,{children:"45 .. 55"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"12"}),(0,r.jsx)(s.td,{children:"March 2019"}),(0,r.jsx)(s.td,{children:"56"}),(0,r.jsx)(s.td,{children:"45 .. 56"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"13"}),(0,r.jsx)(s.td,{children:"September 2019"}),(0,r.jsx)(s.td,{children:"57"}),(0,r.jsx)(s.td,{children:"45 .. 57"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"14"}),(0,r.jsx)(s.td,{children:"March 2020"}),(0,r.jsx)(s.td,{children:"58"}),(0,r.jsx)(s.td,{children:"45 .. 58"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"15"}),(0,r.jsx)(s.td,{children:"September 2020"}),(0,r.jsx)(s.td,{children:"59"}),(0,r.jsx)(s.td,{children:"45 .. 59"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"16"}),(0,r.jsx)(s.td,{children:"March 2021"}),(0,r.jsx)(s.td,{children:"60"}),(0,r.jsx)(s.td,{children:"45 .. 60"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"17"}),(0,r.jsx)(s.td,{children:"September 2021"}),(0,r.jsx)(s.td,{children:"61"}),(0,r.jsx)(s.td,{children:"45 .. 61"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"\uc0c1\uc218-\ud480",children:"\uc0c1\uc218 \ud480"}),"\n",(0,r.jsxs)(s.p,{children:["2\ubc14\uc774\ud2b8\uc758 \uc0c1\uc218\uc758 \uac1c\uc218\uac12\uc774 \uba3c\uc800\uc624\uace0 \uadf8 \ub4a4\ub85c \ucf54\ub4dc\uc5d0 \ub4f1\uc7a5\ud558\ub294 \uc0c1\uc218\uac12\uc774 \ubaa8\uc5ec\uc788\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ud074\ub798\uc2a4\uba85, \uc0c1\uc218\uba85, \uc0c1\uc218 \uac12, \ud544\ub4dc\uba85, \uba54\uc11c\ub4dc\uba85\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","JVM\uc740 \ucf54\ub4dc \uc2e4\ud589 \uc2dc \ub7f0\ud0c0\uc784\uc5d0 \ubc30\uce58\ub41c \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c, \ud574\ub2f9 \uc0c1\uc218 \ud480 \ud14c\uc774\ube14\uc744 \ucc3e\uc544\ubcf4\uace0 \ud544\uc694\ud55c \uac12\uc744 \ucc38\uc870\ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\uc561\uc138\uc2a4-\ud50c\ub798\uadf8",children:"\uc561\uc138\uc2a4 \ud50c\ub798\uadf8"}),"\n",(0,r.jsxs)(s.p,{children:["\ud074\ub798\uc2a4, \uc778\ud130\ud398\uc774\uc2a4\uc640 \uac19\uc740 \ud30c\uc77c\uc758 \uc18d\uc131\uc744 \ud45c\uc2dc\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 public interface\ub85c \uc815\uc758\ub41c \uc778\ud130\ud398\uc774\uc2a4\uc758 \ud50c\ub798\uadf8\ub294 0x0601\uc774\ub2e4."]}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["\uacc4\uc0b0\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. ",(0,r.jsx)(s.code,{children:"ACC_PUBLIC"})," xor ",(0,r.jsx)(s.code,{children:"ACC_INTERFACE"})," xor ",(0,r.jsx)(s.code,{children:"ACC_ABSTRACT"})]}),"\n"]}),"\n",(0,r.jsx)(s.p,{children:"\uacf5\uc2dd\ubb38\uc11c\uc5d0 \ub4e4\uc5b4\uac00\uba74 \uac01 \ud50c\ub798\uadf8\uc5d0 \ub300\ud55c \uc124\uba85 + \ud50c\ub798\uadf8 \uc124\uc815\uc2dc \ub3d9\uc2dc\uc5d0 \uc124\uc815\ub418\uba74 \uc548\ub418\ub294 \ud50c\ub798\uadf8\uc640 \uac19\uc740 \uc124\uba85\uc774 \uc790\uc138\ud558\uac8c \ub098\uc640\uc788\ub2e4."}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Class access and property modifiers"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Flag Name"}),(0,r.jsx)(s.th,{children:"Value"}),(0,r.jsx)(s.th,{children:"Interpretation"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_PUBLIC"}),(0,r.jsx)(s.td,{children:"0x0001"}),(0,r.jsx)(s.td,{children:"Declared\xa0public; may be accessed from outside its package."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_FINAL"}),(0,r.jsx)(s.td,{children:"0x0010"}),(0,r.jsx)(s.td,{children:"Declared\xa0final; no subclasses allowed."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_SUPER"}),(0,r.jsx)(s.td,{children:"0x0020"}),(0,r.jsx)(s.td,{children:"Treat superclass methods specially when invoked by the\xa0invokespecial\xa0instruction."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_INTERFACE"}),(0,r.jsx)(s.td,{children:"0x0200"}),(0,r.jsx)(s.td,{children:"Is an interface, not a class."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ABSTRACT"}),(0,r.jsx)(s.td,{children:"0x0400"}),(0,r.jsx)(s.td,{children:"Declared\xa0abstract; must not be instantiated."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_SYNTHETIC"}),(0,r.jsx)(s.td,{children:"0x1000"}),(0,r.jsx)(s.td,{children:"Declared synthetic; not present in the source code."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ANNOTATION"}),(0,r.jsx)(s.td,{children:"0x2000"}),(0,r.jsx)(s.td,{children:"Declared as an annotation type."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ENUM"}),(0,r.jsx)(s.td,{children:"0x4000"}),(0,r.jsx)(s.td,{children:"Declared as an\xa0enum\xa0type."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_MODULE"}),(0,r.jsx)(s.td,{children:"0x8000"}),(0,r.jsx)(s.td,{children:"Is a module, not a class or interface."})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"this_class",children:"this_class"}),"\n",(0,r.jsxs)(s.p,{children:["\ud074\ub798\uc2a4\uba85\uacfc \uac19\uc740 \uc774\ub984\uc744 \ud45c\ud604\ud558\ub294 \uac12\uc73c\ub85c, \uc0c1\uc218 \ud480\uc5d0\uc11c \ud074\ub798\uc2a4\uba85\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ud574\ub2f9 \uc778\ub371\uc2a4\uc758 \ud56d\ubaa9\uc740 ",(0,r.jsx)(s.code,{children:"CONSTANT_Class_infoclass"})," \ud615\uc2dd\uc758 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"super_class",children:"super_class"}),"\n",(0,r.jsxs)(s.p,{children:["\uc0c1\uc218 \ud480\uc5d0\uc11c \uc288\ud37c \ud074\ub798\uc2a4\uc758 \uc774\ub984\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uc544\ubb34\uac83\ub3c4 \uc0c1\uc18d\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\uc758 \uacbd\uc6b0 ",(0,r.jsx)(s.code,{children:"java.lang.Object"}),"\uc758 \uc778\ub371\uc2a4 \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"interface-field-method",children:"interface, field, method"}),"\n",(0,r.jsxs)(s.p,{children:["\uac01\uac01\uc758 \uac1c\uc218\uc640, \uc815\ubcf4\uc5d0 \ub300\ud55c \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4.",(0,r.jsx)(s.br,{}),"\n","interface, field, method\ub97c \ud45c\uc2dc\ud558\ub294 \ubc29\ubc95\uc774 \uac01\uac01 \ub2e4\ub974\uace0, \uc811\uadfc\uc790\uc5d0 \ub300\ud55c \ud50c\ub798\uadf8\ub3c4 \uac01\uac01 \ub2e4\ub974\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"attributes",children:"attributes"}),"\n",(0,r.jsxs)(s.p,{children:["\ud574\ub2f9 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucd94\uac00 \uc815\ubcf4\uc758 \ubaa8\uc74c\uc774\ub2e4. \uc608) \uc18c\uc2a4\ud30c\uc77c\uba85",(0,r.jsx)(s.br,{}),"\n","\uc815\ud574\uc9c4 \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \uad6c\uc870\ub97c \ud655\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud655\uc778\ud558\uba74\uc11c-\uc0ac\uc6a9\ud55c-\ud234",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234"}),"\n",(0,r.jsxs)(s.p,{children:["IntelliJ plugin - BinEd",(0,r.jsx)(s.br,{}),"\n","IntelliJ plugin - jclasslib Bytecode Viewer"]}),"\n",(0,r.jsx)(s.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(s.p,{children:["2\uc7a5 JVM \uc774\uc57c\uae30, \uc790\ubc14 \ucd5c\uc801\ud654",(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.fileformat.com/ko/programming/class/",children:"Class file in Java, File Format"}),(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html",children:"java se11 Class \ud30c\uc77c \ud615\uc2dd, Oracle"}),(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html",children:"java se17 Class \ud30c\uc77c \ud615\uc2dd, Oracle"})]})]})}function j(e={}){const{wrapper:s}={...(0,t.ah)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,s,n)=>{n.d(s,{ah:()=>a});var r=n(67294);function t(e,s,n){return s in e?Object.defineProperty(e,s,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[s]=n,e}function l(e,s){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);s&&(r=r.filter((function(s){return Object.getOwnPropertyDescriptor(e,s).enumerable}))),n.push.apply(n,r)}return n}function d(e){for(var s=1;s=0||(t[n]=e[n]);return t}(e,s);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(t[n]=e[n])}return t}var c=r.createContext({}),a=function(e){var s=r.useContext(c),n=s;return e&&(n="function"==typeof e?e(s):d(d({},s),e)),n},h={inlineCode:"code",wrapper:function(e){var s=e.children;return r.createElement(r.Fragment,{},s)}},j=r.forwardRef((function(e,s){var n=e.components,t=e.mdxType,l=e.originalType,c=e.parentName,j=i(e,["components","mdxType","originalType","parentName"]),x=a(n),o=t,u=x["".concat(c,".").concat(o)]||x[o]||h[o]||l;return n?r.createElement(u,d(d({ref:s},j),{},{components:n})):r.createElement(u,d({ref:s},j))}));j.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5857],{10032:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>c,contentTitle:()=>d,default:()=>j,frontMatter:()=>l,metadata:()=>i,toc:()=>a});var r=n(85893),t=n(3905);const l={title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",slug:"java-class-file",tags:["Java","Class"]},d=void 0,i={permalink:"/java-class-file",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",source:"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",description:"\ud074\ub798\uc2a4 \ud30c\uc77c",date:"2023-04-03T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 3\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Class",permalink:"/tags/class"}],readingTime:5.63,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",slug:"java-class-file",tags:["Java","Class"]},unlisted:!1,prevItem:{title:"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30",permalink:"/custom-jdbc-template"},nextItem:{title:"\ud14c\uc2a4\ud2b8 \ub300\uc5ed",permalink:"/test-double"}},c={authorsImageUrls:[]},a=[{value:"\ud074\ub798\uc2a4 \ud30c\uc77c",id:"\ud074\ub798\uc2a4-\ud30c\uc77c",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd",id:"\ud074\ub798\uc2a4-\ud30c\uc77c\uc758-\ub370\uc774\ud130-\ud615\uc2dd",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\uad6c\uc870",level:3},{value:"\ub9e4\uc9c1\ub118\ubc84",id:"\ub9e4\uc9c1\ub118\ubc84",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud3ec\ub9f7-\ubc84\uc804",level:3},{value:"\uc0c1\uc218 \ud480",id:"\uc0c1\uc218-\ud480",level:3},{value:"\uc561\uc138\uc2a4 \ud50c\ub798\uadf8",id:"\uc561\uc138\uc2a4-\ud50c\ub798\uadf8",level:3},{value:"this_class",id:"this_class",level:3},{value:"super_class",id:"super_class",level:3},{value:"interface, field, method",id:"interface-field-method",level:3},{value:"attributes",id:"attributes",level:3},{value:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234",id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud655\uc778\ud558\uba74\uc11c-\uc0ac\uc6a9\ud55c-\ud234",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function h(e){const s={a:"a",br:"br",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c",children:"\ud074\ub798\uc2a4 \ud30c\uc77c"}),"\n",(0,r.jsxs)(s.p,{children:["\uc790\ubc14 \uc18c\uc2a4\ucf54\ub4dc\uac00 \uc2e4\ud589\uc774 \ub418\ub824\uba74 \uc790\ubc14 \ucef4\ud30c\uc77c\ub7ec(javac)\ub97c \ud1b5\ud574 \uc18c\uc2a4\ucf54\ub4dc\ub97c \ud074\ub798\uc2a4\ud30c\uc77c\ub85c \ubcc0\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ucef4\ud30c\uc77c\ub41c \ud074\ub798\uc2a4\ud30c\uc77c\uc740 \uc5b4\ub5a4 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744\uae4c?"]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c\uc758-\ub370\uc774\ud130-\ud615\uc2dd",children:"\ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd"}),"\n",(0,r.jsxs)(s.p,{children:["8\ube44\ud2b8 \ubc14\uc774\ud2b8\uc758 \uc2a4\ud2b8\ub9bc\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","16\ube44\ud2b8 \ubc0f 32\ube44\ud2b8\uc758 \ub370\uc774\ud130\ub294 \uac01\uac01 2\uac1c, 4\uac1c\uc758 \uc5f0\uc18d\ub41c 8\ube44\ud2b8\ub97c \uc77d\uc5b4\uc11c \uad6c\uc131\ub41c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uba40\ud2f0\ubc14\uc774\ud2b8\uc758 \uacbd\uc6b0 \ud56d\uc0c1 big endian \uc21c\uc11c\ub85c \uc800\uc7a5\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(s.p,{children:["u1 \u2192 unsigned 1byte",(0,r.jsx)(s.br,{}),"\n","u2 \u2192 unsigned 2byte",(0,r.jsx)(s.br,{}),"\n","u4 \u2192 unsigned 4byte"]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\uad6c\uc870",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{children:"ClassFile {\n u4 magic;\n u2 minor_version;\n u2 major_version;\n u2 constant_pool_count;\n cp_info constant_pool[constant_pool_count-1];\n u2 access_flags;\n u2 this_class;\n u2 super_class;\n u2 interfaces_count;\n u2 interfaces[interfaces_count];\n u2 fields_count;\n field_info fields[fields_count];\n u2 methods_count;\n method_info methods[methods_count];\n u2 attributes_count;\n attribute_info attributes[attributes_count];\n}\n"})}),"\n",(0,r.jsx)(s.h3,{id:"\ub9e4\uc9c1\ub118\ubc84",children:"\ub9e4\uc9c1\ub118\ubc84"}),"\n",(0,r.jsxs)(s.p,{children:["\ubaa8\ub4e0 \ud074\ub798\uc2a4 \ud30c\uc77c\uc740 0xCAFEBABE\ub77c\ub294 \ub9e4\uc9c1\ub118\ubc84\ub85c \uc2dc\uc791\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ubcf4\ud1b5 \ub9e4\uc9c1\ub118\ubc84\ub294 \ud30c\uc77c \uc885\ub958\ub97c \uc2dd\ubcc4\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ub41c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud3ec\ub9f7-\ubc84\uc804",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804"}),"\n",(0,r.jsx)(s.p,{children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ubc84\uc804 \uac12\uc740 \ud074\ub798\uc2a4\ub85c\ub354\uc758 \ud638\ud658\uc131 \ubcf4\uc7a5\uc744 \uc704\ud574 \uaf2d \ud544\uc694\ud55c \uac12\uc774\ub2e4."}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Java 17 \ubc84\uc804\uc73c\ub85c \ube4c\ub4dc\ud55c\ub2e4\uba74 class version 61 ex) 00 00 00 3D"}),"\n"]}),"\n",(0,r.jsxs)(s.p,{children:["\ud638\ud658\ub418\uc9c0 \uc54a\ub294 \ubc84\uc804\uc758 \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \ub85c\ub529\ud558\ub824\uace0 \ud558\ub294 \uacbd\uc6b0 \ub7f0\ud0c0\uc784\uc5d0 ",(0,r.jsx)(s.code,{children:"UnsupportedClassVersionError"})," \uc608\uc678\uac00 \ubc1c\uc0dd\ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"class\xa0file format major versions"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Java SE"}),(0,r.jsx)(s.th,{children:"Released"}),(0,r.jsx)(s.th,{children:"Major"}),(0,r.jsx)(s.th,{children:"Supported majors"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"8"}),(0,r.jsx)(s.td,{children:"March 2014"}),(0,r.jsx)(s.td,{children:"52"}),(0,r.jsx)(s.td,{children:"45 .. 52"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"9"}),(0,r.jsx)(s.td,{children:"September 2017"}),(0,r.jsx)(s.td,{children:"53"}),(0,r.jsx)(s.td,{children:"45 .. 53"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"10"}),(0,r.jsx)(s.td,{children:"March 2018"}),(0,r.jsx)(s.td,{children:"54"}),(0,r.jsx)(s.td,{children:"45 .. 54"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"11"}),(0,r.jsx)(s.td,{children:"September 2018"}),(0,r.jsx)(s.td,{children:"55"}),(0,r.jsx)(s.td,{children:"45 .. 55"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"12"}),(0,r.jsx)(s.td,{children:"March 2019"}),(0,r.jsx)(s.td,{children:"56"}),(0,r.jsx)(s.td,{children:"45 .. 56"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"13"}),(0,r.jsx)(s.td,{children:"September 2019"}),(0,r.jsx)(s.td,{children:"57"}),(0,r.jsx)(s.td,{children:"45 .. 57"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"14"}),(0,r.jsx)(s.td,{children:"March 2020"}),(0,r.jsx)(s.td,{children:"58"}),(0,r.jsx)(s.td,{children:"45 .. 58"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"15"}),(0,r.jsx)(s.td,{children:"September 2020"}),(0,r.jsx)(s.td,{children:"59"}),(0,r.jsx)(s.td,{children:"45 .. 59"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"16"}),(0,r.jsx)(s.td,{children:"March 2021"}),(0,r.jsx)(s.td,{children:"60"}),(0,r.jsx)(s.td,{children:"45 .. 60"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"17"}),(0,r.jsx)(s.td,{children:"September 2021"}),(0,r.jsx)(s.td,{children:"61"}),(0,r.jsx)(s.td,{children:"45 .. 61"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"\uc0c1\uc218-\ud480",children:"\uc0c1\uc218 \ud480"}),"\n",(0,r.jsxs)(s.p,{children:["2\ubc14\uc774\ud2b8\uc758 \uc0c1\uc218\uc758 \uac1c\uc218\uac12\uc774 \uba3c\uc800\uc624\uace0 \uadf8 \ub4a4\ub85c \ucf54\ub4dc\uc5d0 \ub4f1\uc7a5\ud558\ub294 \uc0c1\uc218\uac12\uc774 \ubaa8\uc5ec\uc788\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ud074\ub798\uc2a4\uba85, \uc0c1\uc218\uba85, \uc0c1\uc218 \uac12, \ud544\ub4dc\uba85, \uba54\uc11c\ub4dc\uba85\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","JVM\uc740 \ucf54\ub4dc \uc2e4\ud589 \uc2dc \ub7f0\ud0c0\uc784\uc5d0 \ubc30\uce58\ub41c \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c, \ud574\ub2f9 \uc0c1\uc218 \ud480 \ud14c\uc774\ube14\uc744 \ucc3e\uc544\ubcf4\uace0 \ud544\uc694\ud55c \uac12\uc744 \ucc38\uc870\ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\uc561\uc138\uc2a4-\ud50c\ub798\uadf8",children:"\uc561\uc138\uc2a4 \ud50c\ub798\uadf8"}),"\n",(0,r.jsxs)(s.p,{children:["\ud074\ub798\uc2a4, \uc778\ud130\ud398\uc774\uc2a4\uc640 \uac19\uc740 \ud30c\uc77c\uc758 \uc18d\uc131\uc744 \ud45c\uc2dc\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uc608\ub97c \ub4e4\uc5b4 public interface\ub85c \uc815\uc758\ub41c \uc778\ud130\ud398\uc774\uc2a4\uc758 \ud50c\ub798\uadf8\ub294 0x0601\uc774\ub2e4."]}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["\uacc4\uc0b0\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. ",(0,r.jsx)(s.code,{children:"ACC_PUBLIC"})," xor ",(0,r.jsx)(s.code,{children:"ACC_INTERFACE"})," xor ",(0,r.jsx)(s.code,{children:"ACC_ABSTRACT"})]}),"\n"]}),"\n",(0,r.jsx)(s.p,{children:"\uacf5\uc2dd\ubb38\uc11c\uc5d0 \ub4e4\uc5b4\uac00\uba74 \uac01 \ud50c\ub798\uadf8\uc5d0 \ub300\ud55c \uc124\uba85 + \ud50c\ub798\uadf8 \uc124\uc815\uc2dc \ub3d9\uc2dc\uc5d0 \uc124\uc815\ub418\uba74 \uc548\ub418\ub294 \ud50c\ub798\uadf8\uc640 \uac19\uc740 \uc124\uba85\uc774 \uc790\uc138\ud558\uac8c \ub098\uc640\uc788\ub2e4."}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Class access and property modifiers"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Flag Name"}),(0,r.jsx)(s.th,{children:"Value"}),(0,r.jsx)(s.th,{children:"Interpretation"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_PUBLIC"}),(0,r.jsx)(s.td,{children:"0x0001"}),(0,r.jsx)(s.td,{children:"Declared\xa0public; may be accessed from outside its package."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_FINAL"}),(0,r.jsx)(s.td,{children:"0x0010"}),(0,r.jsx)(s.td,{children:"Declared\xa0final; no subclasses allowed."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_SUPER"}),(0,r.jsx)(s.td,{children:"0x0020"}),(0,r.jsx)(s.td,{children:"Treat superclass methods specially when invoked by the\xa0invokespecial\xa0instruction."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_INTERFACE"}),(0,r.jsx)(s.td,{children:"0x0200"}),(0,r.jsx)(s.td,{children:"Is an interface, not a class."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ABSTRACT"}),(0,r.jsx)(s.td,{children:"0x0400"}),(0,r.jsx)(s.td,{children:"Declared\xa0abstract; must not be instantiated."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_SYNTHETIC"}),(0,r.jsx)(s.td,{children:"0x1000"}),(0,r.jsx)(s.td,{children:"Declared synthetic; not present in the source code."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ANNOTATION"}),(0,r.jsx)(s.td,{children:"0x2000"}),(0,r.jsx)(s.td,{children:"Declared as an annotation type."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_ENUM"}),(0,r.jsx)(s.td,{children:"0x4000"}),(0,r.jsx)(s.td,{children:"Declared as an\xa0enum\xa0type."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"ACC_MODULE"}),(0,r.jsx)(s.td,{children:"0x8000"}),(0,r.jsx)(s.td,{children:"Is a module, not a class or interface."})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"this_class",children:"this_class"}),"\n",(0,r.jsxs)(s.p,{children:["\ud074\ub798\uc2a4\uba85\uacfc \uac19\uc740 \uc774\ub984\uc744 \ud45c\ud604\ud558\ub294 \uac12\uc73c\ub85c, \uc0c1\uc218 \ud480\uc5d0\uc11c \ud074\ub798\uc2a4\uba85\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\ud574\ub2f9 \uc778\ub371\uc2a4\uc758 \ud56d\ubaa9\uc740 ",(0,r.jsx)(s.code,{children:"CONSTANT_Class_infoclass"})," \ud615\uc2dd\uc758 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"super_class",children:"super_class"}),"\n",(0,r.jsxs)(s.p,{children:["\uc0c1\uc218 \ud480\uc5d0\uc11c \uc288\ud37c \ud074\ub798\uc2a4\uc758 \uc774\ub984\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4.",(0,r.jsx)(s.br,{}),"\n","\uc544\ubb34\uac83\ub3c4 \uc0c1\uc18d\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\uc758 \uacbd\uc6b0 ",(0,r.jsx)(s.code,{children:"java.lang.Object"}),"\uc758 \uc778\ub371\uc2a4 \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"interface-field-method",children:"interface, field, method"}),"\n",(0,r.jsxs)(s.p,{children:["\uac01\uac01\uc758 \uac1c\uc218\uc640, \uc815\ubcf4\uc5d0 \ub300\ud55c \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4.",(0,r.jsx)(s.br,{}),"\n","interface, field, method\ub97c \ud45c\uc2dc\ud558\ub294 \ubc29\ubc95\uc774 \uac01\uac01 \ub2e4\ub974\uace0, \uc811\uadfc\uc790\uc5d0 \ub300\ud55c \ud50c\ub798\uadf8\ub3c4 \uac01\uac01 \ub2e4\ub974\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"attributes",children:"attributes"}),"\n",(0,r.jsxs)(s.p,{children:["\ud574\ub2f9 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucd94\uac00 \uc815\ubcf4\uc758 \ubaa8\uc74c\uc774\ub2e4. \uc608) \uc18c\uc2a4\ud30c\uc77c\uba85",(0,r.jsx)(s.br,{}),"\n","\uc815\ud574\uc9c4 \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \uad6c\uc870\ub97c \ud655\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(s.h3,{id:"\ud074\ub798\uc2a4-\ud30c\uc77c-\ud655\uc778\ud558\uba74\uc11c-\uc0ac\uc6a9\ud55c-\ud234",children:"\ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234"}),"\n",(0,r.jsxs)(s.p,{children:["IntelliJ plugin - BinEd",(0,r.jsx)(s.br,{}),"\n","IntelliJ plugin - jclasslib Bytecode Viewer"]}),"\n",(0,r.jsx)(s.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(s.p,{children:["2\uc7a5 JVM \uc774\uc57c\uae30, \uc790\ubc14 \ucd5c\uc801\ud654",(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.fileformat.com/ko/programming/class/",children:"Class file in Java, File Format"}),(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html",children:"java se11 Class \ud30c\uc77c \ud615\uc2dd, Oracle"}),(0,r.jsx)(s.br,{}),"\n",(0,r.jsx)(s.a,{href:"https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html",children:"java se17 Class \ud30c\uc77c \ud615\uc2dd, Oracle"})]})]})}function j(e={}){const{wrapper:s}={...(0,t.ah)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,s,n)=>{n.d(s,{ah:()=>a});var r=n(67294);function t(e,s,n){return s in e?Object.defineProperty(e,s,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[s]=n,e}function l(e,s){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);s&&(r=r.filter((function(s){return Object.getOwnPropertyDescriptor(e,s).enumerable}))),n.push.apply(n,r)}return n}function d(e){for(var s=1;s=0||(t[n]=e[n]);return t}(e,s);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(t[n]=e[n])}return t}var c=r.createContext({}),a=function(e){var s=r.useContext(c),n=s;return e&&(n="function"==typeof e?e(s):d(d({},s),e)),n},h={inlineCode:"code",wrapper:function(e){var s=e.children;return r.createElement(r.Fragment,{},s)}},j=r.forwardRef((function(e,s){var n=e.components,t=e.mdxType,l=e.originalType,c=e.parentName,j=i(e,["components","mdxType","originalType","parentName"]),x=a(n),o=t,u=x["".concat(c,".").concat(o)]||x[o]||h[o]||l;return n?r.createElement(u,d(d({ref:s},j),{},{components:n})):r.createElement(u,d({ref:s},j))}));j.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/e1735da7.7747f2b7.js b/assets/js/e1735da7.b8fd0ff5.js similarity index 98% rename from assets/js/e1735da7.7747f2b7.js rename to assets/js/e1735da7.b8fd0ff5.js index 3e0d51f73..82bf1092d 100644 --- a/assets/js/e1735da7.7747f2b7.js +++ b/assets/js/e1735da7.b8fd0ff5.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1611],{79784:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>p,frontMatter:()=>s,metadata:()=>i,toc:()=>o});var r=t(85893),a=t(3905);const s={title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",slug:"tecochat-retrospective-2",tags:["TecoChat","Retrospective"]},l=void 0,i={permalink:"/tecochat-retrospective-2",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",source:"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",description:"\ud504\ub860\ud2b8\uc5d4\ud2b8",date:"2023-05-01T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 1\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.67,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",slug:"tecochat-retrospective-2",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",permalink:"/web-racing-car-retrospective"},nextItem:{title:"Jenkins\ub85c CI/CD \uc124\uc815",permalink:"/jenkins"}},c={authorsImageUrls:[]},o=[{value:"\ud504\ub860\ud2b8\uc5d4\ud2b8",id:"\ud504\ub860\ud2b8\uc5d4\ud2b8",level:3},{value:"\ubc31\uc5d4\ub4dc",id:"\ubc31\uc5d4\ub4dc",level:3},{value:"Http Request Header",id:"http-request-header",level:3},{value:"Elastic Beanstalk",id:"elastic-beanstalk",level:3},{value:"Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac",id:"elastic-beanstalk-rds-\uc124\uc815-\ud6c4-\ubd84\ub9ac",level:3},{value:"Elastic Beanstalk nginx \uc124\uc815",id:"elastic-beanstalk-nginx-\uc124\uc815",level:3},{value:"Jenkins",id:"jenkins",level:3},{value:"Jenkins Blue Ocean",id:"jenkins-blue-ocean",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"\ud504\ub860\ud2b8\uc5d4\ud2b8",children:"\ud504\ub860\ud2b8\uc5d4\ud2b8"}),"\n",(0,r.jsxs)(n.p,{children:["\ub2c9\ub124\uc784\uc744 \uc785\ub825\ud558\uc5ec \uac04\ub2e8\ud788 \ub85c\uadf8\uc778\ud558\ub294 \ud654\uba74, \ucc44\ud305 \ubaa9\ub85d\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\uace0 \ub2e8\uc77c \ucc44\ud305\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ucc44\ud305\uc744 \uc774\uc5b4\ub098\uac08 \uc218 \uc788\uac8c \ud558\ub294 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\uc798\ud558\uac8c \uc2e0\uacbd \uc4f8 \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c, \ud504\ub860\ud2b8\uc5d4\ub4dc \ud558\ub294 \uc0ac\ub78c\ub4e4\uc774 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc5ec\uc720\uac00 \ub41c\ub2e4\uba74 \uc790\uc2e0\uc758 \ucc44\ud305\uc744 \ubcfc \uc218 \uc788\ub294 \uae30\ub2a5\uc774\ub098, \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub294 \uae30\ub2a5, \ub313\uae00 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud560 \uc608\uc815\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ubc31\uc5d4\ub4dc",children:"\ubc31\uc5d4\ub4dc"}),"\n",(0,r.jsxs)(n.p,{children:["\ucd5c\ub300\ud55c \ube68\ub9ac \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uae30\ub85c \uc815\ud574\uc11c, \ubc31\uc5d4\ub4dc\ub294 \ub9d0\ub791\uc774 \uc77c\ub2e8 \ub2e4 \ub9cc\ub4e4\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9d0\ub791\uc774 \ud55c \ubd80\ubd84\uc774 \ub108\ubb34 \ub9ce\uc544\uc11c \ub0b4\uac00 \ubabb \ub530\ub77c\uac00\ub294 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc911\uc5d0 \ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc774\ud574\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"http-request-header",children:"Http Request Header"}),"\n",(0,r.jsxs)(n.p,{children:["\uc544\uc9c1 \uc778\uc99d\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ud558\uc9c0 \uc54a\uc544\uc11c \uc694\uccad \ud5e4\ub354\uc5d0 \uc774\ub984\uc744 \ubcf4\ub0b4\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9d0\ub791\uc774 \ud55c\uae00\uc740 \uc548\ub41c\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c Base64\ub85c \uc778\ucf54\ub529\ud558\uace0, \ubc31\uc5d4\ub4dc\uc5d0\uc11c \ub514\ucf54\ub529 \ud558\uc5ec \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\ub294 pinia\uc5d0 \uc788\ub294 name \uac12\uc744 \uc778\ucf54\ub529 \ud558\ub294 \ucf54\ub4dc\ub2e4. deprecated \ub418\uc5c8\ub2e4\ub294\ub370, \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560 \uc904 \ubab0\ub77c\uc11c \uc77c\ub2e8 \uc774\uac78 \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"const encodedName = () => {\n const uriComponent = unescape(encodeURIComponent(name.value));\n return btoa(uriComponent);\n};\n"})}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk",children:"Elastic Beanstalk"}),"\n",(0,r.jsxs)(n.p,{children:["\uac00\uc7a5 \ube60\ub974\uac8c \ubc31\uc5d4\ub4dc\ub97c \ubc30\ud3ec\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ubb58\uc9c0 \uace0\ubbfc\ud558\ub2e4\uac00 Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uba74 \uc778\ud504\ub77c\uc5d0 \ub300\ud574 \uc798 \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube60\ub974\uac8c \ubc30\ud3ec\ud558\uace0 \uad00\ub9ac\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubaa8\ub2c8\ud130\ub9c1, \ub85c\uae45, \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk-rds-\uc124\uc815-\ud6c4-\ubd84\ub9ac",children:"Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac"}),"\n",(0,r.jsxs)(n.p,{children:["\ucd08\uae30 \uc124\uc815 \uc2dc RDS\ub97c \uc5f0\uacb0\ud558\uace0 \uc124\uc815 \uc644\ub8cc \ud6c4 \ubd84\ub9ac\ud55c\ub2e4\uba74, Beanstalk \uc778\uc2a4\ud134\uc2a4 -> RDS \uc694\uccad \uc2dc \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc744 \uc548 \ud574\ub3c4 \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","RDS \ubd84\ub9ac \uc2dc Beanstalk\uc5d0 \uae30\ubcf8\uc801\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub294 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD\uc640 \uac19\uc740 \ud658\uacbd \ubcc0\uc218\uac00 \uac19\uc774 \uc81c\uac70\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c Elastic Beanstalk\ub85c RDS\ub97c \uc124\uc815\ud558\uba74 \uae30\ubcf8 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uba85\uc740 ebdb\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk-nginx-\uc124\uc815",children:"Elastic Beanstalk nginx \uc124\uc815"}),"\n",(0,r.jsxs)(n.p,{children:["\uc5c5\ub85c\ub4dc\ud558\ub294 zip \ud30c\uc77c \ub0b4\ubd80\uc5d0 ",(0,r.jsx)(n.code,{children:".platform/nginx/conf.d/"})," \uacbd\ub85c\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ucd94\uac00\ud558\uba74 nginx \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"jenkins",children:"Jenkins"}),"\n",(0,r.jsxs)(n.p,{children:["\ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc77c\uc77c\ud788 \ubc30\ud3ec\ud558\uae30 \ubd88\ud3b8\ud574\uc11c Jenkins\ub97c \uc774\uc6a9\ud558\uc5ec Repository\uc5d0 \ucf54\ub4dc\ub97c push \ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ubc30\ud3ec\uac00 \ub418\uac8c \uc124\uc815\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc791\ub144\uc5d0 \ud655\uc778\ud588\uc744 \ub550 2022\ub144 12\uc6d4 31\uc77c\uae4c\uc9c0 EC2 ARM \uae30\ubc18 t4g.small\uc774 \ubb34\ub8cc\uc600\ub294\ub370, \ub2e4\uc2dc \ub4e4\uc5b4\uac00 \ubcf4\ub2c8 2023\ub144\uae4c\uc9c0 12\uc6d4 31\uc77c\uae4c\uc9c0 t4g.small\uc744 \ubb34\ub8cc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","t4g.small\uc740 \ub7a8\uc774 2G\uc778\ub370, \uc608\uc804\uc5d0\ub294 \ubd80\uc871\ud558\uc9c0 \uc54a\uc558\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370 Java 17\uc744 \uc368\uc11c \uadf8\ub7f0\uac00 \ube4c\ub4dc \ud560 \ub54c \ub7a8\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\uc544\uc11c Swap \uba54\ubaa8\ub9ac 2\uae30\uac00\ub97c \ucd94\uac00\ub85c \uc124\uc815\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c build.gradle\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8 \uc2dc \uc0ac\uc6a9\ud558\ub294 \ub7a8\uc744 \ub298\ub9b4 \uc218 \uc788\ub2e4. \uae30\ubcf8\uac12\uc740 512MB\ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-groovy",children:'test {\n maxHeapSize = "1024m"\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"jenkins-blue-ocean",children:"Jenkins Blue Ocean"}),"\n",(0,r.jsxs)(n.p,{children:["Blue Ocean\uc740 Jenkins Pipeline\uc744 \uad6c\uc131\ud558\ub294 \ub370\uc5d0 \uc788\uc5b4 \ud3b8\ub9ac\ud558\uac8c \ud574\uc8fc\ub294 \ub3c4\uad6c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc2dc\uac01\ud654\ub3c4 \uc798 \ub418\uc5b4\uc788\uace0, \uc124\uc815\ub3c4 \ud3b8\ub9ac\ud55c \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n",'\uc624\ub298 \uc801\uc6a9\ud574 \ubcf4\ub2c8 \ub7a8\uc774 \ubd80\uc871\ud558\uc5ec \uc911\uac04\uc5d0 \uc798 \uc548\ub418\uae30\ub3c4 \ud558\uace0 \uadf8\ub798\uc11c \uadf8\ub0e5 "Pipeline\ub9cc \uc0ac\uc6a9\ud560 \uac78 \uadf8\ub7ac\ub098?" \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.']}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/Welcome.html",children:"Elastic Beanstalk, AWS"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://aws.amazon.com/ko/ec2/graviton/",children:"EC2 AWS Graviton, AWS"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings",children:"Default Memory Settings, AWS"})]})]})}function p(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>o});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=r.createContext({}),o=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},d={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,s=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=o(t),h=a,b=u["".concat(c,".").concat(h)]||u[h]||d[h]||s;return t?r.createElement(b,l(l({ref:n},p),{},{components:t})):r.createElement(b,l({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1611],{79784:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>p,frontMatter:()=>s,metadata:()=>i,toc:()=>o});var r=t(85893),a=t(3905);const s={title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",slug:"tecochat-retrospective-2",tags:["TecoChat","Retrospective"]},l=void 0,i={permalink:"/tecochat-retrospective-2",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",source:"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",description:"\ud504\ub860\ud2b8\uc5d4\ud2b8",date:"2023-05-01T00:00:00.000Z",formattedDate:"2023\ub144 5\uc6d4 1\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:4.67,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec",slug:"tecochat-retrospective-2",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"Jenkins\ub85c CI/CD \uc124\uc815",permalink:"/jenkins"},nextItem:{title:"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0",permalink:"/web-racing-car-retrospective"}},c={authorsImageUrls:[]},o=[{value:"\ud504\ub860\ud2b8\uc5d4\ud2b8",id:"\ud504\ub860\ud2b8\uc5d4\ud2b8",level:3},{value:"\ubc31\uc5d4\ub4dc",id:"\ubc31\uc5d4\ub4dc",level:3},{value:"Http Request Header",id:"http-request-header",level:3},{value:"Elastic Beanstalk",id:"elastic-beanstalk",level:3},{value:"Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac",id:"elastic-beanstalk-rds-\uc124\uc815-\ud6c4-\ubd84\ub9ac",level:3},{value:"Elastic Beanstalk nginx \uc124\uc815",id:"elastic-beanstalk-nginx-\uc124\uc815",level:3},{value:"Jenkins",id:"jenkins",level:3},{value:"Jenkins Blue Ocean",id:"jenkins-blue-ocean",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",br:"br",code:"code",h3:"h3",p:"p",pre:"pre",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"\ud504\ub860\ud2b8\uc5d4\ud2b8",children:"\ud504\ub860\ud2b8\uc5d4\ud2b8"}),"\n",(0,r.jsxs)(n.p,{children:["\ub2c9\ub124\uc784\uc744 \uc785\ub825\ud558\uc5ec \uac04\ub2e8\ud788 \ub85c\uadf8\uc778\ud558\ub294 \ud654\uba74, \ucc44\ud305 \ubaa9\ub85d\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\uace0 \ub2e8\uc77c \ucc44\ud305\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ucc44\ud305\uc744 \uc774\uc5b4\ub098\uac08 \uc218 \uc788\uac8c \ud558\ub294 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\uc798\ud558\uac8c \uc2e0\uacbd \uc4f8 \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c, \ud504\ub860\ud2b8\uc5d4\ub4dc \ud558\ub294 \uc0ac\ub78c\ub4e4\uc774 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc5ec\uc720\uac00 \ub41c\ub2e4\uba74 \uc790\uc2e0\uc758 \ucc44\ud305\uc744 \ubcfc \uc218 \uc788\ub294 \uae30\ub2a5\uc774\ub098, \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub294 \uae30\ub2a5, \ub313\uae00 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud560 \uc608\uc815\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ubc31\uc5d4\ub4dc",children:"\ubc31\uc5d4\ub4dc"}),"\n",(0,r.jsxs)(n.p,{children:["\ucd5c\ub300\ud55c \ube68\ub9ac \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uae30\ub85c \uc815\ud574\uc11c, \ubc31\uc5d4\ub4dc\ub294 \ub9d0\ub791\uc774 \uc77c\ub2e8 \ub2e4 \ub9cc\ub4e4\uace0 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9d0\ub791\uc774 \ud55c \ubd80\ubd84\uc774 \ub108\ubb34 \ub9ce\uc544\uc11c \ub0b4\uac00 \ubabb \ub530\ub77c\uac00\ub294 \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc911\uc5d0 \ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc774\ud574\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"http-request-header",children:"Http Request Header"}),"\n",(0,r.jsxs)(n.p,{children:["\uc544\uc9c1 \uc778\uc99d\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ud558\uc9c0 \uc54a\uc544\uc11c \uc694\uccad \ud5e4\ub354\uc5d0 \uc774\ub984\uc744 \ubcf4\ub0b4\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9d0\ub791\uc774 \ud55c\uae00\uc740 \uc548\ub41c\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c Base64\ub85c \uc778\ucf54\ub529\ud558\uace0, \ubc31\uc5d4\ub4dc\uc5d0\uc11c \ub514\ucf54\ub529 \ud558\uc5ec \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\ub798\ub294 pinia\uc5d0 \uc788\ub294 name \uac12\uc744 \uc778\ucf54\ub529 \ud558\ub294 \ucf54\ub4dc\ub2e4. deprecated \ub418\uc5c8\ub2e4\ub294\ub370, \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560 \uc904 \ubab0\ub77c\uc11c \uc77c\ub2e8 \uc774\uac78 \uc0ac\uc6a9\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"const encodedName = () => {\n const uriComponent = unescape(encodeURIComponent(name.value));\n return btoa(uriComponent);\n};\n"})}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk",children:"Elastic Beanstalk"}),"\n",(0,r.jsxs)(n.p,{children:["\uac00\uc7a5 \ube60\ub974\uac8c \ubc31\uc5d4\ub4dc\ub97c \ubc30\ud3ec\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ubb58\uc9c0 \uace0\ubbfc\ud558\ub2e4\uac00 Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uba74 \uc778\ud504\ub77c\uc5d0 \ub300\ud574 \uc798 \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube60\ub974\uac8c \ubc30\ud3ec\ud558\uace0 \uad00\ub9ac\ud560 \uc218 \uc788\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubaa8\ub2c8\ud130\ub9c1, \ub85c\uae45, \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk-rds-\uc124\uc815-\ud6c4-\ubd84\ub9ac",children:"Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac"}),"\n",(0,r.jsxs)(n.p,{children:["\ucd08\uae30 \uc124\uc815 \uc2dc RDS\ub97c \uc5f0\uacb0\ud558\uace0 \uc124\uc815 \uc644\ub8cc \ud6c4 \ubd84\ub9ac\ud55c\ub2e4\uba74, Beanstalk \uc778\uc2a4\ud134\uc2a4 -> RDS \uc694\uccad \uc2dc \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc744 \uc548 \ud574\ub3c4 \ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","RDS \ubd84\ub9ac \uc2dc Beanstalk\uc5d0 \uae30\ubcf8\uc801\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub294 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD\uc640 \uac19\uc740 \ud658\uacbd \ubcc0\uc218\uac00 \uac19\uc774 \uc81c\uac70\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c Elastic Beanstalk\ub85c RDS\ub97c \uc124\uc815\ud558\uba74 \uae30\ubcf8 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uba85\uc740 ebdb\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"elastic-beanstalk-nginx-\uc124\uc815",children:"Elastic Beanstalk nginx \uc124\uc815"}),"\n",(0,r.jsxs)(n.p,{children:["\uc5c5\ub85c\ub4dc\ud558\ub294 zip \ud30c\uc77c \ub0b4\ubd80\uc5d0 ",(0,r.jsx)(n.code,{children:".platform/nginx/conf.d/"})," \uacbd\ub85c\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ucd94\uac00\ud558\uba74 nginx \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"jenkins",children:"Jenkins"}),"\n",(0,r.jsxs)(n.p,{children:["\ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc77c\uc77c\ud788 \ubc30\ud3ec\ud558\uae30 \ubd88\ud3b8\ud574\uc11c Jenkins\ub97c \uc774\uc6a9\ud558\uc5ec Repository\uc5d0 \ucf54\ub4dc\ub97c push \ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ubc30\ud3ec\uac00 \ub418\uac8c \uc124\uc815\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc791\ub144\uc5d0 \ud655\uc778\ud588\uc744 \ub550 2022\ub144 12\uc6d4 31\uc77c\uae4c\uc9c0 EC2 ARM \uae30\ubc18 t4g.small\uc774 \ubb34\ub8cc\uc600\ub294\ub370, \ub2e4\uc2dc \ub4e4\uc5b4\uac00 \ubcf4\ub2c8 2023\ub144\uae4c\uc9c0 12\uc6d4 31\uc77c\uae4c\uc9c0 t4g.small\uc744 \ubb34\ub8cc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","t4g.small\uc740 \ub7a8\uc774 2G\uc778\ub370, \uc608\uc804\uc5d0\ub294 \ubd80\uc871\ud558\uc9c0 \uc54a\uc558\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370 Java 17\uc744 \uc368\uc11c \uadf8\ub7f0\uac00 \ube4c\ub4dc \ud560 \ub54c \ub7a8\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\uc544\uc11c Swap \uba54\ubaa8\ub9ac 2\uae30\uac00\ub97c \ucd94\uac00\ub85c \uc124\uc815\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c build.gradle\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8 \uc2dc \uc0ac\uc6a9\ud558\ub294 \ub7a8\uc744 \ub298\ub9b4 \uc218 \uc788\ub2e4. \uae30\ubcf8\uac12\uc740 512MB\ub77c\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-groovy",children:'test {\n maxHeapSize = "1024m"\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"jenkins-blue-ocean",children:"Jenkins Blue Ocean"}),"\n",(0,r.jsxs)(n.p,{children:["Blue Ocean\uc740 Jenkins Pipeline\uc744 \uad6c\uc131\ud558\ub294 \ub370\uc5d0 \uc788\uc5b4 \ud3b8\ub9ac\ud558\uac8c \ud574\uc8fc\ub294 \ub3c4\uad6c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc2dc\uac01\ud654\ub3c4 \uc798 \ub418\uc5b4\uc788\uace0, \uc124\uc815\ub3c4 \ud3b8\ub9ac\ud55c \uac83 \uac19\ub2e4.",(0,r.jsx)(n.br,{}),"\n",'\uc624\ub298 \uc801\uc6a9\ud574 \ubcf4\ub2c8 \ub7a8\uc774 \ubd80\uc871\ud558\uc5ec \uc911\uac04\uc5d0 \uc798 \uc548\ub418\uae30\ub3c4 \ud558\uace0 \uadf8\ub798\uc11c \uadf8\ub0e5 "Pipeline\ub9cc \uc0ac\uc6a9\ud560 \uac78 \uadf8\ub7ac\ub098?" \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4.']}),"\n",(0,r.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/Welcome.html",children:"Elastic Beanstalk, AWS"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://aws.amazon.com/ko/ec2/graviton/",children:"EC2 AWS Graviton, AWS"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings",children:"Default Memory Settings, AWS"})]})]})}function p(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>o});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=r.createContext({}),o=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},d={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,s=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=o(t),h=a,b=u["".concat(c,".").concat(h)]||u[h]||d[h]||s;return t?r.createElement(b,l(l({ref:n},p),{},{components:t})):r.createElement(b,l({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/e1a06456.e625e406.js b/assets/js/e1a06456.58ffb480.js similarity index 98% rename from assets/js/e1a06456.e625e406.js rename to assets/js/e1a06456.58ffb480.js index 030b40c00..d8bf4a53c 100644 --- a/assets/js/e1a06456.e625e406.js +++ b/assets/js/e1a06456.58ffb480.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9910],{54885:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>c,metadata:()=>s,toc:()=>a});var r=n(85893),o=n(3905);const c={title:"\uc6f9\uc18c\ucf13",slug:"websocket",tags:["WebSocket"]},i=void 0,s={permalink:"/websocket",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-26-WebSocket.mdx",source:"@site/blog/2023-2/2023-06-26-WebSocket.mdx",title:"\uc6f9\uc18c\ucf13",description:"\uc6f9\uc18c\ucf13",date:"2023-06-26T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 26\uc77c",tags:[{label:"WebSocket",permalink:"/tags/web-socket"}],readingTime:4.165,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9\uc18c\ucf13",slug:"websocket",tags:["WebSocket"]},unlisted:!1,prevItem:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",permalink:"/java-spring-springboot"},nextItem:{title:"Docusaurus",permalink:"/docusaurus"}},l={authorsImageUrls:[]},a=[{value:"\uc6f9\uc18c\ucf13",id:"\uc6f9\uc18c\ucf13",level:3},{value:"\uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd",id:"\uc6f9\uc18c\ucf13-\ub4f1\uc7a5-\ubc30\uacbd",level:3},{value:"\uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791",id:"\uc6f9\uc18c\ucf13\uc758-\ub3d9\uc791",level:3},{value:"1. Upgrade \uc694\uccad",id:"1-upgrade-\uc694\uccad",level:3},{value:"2. Switching Protocols",id:"2-switching-protocols",level:3},{value:"3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc",id:"3-\ud1b5\uc2e0-\ud6c4-\uc885\ub8cc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",ul:"ul",...(0,o.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13",children:"\uc6f9\uc18c\ucf13"}),"\n",(0,r.jsxs)(t.p,{children:["\ub2e8\uc77c TCP \uc5f0\uacb0\uc744 \ud1b5\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04 \uc804\uc774\uc911 \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\ud1a0\ucf5c",(0,r.jsx)(t.br,{}),"\n","\uc6f9 \ud658\uacbd\uc5d0\uc11c \uc5f0\uc18d\ub41c \ub370\uc774\ud130\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:"\uc6f9\uc18c\ucf13\uc740 HTTP\uc758 \ud3ec\ud2b8\ub97c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud558\uace0 \uac01\uac01 \ud3ec\ud2b8 80\uacfc \ud3ec\ud2b8 443\uc744 \uc0ac\uc6a9\ud558\uc5ec HTTP(ws://) \ubc0f HTTPS(wss://)\ub85c \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud55c\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13-\ub4f1\uc7a5-\ubc30\uacbd",children:"\uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd"}),"\n",(0,r.jsxs)(t.p,{children:["\uc6f9\uc18c\ucf13\uc774 \ub4f1\uc7a5\ud558\uae30 \uc774\uc804, \uc2e4\uc2dc\uac04\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 Polling, Long polling, Streaming \uac19\uc740 \uae30\uc220\uc744 \uc0ac\uc6a9\ud588\uc5b4\uc57c \ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \uc2e4\uc2dc\uac04\uc131\uc774\ub098 \uc591\ubc29\ud5a5\uc131\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \ubabb\ud588\uace0, HTTP\ub97c \uc774\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uacfc\ub3c4\ud55c \uc624\ubc84\ud5e4\ub4dc\uac00 \ubc1c\uc0dd\ud588\ub2e4."]}),"\n",(0,r.jsxs)(t.admonition,{title:"polling, long polling, streaming",type:"note",children:[(0,r.jsx)(t.p,{children:"Polling: \uc8fc\uae30\uc801\uc73c\ub85c \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ubcf4\ub0b4 \uc218\uc2e0\ud560 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\uc11c\ubc84\uc5d0\uc11c \ubcf4\ub0bc \ub0b4\uc6a9\uc774 \uc5c6\uc5b4\ub3c4 \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc54c \uc218 \uc5c6\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\uacc4\uc18d\ud574\uc11c \uc694\uccad\uc744 \ubcf4\ub0b4 \ud655\uc778\uc744 \ud574\uc57c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ubd88\ud544\uc694\ud55c \ubd80\ud558\ub97c \uc8fc\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),(0,r.jsx)(t.p,{children:"Long Polling: \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc5d0 \ub300\ud574 \uc751\ub2f5\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uace0 \uc788\ub2e4\uac00 \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud588\uc744\ub54c \uc751\ub2f5\ud558\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud3f4\ub9c1 \ubc29\uc2dd\ubcf4\ub2e4 \uc11c\ubc84\uc5d0 \uc801\uc740 \ubd80\ud558\ub97c \uc904 \uc218 \uc788\uc9c0\ub9cc, \uc694\uccad\uc758 \uc8fc\uae30\uac00 \uc9e7\uc73c\uba74 \ud3f4\ub9c1\uacfc \ucc28\uc774\uac00 \uc5c6\uc5b4\uc9c4\ub2e4."}),"\n"]}),(0,r.jsx)(t.p,{children:"Streaming: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 request\ub97c \ubcf4\ub0b4\uba74 \ucee4\ub125\uc158\uc744 \ub9fa\uace0, \uc774 \ucee4\ub125\uc158\uc744 \uc720\uc9c0\ud558\uba74\uc11c \uc11c\ubc84\uac00 \uacc4\uc18d \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ud558\uace0 \uc2f6\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ucee4\ub125\uc158\uc744 \ub9fa\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]})]}),"\n",(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13\uc758-\ub3d9\uc791",children:"\uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791"}),"\n",(0,r.jsx)(t.mermaid,{value:"sequenceDiagram\n participant Client\n participant Server\n Client->>Server: Handshake - Upgrade\ub97c \uc774\uc6a9\ud55c WebSocket \uc804\ud658 \uc694\uccad\n Server->>Client: Handshake - HttpStatus 101(Switching Protocols)\n\n Client->>Server: \uc591\ubc29\ud5a5 \ud1b5\uc2e0\n Server->>Client: \n\n Client->>Server: \uc885\ub8cc\n Server->>Client: "}),"\n",(0,r.jsx)(t.h3,{id:"1-upgrade-\uc694\uccad",children:"1. Upgrade \uc694\uccad"}),"\n",(0,r.jsxs)(t.p,{children:["WebSocket \ud504\ub85c\ud1a0\ucf5c\ub85c \uc804\ud658\ud558\ub294 HTTP \uc694\uccad\uc744 \ubcf4\ub0b8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 HTTP\uc640 \uac19\uc774 80, 443 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc6f9\uc18c\ucf13\uc73c\ub85c \uc804\ud658\ud558\uae30 \uc704\ud574\uc11c\ub294 Upgrade: websocket, Connection: Upgrade \ud5e4\ub354\uac00 \ud544\uc694\ud558\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Key\ub294 \uc11c\ubc84\uc5d0\uc11c Sec-WebSocket-Accept\ub97c \uacc4\uc0b0\ud558\uc5ec \uc751\ub2f5\ud558\uace0 \uc774 \uac12\uc774 \uc608\uc0c1\ud55c \uac12\uacfc \ub2e4\ub974\uba74 \uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Protocol\uc758 \uacbd\uc6b0 \uc11c\ube0c\ud504\ub85c\ud1a0\ucf5c\uc758 \ubaa9\ub85d\uc73c\ub85c \uc11c\ubc84 \uce21\uc5d0\uc11c\ub294 \ud574\ub2f9 \ubaa9\ub85d \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud558\uc5ec \ubc18\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub9cc\uc57d \uc11c\ubc84\uce21\uc5d0\uc11c \uc5ec\ub7ec \uac1c \uc9c0\uc6d0\uc774 \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc9c0\uc6d0 \uac00\ub2a5\ud55c \ud504\ub85c\ud1a0\ucf5c \uc911 \uccab\ubc88\uc9f8 \ud504\ub85c\ud1a0\ucf5c\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc73c\ub85c \ubcf4\ub0b8\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"GET /chats HTTP/1.1\nHost: localhost:8080\nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==\nSec-WebSocket-Protocol: v10.stomp, v11.stomp\nSec-WebSocket-Version: 13\nOrigin: http://localhost:8080\n"})}),"\n",(0,r.jsx)(t.h3,{id:"2-switching-protocols",children:"2. Switching Protocols"}),"\n",(0,r.jsxs)(t.p,{children:["\uc11c\ubc84\ub294 101 Switching Protocols \uc751\ub2f5\uc744 \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Accept\uc740 Sec-WebSocket-Key \ub4a4\uc5d0 ",(0,r.jsx)(t.code,{children:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"}),"\ub97c \ubd99\uc774\uace0 SHA1\ub85c \ud574\uc2f1 \ud6c4 Base64\ub85c \uc778\ucf54\ub529\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \uc11c\ubc84 \uc6f9\uc18c\ucf13 \ud504\ub85c\ud1a0\ucf5c\uc758 \uc9c0\uc6d0 \uc5ec\ubd80\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uba85\ud655\ud788 \uc54c\ub9ac\uae30 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"HTTP/1.1 101 Switching Protocols \nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=\nSec-WebSocket-Protocol: v10.stomp\n"})}),"\n",(0,r.jsx)(t.h3,{id:"3-\ud1b5\uc2e0-\ud6c4-\uc885\ub8cc",children:"3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:["\uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uba74 \uc6f9\uc18c\ucf13 \ud504\ub808\uc784 \ub2e8\uc704\ub85c \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc5f0\uacb0 \uc885\ub8cc\ub97c \uc6d0\ud558\ub294 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8, \uc11c\ubc84 \ubaa8\ub450 \uc5f0\uacb0 \uc885\ub8cc\ub97c \uc694\uccad\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://datatracker.ietf.org/doc/html/rfc6455",children:"https://datatracker.ietf.org/doc/html/rfc6455"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications",children:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers",children:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://docs.spring.io/spring-framework/reference/web/websocket.html",children:"https://docs.spring.io/spring-framework/reference/web/websocket.html"})]})]})}function d(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>a});var r=n(67294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),a=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),h=a(n),b=o,g=h["".concat(l,".").concat(b)]||h[b]||p[b]||c;return n?r.createElement(g,i(i({ref:t},d),{},{components:n})):r.createElement(g,i({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9910],{54885:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>c,metadata:()=>s,toc:()=>a});var r=n(85893),o=n(3905);const c={title:"\uc6f9\uc18c\ucf13",slug:"websocket",tags:["WebSocket"]},i=void 0,s={permalink:"/websocket",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-26-WebSocket.mdx",source:"@site/blog/2023-2/2023-06-26-WebSocket.mdx",title:"\uc6f9\uc18c\ucf13",description:"\uc6f9\uc18c\ucf13",date:"2023-06-26T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 26\uc77c",tags:[{label:"WebSocket",permalink:"/tags/web-socket"}],readingTime:4.165,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9\uc18c\ucf13",slug:"websocket",tags:["WebSocket"]},unlisted:!1,prevItem:{title:"Docusaurus",permalink:"/docusaurus"},nextItem:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",permalink:"/java-spring-springboot"}},l={authorsImageUrls:[]},a=[{value:"\uc6f9\uc18c\ucf13",id:"\uc6f9\uc18c\ucf13",level:3},{value:"\uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd",id:"\uc6f9\uc18c\ucf13-\ub4f1\uc7a5-\ubc30\uacbd",level:3},{value:"\uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791",id:"\uc6f9\uc18c\ucf13\uc758-\ub3d9\uc791",level:3},{value:"1. Upgrade \uc694\uccad",id:"1-upgrade-\uc694\uccad",level:3},{value:"2. Switching Protocols",id:"2-switching-protocols",level:3},{value:"3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc",id:"3-\ud1b5\uc2e0-\ud6c4-\uc885\ub8cc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",ul:"ul",...(0,o.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13",children:"\uc6f9\uc18c\ucf13"}),"\n",(0,r.jsxs)(t.p,{children:["\ub2e8\uc77c TCP \uc5f0\uacb0\uc744 \ud1b5\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04 \uc804\uc774\uc911 \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\ud1a0\ucf5c",(0,r.jsx)(t.br,{}),"\n","\uc6f9 \ud658\uacbd\uc5d0\uc11c \uc5f0\uc18d\ub41c \ub370\uc774\ud130\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:"\uc6f9\uc18c\ucf13\uc740 HTTP\uc758 \ud3ec\ud2b8\ub97c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud558\uace0 \uac01\uac01 \ud3ec\ud2b8 80\uacfc \ud3ec\ud2b8 443\uc744 \uc0ac\uc6a9\ud558\uc5ec HTTP(ws://) \ubc0f HTTPS(wss://)\ub85c \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud55c\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13-\ub4f1\uc7a5-\ubc30\uacbd",children:"\uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd"}),"\n",(0,r.jsxs)(t.p,{children:["\uc6f9\uc18c\ucf13\uc774 \ub4f1\uc7a5\ud558\uae30 \uc774\uc804, \uc2e4\uc2dc\uac04\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 Polling, Long polling, Streaming \uac19\uc740 \uae30\uc220\uc744 \uc0ac\uc6a9\ud588\uc5b4\uc57c \ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \uc2e4\uc2dc\uac04\uc131\uc774\ub098 \uc591\ubc29\ud5a5\uc131\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \ubabb\ud588\uace0, HTTP\ub97c \uc774\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uacfc\ub3c4\ud55c \uc624\ubc84\ud5e4\ub4dc\uac00 \ubc1c\uc0dd\ud588\ub2e4."]}),"\n",(0,r.jsxs)(t.admonition,{title:"polling, long polling, streaming",type:"note",children:[(0,r.jsx)(t.p,{children:"Polling: \uc8fc\uae30\uc801\uc73c\ub85c \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ubcf4\ub0b4 \uc218\uc2e0\ud560 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\uc11c\ubc84\uc5d0\uc11c \ubcf4\ub0bc \ub0b4\uc6a9\uc774 \uc5c6\uc5b4\ub3c4 \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc54c \uc218 \uc5c6\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\uacc4\uc18d\ud574\uc11c \uc694\uccad\uc744 \ubcf4\ub0b4 \ud655\uc778\uc744 \ud574\uc57c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ubd88\ud544\uc694\ud55c \ubd80\ud558\ub97c \uc8fc\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),(0,r.jsx)(t.p,{children:"Long Polling: \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc5d0 \ub300\ud574 \uc751\ub2f5\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uace0 \uc788\ub2e4\uac00 \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud588\uc744\ub54c \uc751\ub2f5\ud558\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud3f4\ub9c1 \ubc29\uc2dd\ubcf4\ub2e4 \uc11c\ubc84\uc5d0 \uc801\uc740 \ubd80\ud558\ub97c \uc904 \uc218 \uc788\uc9c0\ub9cc, \uc694\uccad\uc758 \uc8fc\uae30\uac00 \uc9e7\uc73c\uba74 \ud3f4\ub9c1\uacfc \ucc28\uc774\uac00 \uc5c6\uc5b4\uc9c4\ub2e4."}),"\n"]}),(0,r.jsx)(t.p,{children:"Streaming: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 request\ub97c \ubcf4\ub0b4\uba74 \ucee4\ub125\uc158\uc744 \ub9fa\uace0, \uc774 \ucee4\ub125\uc158\uc744 \uc720\uc9c0\ud558\uba74\uc11c \uc11c\ubc84\uac00 \uacc4\uc18d \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ud558\uace0 \uc2f6\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ucee4\ub125\uc158\uc744 \ub9fa\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]})]}),"\n",(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13\uc758-\ub3d9\uc791",children:"\uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791"}),"\n",(0,r.jsx)(t.mermaid,{value:"sequenceDiagram\n participant Client\n participant Server\n Client->>Server: Handshake - Upgrade\ub97c \uc774\uc6a9\ud55c WebSocket \uc804\ud658 \uc694\uccad\n Server->>Client: Handshake - HttpStatus 101(Switching Protocols)\n\n Client->>Server: \uc591\ubc29\ud5a5 \ud1b5\uc2e0\n Server->>Client: \n\n Client->>Server: \uc885\ub8cc\n Server->>Client: "}),"\n",(0,r.jsx)(t.h3,{id:"1-upgrade-\uc694\uccad",children:"1. Upgrade \uc694\uccad"}),"\n",(0,r.jsxs)(t.p,{children:["WebSocket \ud504\ub85c\ud1a0\ucf5c\ub85c \uc804\ud658\ud558\ub294 HTTP \uc694\uccad\uc744 \ubcf4\ub0b8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 HTTP\uc640 \uac19\uc774 80, 443 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc6f9\uc18c\ucf13\uc73c\ub85c \uc804\ud658\ud558\uae30 \uc704\ud574\uc11c\ub294 Upgrade: websocket, Connection: Upgrade \ud5e4\ub354\uac00 \ud544\uc694\ud558\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Key\ub294 \uc11c\ubc84\uc5d0\uc11c Sec-WebSocket-Accept\ub97c \uacc4\uc0b0\ud558\uc5ec \uc751\ub2f5\ud558\uace0 \uc774 \uac12\uc774 \uc608\uc0c1\ud55c \uac12\uacfc \ub2e4\ub974\uba74 \uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Protocol\uc758 \uacbd\uc6b0 \uc11c\ube0c\ud504\ub85c\ud1a0\ucf5c\uc758 \ubaa9\ub85d\uc73c\ub85c \uc11c\ubc84 \uce21\uc5d0\uc11c\ub294 \ud574\ub2f9 \ubaa9\ub85d \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud558\uc5ec \ubc18\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub9cc\uc57d \uc11c\ubc84\uce21\uc5d0\uc11c \uc5ec\ub7ec \uac1c \uc9c0\uc6d0\uc774 \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc9c0\uc6d0 \uac00\ub2a5\ud55c \ud504\ub85c\ud1a0\ucf5c \uc911 \uccab\ubc88\uc9f8 \ud504\ub85c\ud1a0\ucf5c\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc73c\ub85c \ubcf4\ub0b8\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"GET /chats HTTP/1.1\nHost: localhost:8080\nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==\nSec-WebSocket-Protocol: v10.stomp, v11.stomp\nSec-WebSocket-Version: 13\nOrigin: http://localhost:8080\n"})}),"\n",(0,r.jsx)(t.h3,{id:"2-switching-protocols",children:"2. Switching Protocols"}),"\n",(0,r.jsxs)(t.p,{children:["\uc11c\ubc84\ub294 101 Switching Protocols \uc751\ub2f5\uc744 \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Accept\uc740 Sec-WebSocket-Key \ub4a4\uc5d0 ",(0,r.jsx)(t.code,{children:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"}),"\ub97c \ubd99\uc774\uace0 SHA1\ub85c \ud574\uc2f1 \ud6c4 Base64\ub85c \uc778\ucf54\ub529\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \uc11c\ubc84 \uc6f9\uc18c\ucf13 \ud504\ub85c\ud1a0\ucf5c\uc758 \uc9c0\uc6d0 \uc5ec\ubd80\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uba85\ud655\ud788 \uc54c\ub9ac\uae30 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"HTTP/1.1 101 Switching Protocols \nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=\nSec-WebSocket-Protocol: v10.stomp\n"})}),"\n",(0,r.jsx)(t.h3,{id:"3-\ud1b5\uc2e0-\ud6c4-\uc885\ub8cc",children:"3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:["\uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uba74 \uc6f9\uc18c\ucf13 \ud504\ub808\uc784 \ub2e8\uc704\ub85c \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc5f0\uacb0 \uc885\ub8cc\ub97c \uc6d0\ud558\ub294 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8, \uc11c\ubc84 \ubaa8\ub450 \uc5f0\uacb0 \uc885\ub8cc\ub97c \uc694\uccad\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://datatracker.ietf.org/doc/html/rfc6455",children:"https://datatracker.ietf.org/doc/html/rfc6455"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications",children:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers",children:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://docs.spring.io/spring-framework/reference/web/websocket.html",children:"https://docs.spring.io/spring-framework/reference/web/websocket.html"})]})]})}function d(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>a});var r=n(67294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),a=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),h=a(n),b=o,g=h["".concat(l,".").concat(b)]||h[b]||p[b]||c;return n?r.createElement(g,i(i({ref:t},d),{},{components:n})):r.createElement(g,i({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/e2326195.c1345a1c.js b/assets/js/e2326195.07314e50.js similarity index 97% rename from assets/js/e2326195.c1345a1c.js rename to assets/js/e2326195.07314e50.js index 878856abb..1b8a2f175 100644 --- a/assets/js/e2326195.c1345a1c.js +++ b/assets/js/e2326195.07314e50.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9467],{45682:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var t=r(85893),c=r(3905);const a={title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},o=void 0,i={permalink:"/log-async-exception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",description:"\ubb38\uc81c \uc0c1\ud669",date:"2023-09-18T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 18\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"exception",permalink:"/tags/exception"}],readingTime:3.615,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},unlisted:!1,prevItem:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",permalink:"/web-application-evolution"},nextItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"}},s={authorsImageUrls:[]},l=[{value:"\ubb38\uc81c \uc0c1\ud669",id:"\ubb38\uc81c-\uc0c1\ud669",level:3},{value:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",level:3},{value:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c",id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={a:"a",br:"br",code:"code",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ubb38\uc81c-\uc0c1\ud669",children:"\ubb38\uc81c \uc0c1\ud669"}),"\n",(0,t.jsxs)(n.p,{children:["\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 ",(0,t.jsx)(n.code,{children:"@Async"}),"\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 ",(0,t.jsx)(n.code,{children:"@ControllerAdvice"})," + ",(0,t.jsx)(n.code,{children:"@ExceptionHandler"}),"\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",children:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1 4.1 \ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html",children:"AsyncUncaughtExceptionHandler"}),"\uc758 \uacbd\uc6b0 \ubc18\ud658 \ud0c0\uc785\uc774 void\uc778 \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\ub97c \uc608\uc678 \ucc98\ub9ac\ud558\uae30 \uc27d\ub3c4\ub85d \ub3c4\uc640\uc900\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ub530\ub77c\uc11c AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ud578\ub4e4\ub9c1\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 \ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\ub3c4 \ub9c8\ucc2c\uac00\uc9c0\ub85c MDC\uc758 \uc815\ubcf4\ub97c \uac00\uc838\uc640\uc11c \ub85c\uadf8\ub97c \ucd9c\ub825\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncExceptionHandler",children:'@Slf4j\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\n\n private static final String LOG_FORMAT = "[%s] %s";\n\n @Override\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["AsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","getAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncConfig",children:"@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc774\uc81c \ube44\ub3d9\uae30 \uc0c1\ud669\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544 \ucc98\ub9ac\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",children:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c"}),"\n",(0,t.jsx)(n.p,{children:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"./mdc-null.png",src:r(81450).Z+"",width:"2236",height:"426"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html",children:"TaskDecorator"}),"\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=MdcTaskDecorator",children:"public class MdcTaskDecorator implements TaskDecorator {\n\n @Override\n public Runnable decorate(final Runnable runnable) {\n Map threadContext = MDC.getCopyOfContextMap();\n return () -> {\n MDC.setContextMap(threadContext);\n runnable.run();\n };\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc0dd\uc131\ud55c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncConfig",children:"@RequiredArgsConstructor\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n private final AsyncConfigurationProperties properties;\n\n @Bean\n public ThreadPoolTaskExecutor taskExecutor() {\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n executor.setCorePoolSize(properties.coreSize());\n executor.setMaxPoolSize(properties.maxSize());\n executor.setQueueCapacity(properties.queueCapacity());\n \n // highlight-next-line\n executor.setTaskDecorator(new MdcTaskDecorator());\n executor.setWaitForTasksToCompleteOnShutdown(true);\n executor.initialize();\n return executor;\n }\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"./mdc-not-null.png",src:r(97754).Z+"",width:"2620",height:"440"})}),"\n",(0,t.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://www.baeldung.com/spring-async",children:"spring async, baeldung"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception",children:"@Async will not call by @ControllerAdvice for global exception"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://blog.gangnamunni.com/post/mdc-context-task-decorator/",children:"Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html",children:"TaskDecorator, Spring docs"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html",children:"AsyncUncaughtExceptionHandler"})]})]})}function d(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>l});var t=r(67294);function c(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(c[r]=e[r]);return c}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var s=t.createContext({}),l=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,c=e.mdxType,a=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),u=l(r),g=c,h=u["".concat(s,".").concat(g)]||u[g]||p[g]||a;return r?t.createElement(h,o(o({ref:n},d),{},{components:r})):t.createElement(h,o({ref:n},d))}));d.displayName="MDXCreateElement"},97754:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/mdc-not-null-2b12c13f4f420a335c9e55dbea503f1b.png"},81450:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/mdc-null-95b3bbdce99ef36ba843986413e0421a.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9467],{45682:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var t=r(85893),c=r(3905);const a={title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},o=void 0,i={permalink:"/log-async-exception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",description:"\ubb38\uc81c \uc0c1\ud669",date:"2023-09-18T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 18\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"exception",permalink:"/tags/exception"}],readingTime:3.615,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},unlisted:!1,prevItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"},nextItem:{title:"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815",permalink:"/web-application-evolution"}},s={authorsImageUrls:[]},l=[{value:"\ubb38\uc81c \uc0c1\ud669",id:"\ubb38\uc81c-\uc0c1\ud669",level:3},{value:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",level:3},{value:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c",id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const n={a:"a",br:"br",code:"code",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ubb38\uc81c-\uc0c1\ud669",children:"\ubb38\uc81c \uc0c1\ud669"}),"\n",(0,t.jsxs)(n.p,{children:["\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 ",(0,t.jsx)(n.code,{children:"@Async"}),"\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 ",(0,t.jsx)(n.code,{children:"@ControllerAdvice"})," + ",(0,t.jsx)(n.code,{children:"@ExceptionHandler"}),"\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",children:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815"}),"\n",(0,t.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1 4.1 \ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html",children:"AsyncUncaughtExceptionHandler"}),"\uc758 \uacbd\uc6b0 \ubc18\ud658 \ud0c0\uc785\uc774 void\uc778 \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\ub97c \uc608\uc678 \ucc98\ub9ac\ud558\uae30 \uc27d\ub3c4\ub85d \ub3c4\uc640\uc900\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ub530\ub77c\uc11c AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ud578\ub4e4\ub9c1\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae30\uc874\uc758 \ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac\ub3c4 \ub9c8\ucc2c\uac00\uc9c0\ub85c MDC\uc758 \uc815\ubcf4\ub97c \uac00\uc838\uc640\uc11c \ub85c\uadf8\ub97c \ucd9c\ub825\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncExceptionHandler",children:'@Slf4j\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\n\n private static final String LOG_FORMAT = "[%s] %s";\n\n @Override\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["AsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,t.jsx)(n.br,{}),"\n","getAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncConfig",children:"@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc774\uc81c \ube44\ub3d9\uae30 \uc0c1\ud669\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544 \ucc98\ub9ac\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.h3,{id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",children:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c"}),"\n",(0,t.jsx)(n.p,{children:"\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"./mdc-null.png",src:r(81450).Z+"",width:"2236",height:"426"})}),"\n",(0,t.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html",children:"TaskDecorator"}),"\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=MdcTaskDecorator",children:"public class MdcTaskDecorator implements TaskDecorator {\n\n @Override\n public Runnable decorate(final Runnable runnable) {\n Map threadContext = MDC.getCopyOfContextMap();\n return () -> {\n MDC.setContextMap(threadContext);\n runnable.run();\n };\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc0dd\uc131\ud55c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",metastring:"title=AsyncConfig",children:"@RequiredArgsConstructor\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n private final AsyncConfigurationProperties properties;\n\n @Bean\n public ThreadPoolTaskExecutor taskExecutor() {\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n executor.setCorePoolSize(properties.coreSize());\n executor.setMaxPoolSize(properties.maxSize());\n executor.setQueueCapacity(properties.queueCapacity());\n \n // highlight-next-line\n executor.setTaskDecorator(new MdcTaskDecorator());\n executor.setWaitForTasksToCompleteOnShutdown(true);\n executor.initialize();\n return executor;\n }\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"./mdc-not-null.png",src:r(97754).Z+"",width:"2620",height:"440"})}),"\n",(0,t.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://www.baeldung.com/spring-async",children:"spring async, baeldung"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception",children:"@Async will not call by @ControllerAdvice for global exception"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://blog.gangnamunni.com/post/mdc-context-task-decorator/",children:"Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html",children:"TaskDecorator, Spring docs"}),(0,t.jsx)(n.br,{}),"\n",(0,t.jsx)(n.a,{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.html",children:"AsyncUncaughtExceptionHandler"})]})]})}function d(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>l});var t=r(67294);function c(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(c[r]=e[r]);return c}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(c[r]=e[r])}return c}var s=t.createContext({}),l=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,c=e.mdxType,a=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),u=l(r),g=c,h=u["".concat(s,".").concat(g)]||u[g]||p[g]||a;return r?t.createElement(h,o(o({ref:n},d),{},{components:r})):t.createElement(h,o({ref:n},d))}));d.displayName="MDXCreateElement"},97754:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/mdc-not-null-2b12c13f4f420a335c9e55dbea503f1b.png"},81450:(e,n,r)=>{r.d(n,{Z:()=>t});const t=r.p+"assets/images/mdc-null-95b3bbdce99ef36ba843986413e0421a.png"}}]); \ No newline at end of file diff --git a/assets/js/e6a6ed43.a7a88c94.js b/assets/js/e6a6ed43.9f35502e.js similarity index 98% rename from assets/js/e6a6ed43.a7a88c94.js rename to assets/js/e6a6ed43.9f35502e.js index 6c7366a8f..20f417d48 100644 --- a/assets/js/e6a6ed43.a7a88c94.js +++ b/assets/js/e6a6ed43.9f35502e.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5300],{66940:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>t,metadata:()=>o,toc:()=>a});var i=r(85893),l=r(3905);const t={title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",slug:"grasp",tags:["GRASP","OOP"]},s=void 0,o={permalink:"/grasp",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-30-GRASP.mdx",source:"@site/blog/2023-1/2023-03-30-GRASP.mdx",title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",description:"GRASP(General Responsibility Assignment Software Pattern)",date:"2023-03-30T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 30\uc77c",tags:[{label:"GRASP",permalink:"/tags/grasp"},{label:"OOP",permalink:"/tags/oop"}],readingTime:8.085,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",slug:"grasp",tags:["GRASP","OOP"]},unlisted:!1,prevItem:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",permalink:"/chess-retrospective"},nextItem:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",permalink:"/blackjack-retrospective"}},c={authorsImageUrls:[]},a=[{value:"GRASP(General Responsibility Assignment Software Pattern)",id:"graspgeneral-responsibility-assignment-software-pattern",level:3},{value:"\uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)",id:"\uc815\ubcf4-\uc804\ubb38\uac00-\ud328\ud134information-expert",level:3},{value:"\ucc3d\uc870\uc790 \ud328\ud134(Creator)",id:"\ucc3d\uc870\uc790-\ud328\ud134creator",level:3},{value:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)",id:"\ub0ae\uc740-\uacb0\ud569\ub3c4-\ud328\ud134low-coupling",level:3},{value:"\ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)",id:"\ub192\uc740-\uc751\uc9d1\ub3c4-\ud328\ud134high-cohesion",level:3},{value:"\ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)",id:"\ucee8\ud2b8\ub864\ub7ec-\ud328\ud134controller",level:3},{value:"\ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)",id:"\ub2e4\ud615\uc131-\ud328\ud134polymorphism",level:3},{value:"\ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)",id:"\ubcc0\uacbd-\ubcf4\ud638-\ud328\ud134protected-variations",level:3},{value:"\uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)",id:"\uac04\uc811-\ucc38\uc870-\ud328\ud134indirection",level:3},{value:"\uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)",id:"\uc21c\uc218\ud55c-\uac00\uacf5\ubb3c-\ud328\ud134pure-fabrication",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",blockquote:"blockquote",h3:"h3",li:"li",p:"p",ul:"ul",...(0,l.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"graspgeneral-responsibility-assignment-software-pattern",children:"GRASP(General Responsibility Assignment Software Pattern)"}),"\n",(0,i.jsx)(n.p,{children:"\ud06c\ub808\uc774\uadf8 \ub77c\ub9cc\uc758 Applying UML and Patterns\uc774\ub77c\ub294 \ucc45\uc5d0\uc11c \ub098\uc628 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134"}),"\n",(0,i.jsx)(n.p,{children:"\uac01 \ud328\ud134\ub9c8\ub2e4 Solution\uacfc Problem\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uc815\ubcf4-\uc804\ubb38\uac00-\ud328\ud134information-expert",children:"\uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \uac1d\uccb4\uc5d0 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uae30\ubcf8 \uc6d0\uce59\uc740 \ubb34\uc5c7\uc778\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A: \ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub370 \ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \ud074\ub798\uc2a4(\uc815\ubcf4 \uc804\ubb38\uac00)\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc815\ubcf4\uc640 \ud589\ub3d9\uc744 \uac00\uae4c\uc6b4 \uacf3\uc5d0 \uc704\uce58\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \ucea1\uc290\ud654\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \uac1d\uccb4\ub4e4\ub85c \ucc45\uc784\uc774 \ubd84\uc0b0\ub41c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ucc3d\uc870\uc790-\ud328\ud134creator",children:"\ucc3d\uc870\uc790 \ud328\ud134(Creator)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \ub204\uac00 \uac1d\uccb4 A\ub97c \uc0dd\uc131\ud558\ub294\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A: \ub2e4\uc74c\uc758 \uc870\uac74\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\uc871\ud558\ub294 \uac1d\uccb4\uc5d0\uac8c \uac1d\uccb4 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\uc758 \ucd08\uae30\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"\uc0dd\uc131 \uc608\uc815\uc778 \uac1d\uccb4\uc640 \uc5f0\uad00\ub418\uc5b4 \uc788\ub294 \uac1d\uccb4\uac00 \uc0dd\uc131 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac8c \ub41c\ub2e4\uba74, \uc774\ubbf8 \ud574\ub2f9 \uac1d\uccb4\uc640 \uacb0\ud569\ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\uac8c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ub0ae\uc740-\uacb0\ud569\ub3c4-\ud328\ud134low-coupling",children:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \uc758\uc874\uc131\uc744 \ub0ae\ucd94\uace0 \ubcc0\ud654\uc758 \uc601\ud5a5\uc744 \uc904\uc774\uba70 \uc7ac\uc0ac\uc6a9\uc131\uc744 \uc99d\uac00\uc2dc\ud0a4\ub294 \ubc29\ubc95\uc740?"}),"\n",(0,i.jsx)(n.p,{children:"A: \uc804\uccb4\uc801\uc778 \uacb0\ud569\uc774 \ub0ae\uac8c \uc720\uc9c0\ub418\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"\uacb0\ud569\ub3c4(Coupling)\n\uac1d\uccb4 \uc0ac\uc774\uc758 \uc758\uc874\uc131\uc774 \uacfc\ud55c \uacbd\uc6b0 \uacb0\ud569\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc624\ube0c\uc81d\ud2b8 p.17"}),"\n"]}),"\n",(0,i.jsx)(n.blockquote,{children:"\n"}),"\n",(0,i.jsx)(n.p,{children:"\uacb0\ud569\ub3c4\ub97c \ub0ae\ucd98\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\ub2e4\ub978 \uad6c\uc131 \uc694\uc18c\uc758 \ubcc0\ud654\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc7ac\uc0ac\uc6a9\uc774 \ud3b8\ub9ac\ud574\uc9c4\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\uc758\uc874\ud558\ub294 \ud074\ub798\uc2a4\uac00 \uc801\uae30 \ub54c\ubb38\uc5d0)"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ub192\uc740-\uc751\uc9d1\ub3c4-\ud328\ud134high-cohesion",children:"\ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uac1d\uccb4\ub97c \uad00\ub9ac\ud558\uae30 \uc27d\uac8c \ud558\ub824\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub192\uc740 \uc751\uc9d1\ub3c4\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"\uc751\uc9d1\ub3c4(Cohesion)\n\uc5f0\uad00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc5f0\uad00\uc131 \uc5c6\ub294 \uc791\uc5c5\uc740 \ub2e4\ub978 \uac1d\uccb4\uc5d0\uac8c \uc704\uc784\ud558\ub294 \uac1d\uccb4\ub97c \uac00\ub9ac\ucf1c \uc751\uc9d1\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc624\ube0c\uc81d\ud2b8 p.26"}),"\n"]}),"\n",(0,i.jsx)(n.blockquote,{children:"\n"}),"\n",(0,i.jsx)(n.p,{children:"\ubcc0\uacbd\uc758 \uc774\uc720\uc5d0 \ub530\ub77c \ud074\ub798\uc2a4\ub97c \ubd84\ub9ac\ud55c\ub2e4\uba74 \uc751\uc9d1\ub3c4\ub97c \ub192\uc77c \uc218 \uc788\uace0, \uc751\uc9d1\ub3c4\uac00 \ub192\uc544\uc9c4\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\ud560\ub2f9\ub41c \ucc45\uc784\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0)"}),"\n",(0,i.jsx)(n.li,{children:"\uc720\uc9c0\ubcf4\uc218\uac00 \uc26c\uc6cc\uc9c4\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ub610\ud55c \uc9c0\uc6d0\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc751\uc9d1\ub3c4\uac00 \ub192\uc740 \ud074\ub798\uc2a4\ub294 \ud2b9\uc815\ud55c \ubaa9\uc801\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc7ac\uc0ac\uc6a9\ud558\uae30 \uc88b\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucee8\ud2b8\ub864\ub7ec-\ud328\ud134controller",children:"\ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uac83\uc740 \ub204\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 Controller \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc5b4\ub5a4 \uc11c\ube0c\uc2dc\uc2a4\ud15c\uc774 \uc874\uc7ac\ud55c\ub2e4\uace0 \uac00\uc815\ud560 \ub54c"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc9c1\uc811\uc801\uc73c\ub85c \uac1d\uccb4\uc5d0 \uc811\uadfc\ud558\uc5ec \ud504\ub85c\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uacb0\ud569\ub3c4\uac00 \uc0c1\uc2b9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc11c\ube0c \uc2dc\uc2a4\ud15c\uc5d0 \ub4e4\uc5b4\uc624\ub294 \uc694\uccad\uc744 \ucc98\ub9ac\ud574\uc8fc\ub294 \ucee8\ud2b8\ub864\ub7ec\uac00 \uc788\ub2e4\uba74 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 \ud574\ub2f9 \ucee8\ud2b8\ub864\ub7ec\ub9cc \uc54c\uba74 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub9cc\uc57d \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc758 \ubcc0\uacbd\uc774 \uc0dd\uacbc\uc744 \ub54c \uc678\ubd80\uc5d0 \ubbf8\uce58\ub294 \uc601\ud5a5\ub3c4 \uc904\uc5b4\ub4e0\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ub2e4\ud615\uc131-\ud328\ud134polymorphism",children:"\ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uac1d\uccb4\uc758 \ud0c0\uc785\uc5d0 \ub530\ub77c \ud589\ub3d9\uc774 \ubc14\ub010\ub2e4\uba74 \ucc45\uc784\uc744 \uc5b4\ub5bb\uac8c \ud560\ub2f9\ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. OOP\uac00 \uc9c0\uc6d0\ud558\ub294 \ub2e4\ud615\uc131\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ud65c\uc6a9\ud55c\ub2e4. (\uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0 \ud589\ub3d9\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uad6c\ud604)"}),"\n",(0,i.jsx)(n.p,{children:"\uac1d\uccb4\uc758 \uc885\ub958\uc5d0 \ub530\ub77c \ubd84\uae30\ud558\ub294 \uc870\uac74\ubb38\uc774 \uc544\ub2cc \ub2e4\ud615\uc131\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc0c8\ub85c\uc6b4 \ud0c0\uc785\uc774 \ucd94\uac00\ub418\uc5c8\uc744 \ub54c \uc870\uac74\ubb38\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uae30\uc874\uc758 \uc870\uac74\ubb38\uc744 \uc218\uc815\ud574\uc57c \ud558\uc9c0\ub9cc \ub2e4\ud615\uc131\uc744 \ud65c\uc6a9\ud558\uba74 \uc27d\uac8c \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ubcc0\uacbd-\ubcf4\ud638-\ud328\ud134protected-variations",children:"\ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uc5b4\ub5bb\uac8c \ud558\uba74 \ubcc0\uacbd\uc774 \ub2e4\ub978 \uc694\uc18c\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud560 \uc218 \uc788\uc744\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ubcc0\ud654\uac00 \uc608\uc0c1\ub418\ub294 \uc9c0\uc810\uc744 \uc2dd\ubcc4\ud558\uace0, \uc8fc\uc704\uc5d0 \uc548\uc815\ub41c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud615\uc131\ud558\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uac04\uc811-\ucc38\uc870-\ud328\ud134indirection",children:"\uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud558\uace0 \uc2f6\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ub2e4\ub978 \uac1d\uccb4\ub97c \ub450\uc5b4 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uc7ac\uc790 \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ud558\ub098\uc758 \uac1d\uccb4\ub97c \ucd94\uac00\ud558\uc5ec \ubcf5\uc7a1\ud55c \uad00\uacc4\ub97c \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uac04\uc5d0 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub454\ub2e4\uba74 \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\uc5d0 \ud574\ub2f9\ub41c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uc21c\uc218\ud55c-\uac00\uacf5\ubb3c-\ud328\ud134pure-fabrication",children:"\uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \ucc45\uc784\uc744 \ud560\ub2f9\ud55c \ub3c4\uba54\uc778 \uac1d\uccb4\uac00 Low Coupling, High Cohesion, \uc7ac\uc0ac\uc6a9\uc131 \ub4f1\uc758 \ubaa9\uc801\uc744 \uc704\ubc18\ud55c\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub3c4\uba54\uc778 \uac1c\ub150\uc744 \ud3ec\ud568\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uace0 \ub9e4\uc6b0 \uc751\uc9d1\ub41c \ucc45\uc784\uc744 \ud560\ub2f9\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\ud589\ub3d9\uc744 \ucd94\uac00\ud560 \ub54c, \ud574\ub2f9 \ucc45\uc784\uc744 \uc218\ud589\ud560 \ub3c4\uba54\uc778 \uac1c\ub150\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \ub3c4\uba54\uc778\uacfc \ubb34\uad00\ud55c \uc778\uacf5\uc801\uc778 \uac1d\uccb4\ub97c \ub9cc\ub4e0\ub2e4\uc74c \ud574\ub2f9 \uac1d\uccb4\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uac1d\uccb4\uac00 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud574\uc57c \ud560 \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4\uace0, \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134\uc744 \uc801\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud558\ub77c\ub294 \ucc45\uc784\uc744 \uac00\uc9c0\ub77c\uace0 \ud558\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc608) \uc0c1\uc810\uacfc \uace0\uac1d \ud074\ub798\uc2a4\uac00 \uc788\uace0 \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uace0 \uac00\uc815"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 \uac70\ub798\ub97c \ud558\ub824\uba74 \ud658\uc804\uc744 \ud574\uc57c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub450 \ud074\ub798\uc2a4 \ub2e4 \ud658\uc804\uc5d0 \ub300\ud55c \ucc45\uc784\uc744 \ubd80\uc5ec\ud558\uae30 \uc560\ub9e4\ud558\ub2e4\uba74 \ud658\uc804\uc744 \ucc45\uc784\ud558\ub294 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud558\uace0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:["\uc624\ube0c\uc81d\ud2b8 5\uc7a5. \ucc45\uc784 \ud560\ub2f9\ud558\uae30, ",(0,i.jsx)(n.a,{href:"http://aeternum.egloos.com/",children:"\uc870\uc601\ud638"})]}),"\n",(0,i.jsx)(n.p,{children:"Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS8586826397",children:"GRASP, \ud55c\ube5b \ub124\ud2b8\uc6cc\ud06c"})})]})}function h(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var i=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function t(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var c=i.createContext({}),a=function(e){var n=i.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},h=i.forwardRef((function(e,n){var r=e.components,l=e.mdxType,t=e.originalType,c=e.parentName,h=o(e,["components","mdxType","originalType","parentName"]),p=a(r),j=l,x=p["".concat(c,".").concat(j)]||p[j]||d[j]||t;return r?i.createElement(x,s(s({ref:n},h),{},{components:r})):i.createElement(x,s({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5300],{66940:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>t,metadata:()=>o,toc:()=>a});var i=r(85893),l=r(3905);const t={title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",slug:"grasp",tags:["GRASP","OOP"]},s=void 0,o={permalink:"/grasp",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-30-GRASP.mdx",source:"@site/blog/2023-1/2023-03-30-GRASP.mdx",title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",description:"GRASP(General Responsibility Assignment Software Pattern)",date:"2023-03-30T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 30\uc77c",tags:[{label:"GRASP",permalink:"/tags/grasp"},{label:"OOP",permalink:"/tags/oop"}],readingTime:8.085,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",slug:"grasp",tags:["GRASP","OOP"]},unlisted:!1,prevItem:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",permalink:"/blackjack-retrospective"},nextItem:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",permalink:"/chess-retrospective"}},c={authorsImageUrls:[]},a=[{value:"GRASP(General Responsibility Assignment Software Pattern)",id:"graspgeneral-responsibility-assignment-software-pattern",level:3},{value:"\uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)",id:"\uc815\ubcf4-\uc804\ubb38\uac00-\ud328\ud134information-expert",level:3},{value:"\ucc3d\uc870\uc790 \ud328\ud134(Creator)",id:"\ucc3d\uc870\uc790-\ud328\ud134creator",level:3},{value:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)",id:"\ub0ae\uc740-\uacb0\ud569\ub3c4-\ud328\ud134low-coupling",level:3},{value:"\ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)",id:"\ub192\uc740-\uc751\uc9d1\ub3c4-\ud328\ud134high-cohesion",level:3},{value:"\ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)",id:"\ucee8\ud2b8\ub864\ub7ec-\ud328\ud134controller",level:3},{value:"\ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)",id:"\ub2e4\ud615\uc131-\ud328\ud134polymorphism",level:3},{value:"\ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)",id:"\ubcc0\uacbd-\ubcf4\ud638-\ud328\ud134protected-variations",level:3},{value:"\uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)",id:"\uac04\uc811-\ucc38\uc870-\ud328\ud134indirection",level:3},{value:"\uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)",id:"\uc21c\uc218\ud55c-\uac00\uacf5\ubb3c-\ud328\ud134pure-fabrication",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",blockquote:"blockquote",h3:"h3",li:"li",p:"p",ul:"ul",...(0,l.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"graspgeneral-responsibility-assignment-software-pattern",children:"GRASP(General Responsibility Assignment Software Pattern)"}),"\n",(0,i.jsx)(n.p,{children:"\ud06c\ub808\uc774\uadf8 \ub77c\ub9cc\uc758 Applying UML and Patterns\uc774\ub77c\ub294 \ucc45\uc5d0\uc11c \ub098\uc628 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134"}),"\n",(0,i.jsx)(n.p,{children:"\uac01 \ud328\ud134\ub9c8\ub2e4 Solution\uacfc Problem\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uc815\ubcf4-\uc804\ubb38\uac00-\ud328\ud134information-expert",children:"\uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \uac1d\uccb4\uc5d0 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uae30\ubcf8 \uc6d0\uce59\uc740 \ubb34\uc5c7\uc778\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A: \ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub370 \ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \ud074\ub798\uc2a4(\uc815\ubcf4 \uc804\ubb38\uac00)\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc815\ubcf4\uc640 \ud589\ub3d9\uc744 \uac00\uae4c\uc6b4 \uacf3\uc5d0 \uc704\uce58\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \ucea1\uc290\ud654\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \uac1d\uccb4\ub4e4\ub85c \ucc45\uc784\uc774 \ubd84\uc0b0\ub41c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ucc3d\uc870\uc790-\ud328\ud134creator",children:"\ucc3d\uc870\uc790 \ud328\ud134(Creator)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \ub204\uac00 \uac1d\uccb4 A\ub97c \uc0dd\uc131\ud558\ub294\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A: \ub2e4\uc74c\uc758 \uc870\uac74\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\uc871\ud558\ub294 \uac1d\uccb4\uc5d0\uac8c \uac1d\uccb4 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\uc758 \ucd08\uae30\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"\uc0dd\uc131 \uc608\uc815\uc778 \uac1d\uccb4\uc640 \uc5f0\uad00\ub418\uc5b4 \uc788\ub294 \uac1d\uccb4\uac00 \uc0dd\uc131 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac8c \ub41c\ub2e4\uba74, \uc774\ubbf8 \ud574\ub2f9 \uac1d\uccb4\uc640 \uacb0\ud569\ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\uac8c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ub0ae\uc740-\uacb0\ud569\ub3c4-\ud328\ud134low-coupling",children:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \uc758\uc874\uc131\uc744 \ub0ae\ucd94\uace0 \ubcc0\ud654\uc758 \uc601\ud5a5\uc744 \uc904\uc774\uba70 \uc7ac\uc0ac\uc6a9\uc131\uc744 \uc99d\uac00\uc2dc\ud0a4\ub294 \ubc29\ubc95\uc740?"}),"\n",(0,i.jsx)(n.p,{children:"A: \uc804\uccb4\uc801\uc778 \uacb0\ud569\uc774 \ub0ae\uac8c \uc720\uc9c0\ub418\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"\uacb0\ud569\ub3c4(Coupling)\n\uac1d\uccb4 \uc0ac\uc774\uc758 \uc758\uc874\uc131\uc774 \uacfc\ud55c \uacbd\uc6b0 \uacb0\ud569\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc624\ube0c\uc81d\ud2b8 p.17"}),"\n"]}),"\n",(0,i.jsx)(n.blockquote,{children:"\n"}),"\n",(0,i.jsx)(n.p,{children:"\uacb0\ud569\ub3c4\ub97c \ub0ae\ucd98\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\ub2e4\ub978 \uad6c\uc131 \uc694\uc18c\uc758 \ubcc0\ud654\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc7ac\uc0ac\uc6a9\uc774 \ud3b8\ub9ac\ud574\uc9c4\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\uc758\uc874\ud558\ub294 \ud074\ub798\uc2a4\uac00 \uc801\uae30 \ub54c\ubb38\uc5d0)"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ub192\uc740-\uc751\uc9d1\ub3c4-\ud328\ud134high-cohesion",children:"\ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uac1d\uccb4\ub97c \uad00\ub9ac\ud558\uae30 \uc27d\uac8c \ud558\ub824\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub192\uc740 \uc751\uc9d1\ub3c4\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"\uc751\uc9d1\ub3c4(Cohesion)\n\uc5f0\uad00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc5f0\uad00\uc131 \uc5c6\ub294 \uc791\uc5c5\uc740 \ub2e4\ub978 \uac1d\uccb4\uc5d0\uac8c \uc704\uc784\ud558\ub294 \uac1d\uccb4\ub97c \uac00\ub9ac\ucf1c \uc751\uc9d1\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc624\ube0c\uc81d\ud2b8 p.26"}),"\n"]}),"\n",(0,i.jsx)(n.blockquote,{children:"\n"}),"\n",(0,i.jsx)(n.p,{children:"\ubcc0\uacbd\uc758 \uc774\uc720\uc5d0 \ub530\ub77c \ud074\ub798\uc2a4\ub97c \ubd84\ub9ac\ud55c\ub2e4\uba74 \uc751\uc9d1\ub3c4\ub97c \ub192\uc77c \uc218 \uc788\uace0, \uc751\uc9d1\ub3c4\uac00 \ub192\uc544\uc9c4\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\ud560\ub2f9\ub41c \ucc45\uc784\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0)"}),"\n",(0,i.jsx)(n.li,{children:"\uc720\uc9c0\ubcf4\uc218\uac00 \uc26c\uc6cc\uc9c4\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ub610\ud55c \uc9c0\uc6d0\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc751\uc9d1\ub3c4\uac00 \ub192\uc740 \ud074\ub798\uc2a4\ub294 \ud2b9\uc815\ud55c \ubaa9\uc801\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc7ac\uc0ac\uc6a9\ud558\uae30 \uc88b\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucee8\ud2b8\ub864\ub7ec-\ud328\ud134controller",children:"\ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uac83\uc740 \ub204\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 Controller \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc5b4\ub5a4 \uc11c\ube0c\uc2dc\uc2a4\ud15c\uc774 \uc874\uc7ac\ud55c\ub2e4\uace0 \uac00\uc815\ud560 \ub54c"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc9c1\uc811\uc801\uc73c\ub85c \uac1d\uccb4\uc5d0 \uc811\uadfc\ud558\uc5ec \ud504\ub85c\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uacb0\ud569\ub3c4\uac00 \uc0c1\uc2b9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc11c\ube0c \uc2dc\uc2a4\ud15c\uc5d0 \ub4e4\uc5b4\uc624\ub294 \uc694\uccad\uc744 \ucc98\ub9ac\ud574\uc8fc\ub294 \ucee8\ud2b8\ub864\ub7ec\uac00 \uc788\ub2e4\uba74 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 \ud574\ub2f9 \ucee8\ud2b8\ub864\ub7ec\ub9cc \uc54c\uba74 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub9cc\uc57d \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc758 \ubcc0\uacbd\uc774 \uc0dd\uacbc\uc744 \ub54c \uc678\ubd80\uc5d0 \ubbf8\uce58\ub294 \uc601\ud5a5\ub3c4 \uc904\uc5b4\ub4e0\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ub2e4\ud615\uc131-\ud328\ud134polymorphism",children:"\ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uac1d\uccb4\uc758 \ud0c0\uc785\uc5d0 \ub530\ub77c \ud589\ub3d9\uc774 \ubc14\ub010\ub2e4\uba74 \ucc45\uc784\uc744 \uc5b4\ub5bb\uac8c \ud560\ub2f9\ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. OOP\uac00 \uc9c0\uc6d0\ud558\ub294 \ub2e4\ud615\uc131\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ud65c\uc6a9\ud55c\ub2e4. (\uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0 \ud589\ub3d9\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uad6c\ud604)"}),"\n",(0,i.jsx)(n.p,{children:"\uac1d\uccb4\uc758 \uc885\ub958\uc5d0 \ub530\ub77c \ubd84\uae30\ud558\ub294 \uc870\uac74\ubb38\uc774 \uc544\ub2cc \ub2e4\ud615\uc131\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc0c8\ub85c\uc6b4 \ud0c0\uc785\uc774 \ucd94\uac00\ub418\uc5c8\uc744 \ub54c \uc870\uac74\ubb38\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uae30\uc874\uc758 \uc870\uac74\ubb38\uc744 \uc218\uc815\ud574\uc57c \ud558\uc9c0\ub9cc \ub2e4\ud615\uc131\uc744 \ud65c\uc6a9\ud558\uba74 \uc27d\uac8c \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ubcc0\uacbd-\ubcf4\ud638-\ud328\ud134protected-variations",children:"\ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uc5b4\ub5bb\uac8c \ud558\uba74 \ubcc0\uacbd\uc774 \ub2e4\ub978 \uc694\uc18c\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud560 \uc218 \uc788\uc744\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ubcc0\ud654\uac00 \uc608\uc0c1\ub418\ub294 \uc9c0\uc810\uc744 \uc2dd\ubcc4\ud558\uace0, \uc8fc\uc704\uc5d0 \uc548\uc815\ub41c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud615\uc131\ud558\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uac04\uc811-\ucc38\uc870-\ud328\ud134indirection",children:"\uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud558\uace0 \uc2f6\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ub2e4\ub978 \uac1d\uccb4\ub97c \ub450\uc5b4 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uc7ac\uc790 \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ud558\ub098\uc758 \uac1d\uccb4\ub97c \ucd94\uac00\ud558\uc5ec \ubcf5\uc7a1\ud55c \uad00\uacc4\ub97c \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uac04\uc5d0 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub454\ub2e4\uba74 \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\uc5d0 \ud574\ub2f9\ub41c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uc21c\uc218\ud55c-\uac00\uacf5\ubb3c-\ud328\ud134pure-fabrication",children:"\uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \ucc45\uc784\uc744 \ud560\ub2f9\ud55c \ub3c4\uba54\uc778 \uac1d\uccb4\uac00 Low Coupling, High Cohesion, \uc7ac\uc0ac\uc6a9\uc131 \ub4f1\uc758 \ubaa9\uc801\uc744 \uc704\ubc18\ud55c\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub3c4\uba54\uc778 \uac1c\ub150\uc744 \ud3ec\ud568\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uace0 \ub9e4\uc6b0 \uc751\uc9d1\ub41c \ucc45\uc784\uc744 \ud560\ub2f9\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\ud589\ub3d9\uc744 \ucd94\uac00\ud560 \ub54c, \ud574\ub2f9 \ucc45\uc784\uc744 \uc218\ud589\ud560 \ub3c4\uba54\uc778 \uac1c\ub150\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \ub3c4\uba54\uc778\uacfc \ubb34\uad00\ud55c \uc778\uacf5\uc801\uc778 \uac1d\uccb4\ub97c \ub9cc\ub4e0\ub2e4\uc74c \ud574\ub2f9 \uac1d\uccb4\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uac1d\uccb4\uac00 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud574\uc57c \ud560 \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4\uace0, \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134\uc744 \uc801\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud558\ub77c\ub294 \ucc45\uc784\uc744 \uac00\uc9c0\ub77c\uace0 \ud558\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc608) \uc0c1\uc810\uacfc \uace0\uac1d \ud074\ub798\uc2a4\uac00 \uc788\uace0 \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uace0 \uac00\uc815"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 \uac70\ub798\ub97c \ud558\ub824\uba74 \ud658\uc804\uc744 \ud574\uc57c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub450 \ud074\ub798\uc2a4 \ub2e4 \ud658\uc804\uc5d0 \ub300\ud55c \ucc45\uc784\uc744 \ubd80\uc5ec\ud558\uae30 \uc560\ub9e4\ud558\ub2e4\uba74 \ud658\uc804\uc744 \ucc45\uc784\ud558\ub294 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud558\uace0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:["\uc624\ube0c\uc81d\ud2b8 5\uc7a5. \ucc45\uc784 \ud560\ub2f9\ud558\uae30, ",(0,i.jsx)(n.a,{href:"http://aeternum.egloos.com/",children:"\uc870\uc601\ud638"})]}),"\n",(0,i.jsx)(n.p,{children:"Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS8586826397",children:"GRASP, \ud55c\ube5b \ub124\ud2b8\uc6cc\ud06c"})})]})}function h(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var i=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function t(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var c=i.createContext({}),a=function(e){var n=i.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},h=i.forwardRef((function(e,n){var r=e.components,l=e.mdxType,t=e.originalType,c=e.parentName,h=o(e,["components","mdxType","originalType","parentName"]),p=a(r),j=l,x=p["".concat(c,".").concat(j)]||p[j]||d[j]||t;return r?i.createElement(x,s(s({ref:n},h),{},{components:r})):i.createElement(x,s({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/e9eabc5d.fcb4962f.js b/assets/js/e9eabc5d.60ab3c19.js similarity index 98% rename from assets/js/e9eabc5d.fcb4962f.js rename to assets/js/e9eabc5d.60ab3c19.js index 19e7882c1..3add0097a 100644 --- a/assets/js/e9eabc5d.fcb4962f.js +++ b/assets/js/e9eabc5d.60ab3c19.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1112],{40376:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>t,metadata:()=>o,toc:()=>a});var i=r(85893),l=r(3905);const t={title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",slug:"grasp",tags:["GRASP","OOP"]},s=void 0,o={permalink:"/grasp",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-30-GRASP.mdx",source:"@site/blog/2023-1/2023-03-30-GRASP.mdx",title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",description:"GRASP(General Responsibility Assignment Software Pattern)",date:"2023-03-30T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 30\uc77c",tags:[{label:"GRASP",permalink:"/tags/grasp"},{label:"OOP",permalink:"/tags/oop"}],readingTime:8.085,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",slug:"grasp",tags:["GRASP","OOP"]},unlisted:!1,prevItem:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",permalink:"/chess-retrospective"},nextItem:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",permalink:"/blackjack-retrospective"}},c={authorsImageUrls:[]},a=[{value:"GRASP(General Responsibility Assignment Software Pattern)",id:"graspgeneral-responsibility-assignment-software-pattern",level:3},{value:"\uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)",id:"\uc815\ubcf4-\uc804\ubb38\uac00-\ud328\ud134information-expert",level:3},{value:"\ucc3d\uc870\uc790 \ud328\ud134(Creator)",id:"\ucc3d\uc870\uc790-\ud328\ud134creator",level:3},{value:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)",id:"\ub0ae\uc740-\uacb0\ud569\ub3c4-\ud328\ud134low-coupling",level:3},{value:"\ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)",id:"\ub192\uc740-\uc751\uc9d1\ub3c4-\ud328\ud134high-cohesion",level:3},{value:"\ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)",id:"\ucee8\ud2b8\ub864\ub7ec-\ud328\ud134controller",level:3},{value:"\ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)",id:"\ub2e4\ud615\uc131-\ud328\ud134polymorphism",level:3},{value:"\ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)",id:"\ubcc0\uacbd-\ubcf4\ud638-\ud328\ud134protected-variations",level:3},{value:"\uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)",id:"\uac04\uc811-\ucc38\uc870-\ud328\ud134indirection",level:3},{value:"\uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)",id:"\uc21c\uc218\ud55c-\uac00\uacf5\ubb3c-\ud328\ud134pure-fabrication",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",blockquote:"blockquote",h3:"h3",li:"li",p:"p",ul:"ul",...(0,l.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"graspgeneral-responsibility-assignment-software-pattern",children:"GRASP(General Responsibility Assignment Software Pattern)"}),"\n",(0,i.jsx)(n.p,{children:"\ud06c\ub808\uc774\uadf8 \ub77c\ub9cc\uc758 Applying UML and Patterns\uc774\ub77c\ub294 \ucc45\uc5d0\uc11c \ub098\uc628 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134"}),"\n",(0,i.jsx)(n.p,{children:"\uac01 \ud328\ud134\ub9c8\ub2e4 Solution\uacfc Problem\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uc815\ubcf4-\uc804\ubb38\uac00-\ud328\ud134information-expert",children:"\uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \uac1d\uccb4\uc5d0 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uae30\ubcf8 \uc6d0\uce59\uc740 \ubb34\uc5c7\uc778\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A: \ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub370 \ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \ud074\ub798\uc2a4(\uc815\ubcf4 \uc804\ubb38\uac00)\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc815\ubcf4\uc640 \ud589\ub3d9\uc744 \uac00\uae4c\uc6b4 \uacf3\uc5d0 \uc704\uce58\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \ucea1\uc290\ud654\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \uac1d\uccb4\ub4e4\ub85c \ucc45\uc784\uc774 \ubd84\uc0b0\ub41c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ucc3d\uc870\uc790-\ud328\ud134creator",children:"\ucc3d\uc870\uc790 \ud328\ud134(Creator)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \ub204\uac00 \uac1d\uccb4 A\ub97c \uc0dd\uc131\ud558\ub294\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A: \ub2e4\uc74c\uc758 \uc870\uac74\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\uc871\ud558\ub294 \uac1d\uccb4\uc5d0\uac8c \uac1d\uccb4 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\uc758 \ucd08\uae30\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"\uc0dd\uc131 \uc608\uc815\uc778 \uac1d\uccb4\uc640 \uc5f0\uad00\ub418\uc5b4 \uc788\ub294 \uac1d\uccb4\uac00 \uc0dd\uc131 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac8c \ub41c\ub2e4\uba74, \uc774\ubbf8 \ud574\ub2f9 \uac1d\uccb4\uc640 \uacb0\ud569\ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\uac8c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ub0ae\uc740-\uacb0\ud569\ub3c4-\ud328\ud134low-coupling",children:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \uc758\uc874\uc131\uc744 \ub0ae\ucd94\uace0 \ubcc0\ud654\uc758 \uc601\ud5a5\uc744 \uc904\uc774\uba70 \uc7ac\uc0ac\uc6a9\uc131\uc744 \uc99d\uac00\uc2dc\ud0a4\ub294 \ubc29\ubc95\uc740?"}),"\n",(0,i.jsx)(n.p,{children:"A: \uc804\uccb4\uc801\uc778 \uacb0\ud569\uc774 \ub0ae\uac8c \uc720\uc9c0\ub418\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"\uacb0\ud569\ub3c4(Coupling)\n\uac1d\uccb4 \uc0ac\uc774\uc758 \uc758\uc874\uc131\uc774 \uacfc\ud55c \uacbd\uc6b0 \uacb0\ud569\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc624\ube0c\uc81d\ud2b8 p.17"}),"\n"]}),"\n",(0,i.jsx)(n.blockquote,{children:"\n"}),"\n",(0,i.jsx)(n.p,{children:"\uacb0\ud569\ub3c4\ub97c \ub0ae\ucd98\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\ub2e4\ub978 \uad6c\uc131 \uc694\uc18c\uc758 \ubcc0\ud654\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc7ac\uc0ac\uc6a9\uc774 \ud3b8\ub9ac\ud574\uc9c4\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\uc758\uc874\ud558\ub294 \ud074\ub798\uc2a4\uac00 \uc801\uae30 \ub54c\ubb38\uc5d0)"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ub192\uc740-\uc751\uc9d1\ub3c4-\ud328\ud134high-cohesion",children:"\ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uac1d\uccb4\ub97c \uad00\ub9ac\ud558\uae30 \uc27d\uac8c \ud558\ub824\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub192\uc740 \uc751\uc9d1\ub3c4\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"\uc751\uc9d1\ub3c4(Cohesion)\n\uc5f0\uad00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc5f0\uad00\uc131 \uc5c6\ub294 \uc791\uc5c5\uc740 \ub2e4\ub978 \uac1d\uccb4\uc5d0\uac8c \uc704\uc784\ud558\ub294 \uac1d\uccb4\ub97c \uac00\ub9ac\ucf1c \uc751\uc9d1\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc624\ube0c\uc81d\ud2b8 p.26"}),"\n"]}),"\n",(0,i.jsx)(n.blockquote,{children:"\n"}),"\n",(0,i.jsx)(n.p,{children:"\ubcc0\uacbd\uc758 \uc774\uc720\uc5d0 \ub530\ub77c \ud074\ub798\uc2a4\ub97c \ubd84\ub9ac\ud55c\ub2e4\uba74 \uc751\uc9d1\ub3c4\ub97c \ub192\uc77c \uc218 \uc788\uace0, \uc751\uc9d1\ub3c4\uac00 \ub192\uc544\uc9c4\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\ud560\ub2f9\ub41c \ucc45\uc784\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0)"}),"\n",(0,i.jsx)(n.li,{children:"\uc720\uc9c0\ubcf4\uc218\uac00 \uc26c\uc6cc\uc9c4\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ub610\ud55c \uc9c0\uc6d0\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc751\uc9d1\ub3c4\uac00 \ub192\uc740 \ud074\ub798\uc2a4\ub294 \ud2b9\uc815\ud55c \ubaa9\uc801\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc7ac\uc0ac\uc6a9\ud558\uae30 \uc88b\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucee8\ud2b8\ub864\ub7ec-\ud328\ud134controller",children:"\ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uac83\uc740 \ub204\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 Controller \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc5b4\ub5a4 \uc11c\ube0c\uc2dc\uc2a4\ud15c\uc774 \uc874\uc7ac\ud55c\ub2e4\uace0 \uac00\uc815\ud560 \ub54c"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc9c1\uc811\uc801\uc73c\ub85c \uac1d\uccb4\uc5d0 \uc811\uadfc\ud558\uc5ec \ud504\ub85c\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uacb0\ud569\ub3c4\uac00 \uc0c1\uc2b9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc11c\ube0c \uc2dc\uc2a4\ud15c\uc5d0 \ub4e4\uc5b4\uc624\ub294 \uc694\uccad\uc744 \ucc98\ub9ac\ud574\uc8fc\ub294 \ucee8\ud2b8\ub864\ub7ec\uac00 \uc788\ub2e4\uba74 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 \ud574\ub2f9 \ucee8\ud2b8\ub864\ub7ec\ub9cc \uc54c\uba74 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub9cc\uc57d \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc758 \ubcc0\uacbd\uc774 \uc0dd\uacbc\uc744 \ub54c \uc678\ubd80\uc5d0 \ubbf8\uce58\ub294 \uc601\ud5a5\ub3c4 \uc904\uc5b4\ub4e0\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ub2e4\ud615\uc131-\ud328\ud134polymorphism",children:"\ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uac1d\uccb4\uc758 \ud0c0\uc785\uc5d0 \ub530\ub77c \ud589\ub3d9\uc774 \ubc14\ub010\ub2e4\uba74 \ucc45\uc784\uc744 \uc5b4\ub5bb\uac8c \ud560\ub2f9\ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. OOP\uac00 \uc9c0\uc6d0\ud558\ub294 \ub2e4\ud615\uc131\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ud65c\uc6a9\ud55c\ub2e4. (\uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0 \ud589\ub3d9\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uad6c\ud604)"}),"\n",(0,i.jsx)(n.p,{children:"\uac1d\uccb4\uc758 \uc885\ub958\uc5d0 \ub530\ub77c \ubd84\uae30\ud558\ub294 \uc870\uac74\ubb38\uc774 \uc544\ub2cc \ub2e4\ud615\uc131\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc0c8\ub85c\uc6b4 \ud0c0\uc785\uc774 \ucd94\uac00\ub418\uc5c8\uc744 \ub54c \uc870\uac74\ubb38\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uae30\uc874\uc758 \uc870\uac74\ubb38\uc744 \uc218\uc815\ud574\uc57c \ud558\uc9c0\ub9cc \ub2e4\ud615\uc131\uc744 \ud65c\uc6a9\ud558\uba74 \uc27d\uac8c \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ubcc0\uacbd-\ubcf4\ud638-\ud328\ud134protected-variations",children:"\ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uc5b4\ub5bb\uac8c \ud558\uba74 \ubcc0\uacbd\uc774 \ub2e4\ub978 \uc694\uc18c\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud560 \uc218 \uc788\uc744\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ubcc0\ud654\uac00 \uc608\uc0c1\ub418\ub294 \uc9c0\uc810\uc744 \uc2dd\ubcc4\ud558\uace0, \uc8fc\uc704\uc5d0 \uc548\uc815\ub41c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud615\uc131\ud558\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uac04\uc811-\ucc38\uc870-\ud328\ud134indirection",children:"\uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud558\uace0 \uc2f6\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ub2e4\ub978 \uac1d\uccb4\ub97c \ub450\uc5b4 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uc7ac\uc790 \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ud558\ub098\uc758 \uac1d\uccb4\ub97c \ucd94\uac00\ud558\uc5ec \ubcf5\uc7a1\ud55c \uad00\uacc4\ub97c \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uac04\uc5d0 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub454\ub2e4\uba74 \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\uc5d0 \ud574\ub2f9\ub41c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uc21c\uc218\ud55c-\uac00\uacf5\ubb3c-\ud328\ud134pure-fabrication",children:"\uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \ucc45\uc784\uc744 \ud560\ub2f9\ud55c \ub3c4\uba54\uc778 \uac1d\uccb4\uac00 Low Coupling, High Cohesion, \uc7ac\uc0ac\uc6a9\uc131 \ub4f1\uc758 \ubaa9\uc801\uc744 \uc704\ubc18\ud55c\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub3c4\uba54\uc778 \uac1c\ub150\uc744 \ud3ec\ud568\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uace0 \ub9e4\uc6b0 \uc751\uc9d1\ub41c \ucc45\uc784\uc744 \ud560\ub2f9\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\ud589\ub3d9\uc744 \ucd94\uac00\ud560 \ub54c, \ud574\ub2f9 \ucc45\uc784\uc744 \uc218\ud589\ud560 \ub3c4\uba54\uc778 \uac1c\ub150\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \ub3c4\uba54\uc778\uacfc \ubb34\uad00\ud55c \uc778\uacf5\uc801\uc778 \uac1d\uccb4\ub97c \ub9cc\ub4e0\ub2e4\uc74c \ud574\ub2f9 \uac1d\uccb4\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uac1d\uccb4\uac00 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud574\uc57c \ud560 \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4\uace0, \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134\uc744 \uc801\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud558\ub77c\ub294 \ucc45\uc784\uc744 \uac00\uc9c0\ub77c\uace0 \ud558\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc608) \uc0c1\uc810\uacfc \uace0\uac1d \ud074\ub798\uc2a4\uac00 \uc788\uace0 \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uace0 \uac00\uc815"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 \uac70\ub798\ub97c \ud558\ub824\uba74 \ud658\uc804\uc744 \ud574\uc57c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub450 \ud074\ub798\uc2a4 \ub2e4 \ud658\uc804\uc5d0 \ub300\ud55c \ucc45\uc784\uc744 \ubd80\uc5ec\ud558\uae30 \uc560\ub9e4\ud558\ub2e4\uba74 \ud658\uc804\uc744 \ucc45\uc784\ud558\ub294 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud558\uace0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:["\uc624\ube0c\uc81d\ud2b8 5\uc7a5. \ucc45\uc784 \ud560\ub2f9\ud558\uae30, ",(0,i.jsx)(n.a,{href:"http://aeternum.egloos.com/",children:"\uc870\uc601\ud638"})]}),"\n",(0,i.jsx)(n.p,{children:"Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS8586826397",children:"GRASP, \ud55c\ube5b \ub124\ud2b8\uc6cc\ud06c"})})]})}function h(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var i=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function t(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var c=i.createContext({}),a=function(e){var n=i.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},h=i.forwardRef((function(e,n){var r=e.components,l=e.mdxType,t=e.originalType,c=e.parentName,h=o(e,["components","mdxType","originalType","parentName"]),p=a(r),j=l,x=p["".concat(c,".").concat(j)]||p[j]||d[j]||t;return r?i.createElement(x,s(s({ref:n},h),{},{components:r})):i.createElement(x,s({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1112],{40376:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>t,metadata:()=>o,toc:()=>a});var i=r(85893),l=r(3905);const t={title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",slug:"grasp",tags:["GRASP","OOP"]},s=void 0,o={permalink:"/grasp",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-30-GRASP.mdx",source:"@site/blog/2023-1/2023-03-30-GRASP.mdx",title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",description:"GRASP(General Responsibility Assignment Software Pattern)",date:"2023-03-30T00:00:00.000Z",formattedDate:"2023\ub144 3\uc6d4 30\uc77c",tags:[{label:"GRASP",permalink:"/tags/grasp"},{label:"OOP",permalink:"/tags/oop"}],readingTime:8.085,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134",slug:"grasp",tags:["GRASP","OOP"]},unlisted:!1,prevItem:{title:"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0",permalink:"/blackjack-retrospective"},nextItem:{title:"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0",permalink:"/chess-retrospective"}},c={authorsImageUrls:[]},a=[{value:"GRASP(General Responsibility Assignment Software Pattern)",id:"graspgeneral-responsibility-assignment-software-pattern",level:3},{value:"\uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)",id:"\uc815\ubcf4-\uc804\ubb38\uac00-\ud328\ud134information-expert",level:3},{value:"\ucc3d\uc870\uc790 \ud328\ud134(Creator)",id:"\ucc3d\uc870\uc790-\ud328\ud134creator",level:3},{value:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)",id:"\ub0ae\uc740-\uacb0\ud569\ub3c4-\ud328\ud134low-coupling",level:3},{value:"\ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)",id:"\ub192\uc740-\uc751\uc9d1\ub3c4-\ud328\ud134high-cohesion",level:3},{value:"\ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)",id:"\ucee8\ud2b8\ub864\ub7ec-\ud328\ud134controller",level:3},{value:"\ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)",id:"\ub2e4\ud615\uc131-\ud328\ud134polymorphism",level:3},{value:"\ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)",id:"\ubcc0\uacbd-\ubcf4\ud638-\ud328\ud134protected-variations",level:3},{value:"\uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)",id:"\uac04\uc811-\ucc38\uc870-\ud328\ud134indirection",level:3},{value:"\uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)",id:"\uc21c\uc218\ud55c-\uac00\uacf5\ubb3c-\ud328\ud134pure-fabrication",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function d(e){const n={a:"a",blockquote:"blockquote",h3:"h3",li:"li",p:"p",ul:"ul",...(0,l.ah)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h3,{id:"graspgeneral-responsibility-assignment-software-pattern",children:"GRASP(General Responsibility Assignment Software Pattern)"}),"\n",(0,i.jsx)(n.p,{children:"\ud06c\ub808\uc774\uadf8 \ub77c\ub9cc\uc758 Applying UML and Patterns\uc774\ub77c\ub294 \ucc45\uc5d0\uc11c \ub098\uc628 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134"}),"\n",(0,i.jsx)(n.p,{children:"\uac01 \ud328\ud134\ub9c8\ub2e4 Solution\uacfc Problem\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uc815\ubcf4-\uc804\ubb38\uac00-\ud328\ud134information-expert",children:"\uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \uac1d\uccb4\uc5d0 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uae30\ubcf8 \uc6d0\uce59\uc740 \ubb34\uc5c7\uc778\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A: \ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub370 \ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \ud074\ub798\uc2a4(\uc815\ubcf4 \uc804\ubb38\uac00)\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc815\ubcf4\uc640 \ud589\ub3d9\uc744 \uac00\uae4c\uc6b4 \uacf3\uc5d0 \uc704\uce58\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \ucea1\uc290\ud654\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \uac1d\uccb4\ub4e4\ub85c \ucc45\uc784\uc774 \ubd84\uc0b0\ub41c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ucc3d\uc870\uc790-\ud328\ud134creator",children:"\ucc3d\uc870\uc790 \ud328\ud134(Creator)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \ub204\uac00 \uac1d\uccb4 A\ub97c \uc0dd\uc131\ud558\ub294\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A: \ub2e4\uc74c\uc758 \uc870\uac74\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\uc871\ud558\ub294 \uac1d\uccb4\uc5d0\uac8c \uac1d\uccb4 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"B\uac00 A \uac1d\uccb4\uc758 \ucd08\uae30\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"\uc0dd\uc131 \uc608\uc815\uc778 \uac1d\uccb4\uc640 \uc5f0\uad00\ub418\uc5b4 \uc788\ub294 \uac1d\uccb4\uac00 \uc0dd\uc131 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac8c \ub41c\ub2e4\uba74, \uc774\ubbf8 \ud574\ub2f9 \uac1d\uccb4\uc640 \uacb0\ud569\ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\uac8c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ub0ae\uc740-\uacb0\ud569\ub3c4-\ud328\ud134low-coupling",children:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)"}),"\n",(0,i.jsx)(n.p,{children:"Q: \uc758\uc874\uc131\uc744 \ub0ae\ucd94\uace0 \ubcc0\ud654\uc758 \uc601\ud5a5\uc744 \uc904\uc774\uba70 \uc7ac\uc0ac\uc6a9\uc131\uc744 \uc99d\uac00\uc2dc\ud0a4\ub294 \ubc29\ubc95\uc740?"}),"\n",(0,i.jsx)(n.p,{children:"A: \uc804\uccb4\uc801\uc778 \uacb0\ud569\uc774 \ub0ae\uac8c \uc720\uc9c0\ub418\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"\uacb0\ud569\ub3c4(Coupling)\n\uac1d\uccb4 \uc0ac\uc774\uc758 \uc758\uc874\uc131\uc774 \uacfc\ud55c \uacbd\uc6b0 \uacb0\ud569\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc624\ube0c\uc81d\ud2b8 p.17"}),"\n"]}),"\n",(0,i.jsx)(n.blockquote,{children:"\n"}),"\n",(0,i.jsx)(n.p,{children:"\uacb0\ud569\ub3c4\ub97c \ub0ae\ucd98\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\ub2e4\ub978 \uad6c\uc131 \uc694\uc18c\uc758 \ubcc0\ud654\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc7ac\uc0ac\uc6a9\uc774 \ud3b8\ub9ac\ud574\uc9c4\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\uc758\uc874\ud558\ub294 \ud074\ub798\uc2a4\uac00 \uc801\uae30 \ub54c\ubb38\uc5d0)"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ub192\uc740-\uc751\uc9d1\ub3c4-\ud328\ud134high-cohesion",children:"\ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uac1d\uccb4\ub97c \uad00\ub9ac\ud558\uae30 \uc27d\uac8c \ud558\ub824\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub192\uc740 \uc751\uc9d1\ub3c4\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"\uc751\uc9d1\ub3c4(Cohesion)\n\uc5f0\uad00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc5f0\uad00\uc131 \uc5c6\ub294 \uc791\uc5c5\uc740 \ub2e4\ub978 \uac1d\uccb4\uc5d0\uac8c \uc704\uc784\ud558\ub294 \uac1d\uccb4\ub97c \uac00\ub9ac\ucf1c \uc751\uc9d1\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4."}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc624\ube0c\uc81d\ud2b8 p.26"}),"\n"]}),"\n",(0,i.jsx)(n.blockquote,{children:"\n"}),"\n",(0,i.jsx)(n.p,{children:"\ubcc0\uacbd\uc758 \uc774\uc720\uc5d0 \ub530\ub77c \ud074\ub798\uc2a4\ub97c \ubd84\ub9ac\ud55c\ub2e4\uba74 \uc751\uc9d1\ub3c4\ub97c \ub192\uc77c \uc218 \uc788\uace0, \uc751\uc9d1\ub3c4\uac00 \ub192\uc544\uc9c4\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\ud560\ub2f9\ub41c \ucc45\uc784\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0)"}),"\n",(0,i.jsx)(n.li,{children:"\uc720\uc9c0\ubcf4\uc218\uac00 \uc26c\uc6cc\uc9c4\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub0ae\uc740 \uacb0\ud569\ub3c4 \ub610\ud55c \uc9c0\uc6d0\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc751\uc9d1\ub3c4\uac00 \ub192\uc740 \ud074\ub798\uc2a4\ub294 \ud2b9\uc815\ud55c \ubaa9\uc801\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc7ac\uc0ac\uc6a9\ud558\uae30 \uc88b\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucee8\ud2b8\ub864\ub7ec-\ud328\ud134controller",children:"\ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uac83\uc740 \ub204\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294\uac00?"}),"\n",(0,i.jsx)(n.p,{children:"A. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 Controller \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc5b4\ub5a4 \uc11c\ube0c\uc2dc\uc2a4\ud15c\uc774 \uc874\uc7ac\ud55c\ub2e4\uace0 \uac00\uc815\ud560 \ub54c"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc9c1\uc811\uc801\uc73c\ub85c \uac1d\uccb4\uc5d0 \uc811\uadfc\ud558\uc5ec \ud504\ub85c\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uacb0\ud569\ub3c4\uac00 \uc0c1\uc2b9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\uc11c\ube0c \uc2dc\uc2a4\ud15c\uc5d0 \ub4e4\uc5b4\uc624\ub294 \uc694\uccad\uc744 \ucc98\ub9ac\ud574\uc8fc\ub294 \ucee8\ud2b8\ub864\ub7ec\uac00 \uc788\ub2e4\uba74 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 \ud574\ub2f9 \ucee8\ud2b8\ub864\ub7ec\ub9cc \uc54c\uba74 \ub41c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub9cc\uc57d \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc758 \ubcc0\uacbd\uc774 \uc0dd\uacbc\uc744 \ub54c \uc678\ubd80\uc5d0 \ubbf8\uce58\ub294 \uc601\ud5a5\ub3c4 \uc904\uc5b4\ub4e0\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ub2e4\ud615\uc131-\ud328\ud134polymorphism",children:"\ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uac1d\uccb4\uc758 \ud0c0\uc785\uc5d0 \ub530\ub77c \ud589\ub3d9\uc774 \ubc14\ub010\ub2e4\uba74 \ucc45\uc784\uc744 \uc5b4\ub5bb\uac8c \ud560\ub2f9\ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. OOP\uac00 \uc9c0\uc6d0\ud558\ub294 \ub2e4\ud615\uc131\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ud65c\uc6a9\ud55c\ub2e4. (\uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0 \ud589\ub3d9\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uad6c\ud604)"}),"\n",(0,i.jsx)(n.p,{children:"\uac1d\uccb4\uc758 \uc885\ub958\uc5d0 \ub530\ub77c \ubd84\uae30\ud558\ub294 \uc870\uac74\ubb38\uc774 \uc544\ub2cc \ub2e4\ud615\uc131\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc0c8\ub85c\uc6b4 \ud0c0\uc785\uc774 \ucd94\uac00\ub418\uc5c8\uc744 \ub54c \uc870\uac74\ubb38\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uae30\uc874\uc758 \uc870\uac74\ubb38\uc744 \uc218\uc815\ud574\uc57c \ud558\uc9c0\ub9cc \ub2e4\ud615\uc131\uc744 \ud65c\uc6a9\ud558\uba74 \uc27d\uac8c \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\ubcc0\uacbd-\ubcf4\ud638-\ud328\ud134protected-variations",children:"\ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \uc5b4\ub5bb\uac8c \ud558\uba74 \ubcc0\uacbd\uc774 \ub2e4\ub978 \uc694\uc18c\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud560 \uc218 \uc788\uc744\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ubcc0\ud654\uac00 \uc608\uc0c1\ub418\ub294 \uc9c0\uc810\uc744 \uc2dd\ubcc4\ud558\uace0, \uc8fc\uc704\uc5d0 \uc548\uc815\ub41c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud615\uc131\ud558\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uac04\uc811-\ucc38\uc870-\ud328\ud134indirection",children:"\uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud558\uace0 \uc2f6\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ub2e4\ub978 \uac1d\uccb4\ub97c \ub450\uc5b4 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uc7ac\uc790 \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ud558\ub098\uc758 \uac1d\uccb4\ub97c \ucd94\uac00\ud558\uc5ec \ubcf5\uc7a1\ud55c \uad00\uacc4\ub97c \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc911\uac04\uc5d0 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub454\ub2e4\uba74 \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\uc5d0 \ud574\ub2f9\ub41c\ub2e4."}),"\n",(0,i.jsx)(n.h3,{id:"\uc21c\uc218\ud55c-\uac00\uacf5\ubb3c-\ud328\ud134pure-fabrication",children:"\uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)"}),"\n",(0,i.jsx)(n.p,{children:"Q. \ucc45\uc784\uc744 \ud560\ub2f9\ud55c \ub3c4\uba54\uc778 \uac1d\uccb4\uac00 Low Coupling, High Cohesion, \uc7ac\uc0ac\uc6a9\uc131 \ub4f1\uc758 \ubaa9\uc801\uc744 \uc704\ubc18\ud55c\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?"}),"\n",(0,i.jsx)(n.p,{children:"A. \ub3c4\uba54\uc778 \uac1c\ub150\uc744 \ud3ec\ud568\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uace0 \ub9e4\uc6b0 \uc751\uc9d1\ub41c \ucc45\uc784\uc744 \ud560\ub2f9\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\ud589\ub3d9\uc744 \ucd94\uac00\ud560 \ub54c, \ud574\ub2f9 \ucc45\uc784\uc744 \uc218\ud589\ud560 \ub3c4\uba54\uc778 \uac1c\ub150\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \ub3c4\uba54\uc778\uacfc \ubb34\uad00\ud55c \uc778\uacf5\uc801\uc778 \uac1d\uccb4\ub97c \ub9cc\ub4e0\ub2e4\uc74c \ud574\ub2f9 \uac1d\uccb4\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uac1d\uccb4\uac00 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud574\uc57c \ud560 \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4\uace0, \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134\uc744 \uc801\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud558\ub77c\ub294 \ucc45\uc784\uc744 \uac00\uc9c0\ub77c\uace0 \ud558\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,i.jsx)(n.p,{children:"\uc608) \uc0c1\uc810\uacfc \uace0\uac1d \ud074\ub798\uc2a4\uac00 \uc788\uace0 \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uace0 \uac00\uc815"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 \uac70\ub798\ub97c \ud558\ub824\uba74 \ud658\uc804\uc744 \ud574\uc57c\ud55c\ub2e4."}),"\n",(0,i.jsx)(n.li,{children:"\ub450 \ud074\ub798\uc2a4 \ub2e4 \ud658\uc804\uc5d0 \ub300\ud55c \ucc45\uc784\uc744 \ubd80\uc5ec\ud558\uae30 \uc560\ub9e4\ud558\ub2e4\uba74 \ud658\uc804\uc744 \ucc45\uc784\ud558\ub294 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud558\uace0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,i.jsxs)(n.p,{children:["\uc624\ube0c\uc81d\ud2b8 5\uc7a5. \ucc45\uc784 \ud560\ub2f9\ud558\uae30, ",(0,i.jsx)(n.a,{href:"http://aeternum.egloos.com/",children:"\uc870\uc601\ud638"})]}),"\n",(0,i.jsx)(n.p,{children:"Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS8586826397",children:"GRASP, \ud55c\ube5b \ub124\ud2b8\uc6cc\ud06c"})})]})}function h(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var i=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function t(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var c=i.createContext({}),a=function(e){var n=i.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},h=i.forwardRef((function(e,n){var r=e.components,l=e.mdxType,t=e.originalType,c=e.parentName,h=o(e,["components","mdxType","originalType","parentName"]),p=a(r),j=l,x=p["".concat(c,".").concat(j)]||p[j]||d[j]||t;return r?i.createElement(x,s(s({ref:n},h),{},{components:r})):i.createElement(x,s({ref:n},h))}));h.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/eff1d58f.886bd191.js b/assets/js/eff1d58f.9a2d582c.js similarity index 98% rename from assets/js/eff1d58f.886bd191.js rename to assets/js/eff1d58f.9a2d582c.js index 9f1ed2af9..587745799 100644 --- a/assets/js/eff1d58f.886bd191.js +++ b/assets/js/eff1d58f.9a2d582c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4137],{68801:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=t(85893),c=t(3905);const a={title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",slug:"tecochat-retrospective-1",tags:["TecoChat","Retrospective"]},s=void 0,i={permalink:"/tecochat-retrospective-1",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",source:"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",description:"4\uc6d4 21\uc77c \uae08\uc694\uc77c",date:"2023-04-22T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 22\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.68,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",slug:"tecochat-retrospective-1",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"Jenkins\ub85c CI/CD \uc124\uc815",permalink:"/jenkins"},nextItem:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",permalink:"/book-leadership-and-self-deception"}},o={authorsImageUrls:[]},l=[{value:"4\uc6d4 21\uc77c \uae08\uc694\uc77c",id:"4\uc6d4-21\uc77c-\uae08\uc694\uc77c",level:3},{value:"\ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?",id:"\ub3c4\uba54\uc778-\uad6c\uc785-\uc131\uacf5",level:3},{value:"\ub9d0\ub791\uc758 DM",id:"\ub9d0\ub791\uc758-dm",level:3},{value:"\ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec",id:"\ub3c4\uba54\uc778-\uc124\uc815-\ubc0f-\ubc30\ud3ec",level:3},{value:"GPT",id:"gpt",level:3},{value:"Sonarcloud",id:"sonarcloud",level:3},{value:"Tiptap",id:"tiptap",level:3},{value:"\ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9",id:"\ud3f0\ud2b8-\ubc0f-favicon-\uc801\uc6a9",level:3}];function p(e){const n={br:"br",code:"code",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"4\uc6d4-21\uc77c-\uae08\uc694\uc77c",children:"4\uc6d4 21\uc77c \uae08\uc694\uc77c"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ubca8 2\ub97c \uc2dc\uc791\ud55c \ub4a4 \ub0b4\uac00 \ud559\uc2b5\uc5d0 \ub300\ud55c \ubc29\ud5a5\uc744 \uc783\uc5b4\ubc84\ub838\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub808\ubca8 3, 4\uc5d0\uc11c \ub098\ub9cc\uc758 \uac15\uc810\uc744 \uac00\uc9c0\uace0 \uc2f6\uc5b4 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e8\uc21c\ud788 \uc2a4\ud504\ub9c1\uc744 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ud6a8\uc728\uc774 \ub9ce\uc774 \ub5a8\uc5b4\uc9c4\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae00\uc4f0\uae30 \uc218\uc0c1\uc73c\ub85c \ubc1b\uc740 \ucfe0\ud3f0\uc744 \uc0ac\uc6a9\ud574 \ube0c\ub77c\uc6b4\uc5d0\uac8c \ucee4\ud53c\ucc57\uc744 \uc2e0\uccad\ud588\uace0, \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud574\ubcf4\ub77c\ub294 \ub2f5\uc744 \ubc1b\uc558\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub098\ub294 \uc544\uc774\ub514\uc5b4\ub97c \ubabb\ub0b4\ub294 \ud3b8\uc778\ub370 \ube0c\ub77c\uc6b4\uc774 \uc544\uc774\ub514\uc5b4\uae4c\uc9c0 \ub358\uc838\uc8fc\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"Chat-GPT \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uace0, \ud574\ub2f9 \ud06c\ub8e8\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc744 \uacf5\uc720\ud560 \uc218 \uc788\ub294 \uac74 \uc5b4\ub5a4\uc9c0?"})]}),"\n",(0,r.jsxs)(n.p,{children:["\uae30\uc220\uc774 \ubaa9\uc801\uc778 \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4\ub294 \ub2f5\ubcc0\uc744 \ub4e4\uc5c8\uace0, \ud63c\uc790 \uc544\ub2c8\uba74 \ud398\uc5b4\ud560 \uc218 \uc788\uc744 \uc815\ub3c4\uc758 \uc778\uc6d0\uc73c\ub85c \uc9c4\ud589\ud558\uba74 \uc88b\uaca0\ub2e4\uace0 \ud558\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud504\ub860\ud2b8\ub791 \uac04\ub2e8\ud558\uac8c \ubc30\ud3ec\uae4c\uc9c0 \ud574\ubcf8 \uacbd\ud5d8\uc774 \uc788\uc5b4\uc11c \ud63c\uc790\ud574\ub3c4 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc744 \uac83 \uac19\uc544\uc11c \ud63c\uc790 \ud558\uae30\ub85c \ub9c8\uc74c\uc744 \uba39\uc5c8\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uac74 \ubabb\ucc38\uc9c0"}),"\n",(0,r.jsx)(n.h3,{id:"\ub3c4\uba54\uc778-\uad6c\uc785-\uc131\uacf5",children:"\ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?"}),"\n",(0,r.jsxs)(n.p,{children:["\ucee4\ud53c\ucc57\uc774 \ub05d\ub098\uace0 \uc9d1\uc73c\ub85c \ub3cc\uc544\uac00\ub294 \uae38\uc5d0 \ubc14\ub85c \ub3c4\uba54\uc778\uc744 \uad6c\ub9e4\ud558\ub824\uace0 namecheap\uc5d0\uc11c \uc801\ub2f9\ud55c \ub3c4\uba54\uc778\uc774 \uc5c6\uc744\uae4c \uac80\uc0c9\uc744 \uacc4\uc18d\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9c8\uce58 \uc5b4\ub9b4 \ub54c \ud588\ub358 \uac8c\uc784 \ub2c9\ub124\uc784 \uc815\ud558\ub294 \uac83\ucc98\ub7fc \uc2dc\uac04\uc774 \uc624\ub798 \uac78\ub838\ub2e4.",(0,r.jsx)(n.br,{}),"\n","dev, io, chat \ub3c4\uba54\uc778\uc774 \ud6c4\ubcf4\uc600\uace0 \uc9d1 \uac00\ub294 \uae38\uc5d0 \uacb0\uc815\ub9cc \ud558\ub2e4\uac00 \uad6c\ub9e4\ud558\uc9c0 \ubabb\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ub9d0\ub791\uc758-dm",children:"\ub9d0\ub791\uc758 DM"}),"\n",(0,r.jsxs)(n.p,{children:["\uc9d1\uc5d0 \uac00\uc11c \ubc25\uc744 \uba39\uace0 \ub9d0\ub791\uc774\ub791 DM \ud558\ub2e4 \ud504\ub85c\uc81d\ud2b8\ub97c \uac19\uc774 \ud558\uc790\ub294 \uc774\uc57c\uae30\uac00 \ub098\uc654\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6b0\ud14c\ucf54 \ucd5c\uace0 \uace0\uc218 \ub9d0\ub791\uc758 \uc694\uad6c\ub77c \uc218\ub77d\ud558\uc9c0 \uc54a\uc73c\uba74 \ud6c4\ud3ed\ud48d\uc744 \uac10\ub2f9\ud560 \uc218 \uc5c6\uc5c8\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ub7f0\uc800\ub7f0 \ub300\ud654\ub97c \ub098\ub204\ub2e4\uac00 \ub09c \ube60\ub974\uac8c \ud504\ub85c\ud1a0\ud0c0\uc785\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uace0 \uc2f6\uc5b4\uc11c \ud504\ub860\ud2b8\ub97c \uad6c\ud604\ud55c\ub2e4\uace0 \ud588\uace0, \ub9d0\ub791\uc740 GPT api\ub97c \uc870\uc0ac\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ub3c4\uba54\uc778\uc5d0 \uad00\ud55c \uc774\uc57c\uae30\ub97c \ud558\ub2e4\uac00 woowachat\uc774 \uc5b8\uae09\ub418\uc5c8\uace0, namecheap\uc5d0\uc11c chat \ub3c4\uba54\uc778\uc744 \uc0ac\uc6a9\ud55c woowa.chat\uc73c\ub85c \uad6c\ub9e4\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ud6c4\uc5d0 teco.chat\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4!"]}),"\n",(0,r.jsx)(n.h3,{id:"\ub3c4\uba54\uc778-\uc124\uc815-\ubc0f-\ubc30\ud3ec",children:"\ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec"}),"\n",(0,r.jsxs)(n.p,{children:["\ud1a0\uc694\uc77c\uc5d0 \uad6c\ub9e4\ud55c \ub3c4\uba54\uc778\uc744 CDN, \ubcf4\uc548 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 Cloudflare\uc5d0 \ub3c4\uba54\uc778 \ub4f1\ub85d\uc744 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc5d0\uac8c \uc775\uc219\ud55c Nuxt3\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\uace0, Cloudflare Pages\ub97c \uc774\uc6a9\ud558\uc5ec \ubc30\ud3ec\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"gpt",children:"GPT"}),"\n",(0,r.jsxs)(n.p,{children:["\ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud558\ub2c8 api limit\uc774 \uc788\uc5b4 \ubd84\ub2f9 3\ubc88\ubc16\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc77c\ub2e8 \ubc31\uc5d4\ub4dc\ub97c \uad6c\ucd95\ud558\uae30 \uc804\uc5d0\ub294 \ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud560 \uc0dd\uac01\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"sonarcloud",children:"Sonarcloud"}),"\n",(0,r.jsxs)(n.p,{children:["\uc815\uc801 \ucf54\ub4dc \ubd84\uc11d \ub3c4\uad6c\ub85c Sonarcloud\ub97c \uc801\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Sonarcloud\ub294 SonarQube\uc758 SaaS \ubc84\uc804\uc774\uace0 \uc0ac\uc6a9\uc774 \ub9e4\uc6b0 \ud3b8\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608\uc804\uc5d0 Sonarcloud\ub97c \uc0ac\uc6a9\ud560 \ub550 \ubc84\ud2bc \uba87 \ubc88 \ub204\ub974\uba74 \uc801\uc6a9\ud560 \uc218 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \ubc14\ub85c github action\uc744 \uc0ac\uc6a9\ud558\ub77c\ub294 \uc548\ub0b4 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Sonarcloud\uac00 \uc790\uccb4\uc801\uc73c\ub85c github repository\uc5d0 push \ud558\uba74 \uc815\uc801 \ubd84\uc11d\uc744 \ud574\uc8fc\ub294 \uae30\ub2a5\uc744 \uc6d0\ud588\uace0, Administration -> Analysis Method\uc5d0 Automatic Analysis\ub97c \uc124\uc815\ud558\ub2c8 \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub108\ubb34 \uaf41\uaf41 \uc228\uaca8\uc838\uc788\ub124"]}),"\n",(0,r.jsx)(n.h3,{id:"tiptap",children:"Tiptap"}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ub4dc \ud558\uc774\ub77c\uc774\ud305 \uae30\ub2a5\uc744 \ub123\uace0 \uc2f6\uc5b4\uc11c Tiptap\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Tiptap\uc740 Headless WYSIWYG \uc5d0\ub514\ud130\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uae30\ub2a5\uc5d0 \ud2b9\ud654\ub418\uc5b4\uc788\ub294 \uc5d0\ub514\ud130\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\uc9c1 Tiptap\uc774 \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uae30\ub2a5\uc744 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc0ac\uc6a9\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc CodeBlockLowlight \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucf54\ub4dc \ube14\ub85d\uc744 \uc608\uc058\uac8c \ucd9c\ub825\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","api \ubc18\ud658\uac12 \uadf8\ub300\ub85c tiptap\uc758 content\uc5d0 \uc124\uc815\ud588\ub354\ub2c8 \ucf54\ub4dc \ube14\ub85d\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc544\uc11c \ubc31 \ud2f1 3\uac1c\ub97c ",(0,r.jsx)(n.code,{children:"
"}),"\ub85c \ubcc0\ud658\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ub744\uc5b4\uc4f0\uae30\ub3c4 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc544\uc11c ",(0,r.jsx)(n.code,{children:"\\n"}),"\ub97c ",(0,r.jsx)(n.code,{children:"
"}),"\ud0dc\uadf8\ub85c \ubcc0\ud658\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubcc0\ud658\ud558\ub294 \ub85c\uc9c1\uc740 GPT\uc758 \ub3c4\uc6c0\uc744 \ub9ce\uc774 \ubc1b\uc558\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:'const replaceCodeFences = (input: String) => {\n const codeFencesRegex = /```([\\w-]*)\\n([\\s\\S]*?)\\n```/g;\n return input\n .replace(codeFencesRegex, (match, p1, p2) => {\n const languageClass = p1 ? ` class="language-${p1}"` : "";\n return `
${p2}
`;\n })\n .replace(/\\n/g, "
");\n};\n'})}),"\n",(0,r.jsx)(n.p,{children:"Tiptap\uc744 \uc801\uc6a9\ud558\ub2c8 \ub2e4\uc74c\uacfc \uac19\uc774 \uae54\ub054\ud55c \ucf54\ub4dc \ube14\ub85d\uc744 \ubcfc \uc218 \uc788\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"tecochat",src:t(49124).Z+"",width:"2388",height:"1500"})}),"\n",(0,r.jsx)(n.h3,{id:"\ud3f0\ud2b8-\ubc0f-favicon-\uc801\uc6a9",children:"\ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9"}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc774\ud2c0\uc740 \ubc30\ub2ec\uc758\ubbfc\uc871 \ub3c4\ud604\uccb4, \ub0b4\uc6a9\uc740 IBM Plex Sans\ub97c \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c favicon\ub3c4 \uac04\ub2e8\ud558\uac8c \uc801\uc6a9\ud574\uc11c \ub9cc\uc871\uc2a4\ub7ec\uc6e0\ub2e4."]})]})}function d(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>l});var r=t(67294);function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(c[t]=e[t]);return c}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(c[t]=e[t])}return c}var o=r.createContext({}),l=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,c=e.mdxType,a=e.originalType,o=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),h=l(t),u=c,j=h["".concat(o,".").concat(u)]||h[u]||p[u]||a;return t?r.createElement(j,s(s({ref:n},d),{},{components:t})):r.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"},49124:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/teco-chat-6b4f31b3d961878efc5c506fc167df1f.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4137],{68801:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=t(85893),c=t(3905);const a={title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",slug:"tecochat-retrospective-1",tags:["TecoChat","Retrospective"]},s=void 0,i={permalink:"/tecochat-retrospective-1",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",source:"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",description:"4\uc6d4 21\uc77c \uae08\uc694\uc77c",date:"2023-04-22T00:00:00.000Z",formattedDate:"2023\ub144 4\uc6d4 22\uc77c",tags:[{label:"TecoChat",permalink:"/tags/teco-chat"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:5.68,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30",slug:"tecochat-retrospective-1",tags:["TecoChat","Retrospective"]},unlisted:!1,prevItem:{title:"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c",permalink:"/book-leadership-and-self-deception"},nextItem:{title:"Jenkins\ub85c CI/CD \uc124\uc815",permalink:"/jenkins"}},o={authorsImageUrls:[]},l=[{value:"4\uc6d4 21\uc77c \uae08\uc694\uc77c",id:"4\uc6d4-21\uc77c-\uae08\uc694\uc77c",level:3},{value:"\ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?",id:"\ub3c4\uba54\uc778-\uad6c\uc785-\uc131\uacf5",level:3},{value:"\ub9d0\ub791\uc758 DM",id:"\ub9d0\ub791\uc758-dm",level:3},{value:"\ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec",id:"\ub3c4\uba54\uc778-\uc124\uc815-\ubc0f-\ubc30\ud3ec",level:3},{value:"GPT",id:"gpt",level:3},{value:"Sonarcloud",id:"sonarcloud",level:3},{value:"Tiptap",id:"tiptap",level:3},{value:"\ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9",id:"\ud3f0\ud2b8-\ubc0f-favicon-\uc801\uc6a9",level:3}];function p(e){const n={br:"br",code:"code",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"4\uc6d4-21\uc77c-\uae08\uc694\uc77c",children:"4\uc6d4 21\uc77c \uae08\uc694\uc77c"}),"\n",(0,r.jsxs)(n.p,{children:["\ub808\ubca8 2\ub97c \uc2dc\uc791\ud55c \ub4a4 \ub0b4\uac00 \ud559\uc2b5\uc5d0 \ub300\ud55c \ubc29\ud5a5\uc744 \uc783\uc5b4\ubc84\ub838\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub808\ubca8 3, 4\uc5d0\uc11c \ub098\ub9cc\uc758 \uac15\uc810\uc744 \uac00\uc9c0\uace0 \uc2f6\uc5b4 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub2e8\uc21c\ud788 \uc2a4\ud504\ub9c1\uc744 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ud6a8\uc728\uc774 \ub9ce\uc774 \ub5a8\uc5b4\uc9c4\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae00\uc4f0\uae30 \uc218\uc0c1\uc73c\ub85c \ubc1b\uc740 \ucfe0\ud3f0\uc744 \uc0ac\uc6a9\ud574 \ube0c\ub77c\uc6b4\uc5d0\uac8c \ucee4\ud53c\ucc57\uc744 \uc2e0\uccad\ud588\uace0, \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud574\ubcf4\ub77c\ub294 \ub2f5\uc744 \ubc1b\uc558\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\ub098\ub294 \uc544\uc774\ub514\uc5b4\ub97c \ubabb\ub0b4\ub294 \ud3b8\uc778\ub370 \ube0c\ub77c\uc6b4\uc774 \uc544\uc774\ub514\uc5b4\uae4c\uc9c0 \ub358\uc838\uc8fc\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.code,{children:"Chat-GPT \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uace0, \ud574\ub2f9 \ud06c\ub8e8\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc744 \uacf5\uc720\ud560 \uc218 \uc788\ub294 \uac74 \uc5b4\ub5a4\uc9c0?"})]}),"\n",(0,r.jsxs)(n.p,{children:["\uae30\uc220\uc774 \ubaa9\uc801\uc778 \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4\ub294 \ub2f5\ubcc0\uc744 \ub4e4\uc5c8\uace0, \ud63c\uc790 \uc544\ub2c8\uba74 \ud398\uc5b4\ud560 \uc218 \uc788\uc744 \uc815\ub3c4\uc758 \uc778\uc6d0\uc73c\ub85c \uc9c4\ud589\ud558\uba74 \uc88b\uaca0\ub2e4\uace0 \ud558\uc168\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ud504\ub860\ud2b8\ub791 \uac04\ub2e8\ud558\uac8c \ubc30\ud3ec\uae4c\uc9c0 \ud574\ubcf8 \uacbd\ud5d8\uc774 \uc788\uc5b4\uc11c \ud63c\uc790\ud574\ub3c4 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc744 \uac83 \uac19\uc544\uc11c \ud63c\uc790 \ud558\uae30\ub85c \ub9c8\uc74c\uc744 \uba39\uc5c8\ub2e4."]}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uac74 \ubabb\ucc38\uc9c0"}),"\n",(0,r.jsx)(n.h3,{id:"\ub3c4\uba54\uc778-\uad6c\uc785-\uc131\uacf5",children:"\ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?"}),"\n",(0,r.jsxs)(n.p,{children:["\ucee4\ud53c\ucc57\uc774 \ub05d\ub098\uace0 \uc9d1\uc73c\ub85c \ub3cc\uc544\uac00\ub294 \uae38\uc5d0 \ubc14\ub85c \ub3c4\uba54\uc778\uc744 \uad6c\ub9e4\ud558\ub824\uace0 namecheap\uc5d0\uc11c \uc801\ub2f9\ud55c \ub3c4\uba54\uc778\uc774 \uc5c6\uc744\uae4c \uac80\uc0c9\uc744 \uacc4\uc18d\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub9c8\uce58 \uc5b4\ub9b4 \ub54c \ud588\ub358 \uac8c\uc784 \ub2c9\ub124\uc784 \uc815\ud558\ub294 \uac83\ucc98\ub7fc \uc2dc\uac04\uc774 \uc624\ub798 \uac78\ub838\ub2e4.",(0,r.jsx)(n.br,{}),"\n","dev, io, chat \ub3c4\uba54\uc778\uc774 \ud6c4\ubcf4\uc600\uace0 \uc9d1 \uac00\ub294 \uae38\uc5d0 \uacb0\uc815\ub9cc \ud558\ub2e4\uac00 \uad6c\ub9e4\ud558\uc9c0 \ubabb\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\ub9d0\ub791\uc758-dm",children:"\ub9d0\ub791\uc758 DM"}),"\n",(0,r.jsxs)(n.p,{children:["\uc9d1\uc5d0 \uac00\uc11c \ubc25\uc744 \uba39\uace0 \ub9d0\ub791\uc774\ub791 DM \ud558\ub2e4 \ud504\ub85c\uc81d\ud2b8\ub97c \uac19\uc774 \ud558\uc790\ub294 \uc774\uc57c\uae30\uac00 \ub098\uc654\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc6b0\ud14c\ucf54 \ucd5c\uace0 \uace0\uc218 \ub9d0\ub791\uc758 \uc694\uad6c\ub77c \uc218\ub77d\ud558\uc9c0 \uc54a\uc73c\uba74 \ud6c4\ud3ed\ud48d\uc744 \uac10\ub2f9\ud560 \uc218 \uc5c6\uc5c8\ub2e4."]}),"\n",(0,r.jsxs)(n.p,{children:["\uc774\ub7f0\uc800\ub7f0 \ub300\ud654\ub97c \ub098\ub204\ub2e4\uac00 \ub09c \ube60\ub974\uac8c \ud504\ub85c\ud1a0\ud0c0\uc785\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uace0 \uc2f6\uc5b4\uc11c \ud504\ub860\ud2b8\ub97c \uad6c\ud604\ud55c\ub2e4\uace0 \ud588\uace0, \ub9d0\ub791\uc740 GPT api\ub97c \uc870\uc0ac\ud558\uae30\ub85c \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ub3c4\uba54\uc778\uc5d0 \uad00\ud55c \uc774\uc57c\uae30\ub97c \ud558\ub2e4\uac00 woowachat\uc774 \uc5b8\uae09\ub418\uc5c8\uace0, namecheap\uc5d0\uc11c chat \ub3c4\uba54\uc778\uc744 \uc0ac\uc6a9\ud55c woowa.chat\uc73c\ub85c \uad6c\ub9e4\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc774\ud6c4\uc5d0 teco.chat\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4!"]}),"\n",(0,r.jsx)(n.h3,{id:"\ub3c4\uba54\uc778-\uc124\uc815-\ubc0f-\ubc30\ud3ec",children:"\ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec"}),"\n",(0,r.jsxs)(n.p,{children:["\ud1a0\uc694\uc77c\uc5d0 \uad6c\ub9e4\ud55c \ub3c4\uba54\uc778\uc744 CDN, \ubcf4\uc548 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 Cloudflare\uc5d0 \ub3c4\uba54\uc778 \ub4f1\ub85d\uc744 \ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub098\uc5d0\uac8c \uc775\uc219\ud55c Nuxt3\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\uace0, Cloudflare Pages\ub97c \uc774\uc6a9\ud558\uc5ec \ubc30\ud3ec\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"gpt",children:"GPT"}),"\n",(0,r.jsxs)(n.p,{children:["\ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud558\ub2c8 api limit\uc774 \uc788\uc5b4 \ubd84\ub2f9 3\ubc88\ubc16\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc77c\ub2e8 \ubc31\uc5d4\ub4dc\ub97c \uad6c\ucd95\ud558\uae30 \uc804\uc5d0\ub294 \ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud560 \uc0dd\uac01\uc774\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"sonarcloud",children:"Sonarcloud"}),"\n",(0,r.jsxs)(n.p,{children:["\uc815\uc801 \ucf54\ub4dc \ubd84\uc11d \ub3c4\uad6c\ub85c Sonarcloud\ub97c \uc801\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Sonarcloud\ub294 SonarQube\uc758 SaaS \ubc84\uc804\uc774\uace0 \uc0ac\uc6a9\uc774 \ub9e4\uc6b0 \ud3b8\ud558\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc608\uc804\uc5d0 Sonarcloud\ub97c \uc0ac\uc6a9\ud560 \ub550 \ubc84\ud2bc \uba87 \ubc88 \ub204\ub974\uba74 \uc801\uc6a9\ud560 \uc218 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \ubc14\ub85c github action\uc744 \uc0ac\uc6a9\ud558\ub77c\ub294 \uc548\ub0b4 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Sonarcloud\uac00 \uc790\uccb4\uc801\uc73c\ub85c github repository\uc5d0 push \ud558\uba74 \uc815\uc801 \ubd84\uc11d\uc744 \ud574\uc8fc\ub294 \uae30\ub2a5\uc744 \uc6d0\ud588\uace0, Administration -> Analysis Method\uc5d0 Automatic Analysis\ub97c \uc124\uc815\ud558\ub2c8 \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub108\ubb34 \uaf41\uaf41 \uc228\uaca8\uc838\uc788\ub124"]}),"\n",(0,r.jsx)(n.h3,{id:"tiptap",children:"Tiptap"}),"\n",(0,r.jsxs)(n.p,{children:["\ucf54\ub4dc \ud558\uc774\ub77c\uc774\ud305 \uae30\ub2a5\uc744 \ub123\uace0 \uc2f6\uc5b4\uc11c Tiptap\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Tiptap\uc740 Headless WYSIWYG \uc5d0\ub514\ud130\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uae30\ub2a5\uc5d0 \ud2b9\ud654\ub418\uc5b4\uc788\ub294 \uc5d0\ub514\ud130\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc544\uc9c1 Tiptap\uc774 \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uae30\ub2a5\uc744 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc0ac\uc6a9\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc CodeBlockLowlight \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucf54\ub4dc \ube14\ub85d\uc744 \uc608\uc058\uac8c \ucd9c\ub825\ud560 \uc218 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","api \ubc18\ud658\uac12 \uadf8\ub300\ub85c tiptap\uc758 content\uc5d0 \uc124\uc815\ud588\ub354\ub2c8 \ucf54\ub4dc \ube14\ub85d\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc544\uc11c \ubc31 \ud2f1 3\uac1c\ub97c ",(0,r.jsx)(n.code,{children:"
"}),"\ub85c \ubcc0\ud658\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c \ub744\uc5b4\uc4f0\uae30\ub3c4 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc544\uc11c ",(0,r.jsx)(n.code,{children:"\\n"}),"\ub97c ",(0,r.jsx)(n.code,{children:"
"}),"\ud0dc\uadf8\ub85c \ubcc0\ud658\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ubcc0\ud658\ud558\ub294 \ub85c\uc9c1\uc740 GPT\uc758 \ub3c4\uc6c0\uc744 \ub9ce\uc774 \ubc1b\uc558\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:'const replaceCodeFences = (input: String) => {\n const codeFencesRegex = /```([\\w-]*)\\n([\\s\\S]*?)\\n```/g;\n return input\n .replace(codeFencesRegex, (match, p1, p2) => {\n const languageClass = p1 ? ` class="language-${p1}"` : "";\n return `
${p2}
`;\n })\n .replace(/\\n/g, "
");\n};\n'})}),"\n",(0,r.jsx)(n.p,{children:"Tiptap\uc744 \uc801\uc6a9\ud558\ub2c8 \ub2e4\uc74c\uacfc \uac19\uc774 \uae54\ub054\ud55c \ucf54\ub4dc \ube14\ub85d\uc744 \ubcfc \uc218 \uc788\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"tecochat",src:t(49124).Z+"",width:"2388",height:"1500"})}),"\n",(0,r.jsx)(n.h3,{id:"\ud3f0\ud2b8-\ubc0f-favicon-\uc801\uc6a9",children:"\ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9"}),"\n",(0,r.jsxs)(n.p,{children:["\ud0c0\uc774\ud2c0\uc740 \ubc30\ub2ec\uc758\ubbfc\uc871 \ub3c4\ud604\uccb4, \ub0b4\uc6a9\uc740 IBM Plex Sans\ub97c \uc0ac\uc6a9\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ucd94\uac00\ub85c favicon\ub3c4 \uac04\ub2e8\ud558\uac8c \uc801\uc6a9\ud574\uc11c \ub9cc\uc871\uc2a4\ub7ec\uc6e0\ub2e4."]})]})}function d(e={}){const{wrapper:n}={...(0,c.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>l});var r=t(67294);function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(c[t]=e[t]);return c}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(c[t]=e[t])}return c}var o=r.createContext({}),l=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,c=e.mdxType,a=e.originalType,o=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),h=l(t),u=c,j=h["".concat(o,".").concat(u)]||h[u]||p[u]||a;return t?r.createElement(j,s(s({ref:n},d),{},{components:t})):r.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"},49124:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/teco-chat-6b4f31b3d961878efc5c506fc167df1f.png"}}]); \ No newline at end of file diff --git a/assets/js/f06cb3e2.536ef825.js b/assets/js/f06cb3e2.0fe3406d.js similarity index 99% rename from assets/js/f06cb3e2.536ef825.js rename to assets/js/f06cb3e2.0fe3406d.js index 545e85f4d..14503919f 100644 --- a/assets/js/f06cb3e2.536ef825.js +++ b/assets/js/f06cb3e2.0fe3406d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2620],{43487:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>u,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>d});var a=r(85893),t=r(3905),i=r(74866),l=r(85162);const s={title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",slug:"db-replication",tags:["mysql","replication"]},c=void 0,o={permalink:"/db-replication",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",source:"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",description:"\ubcf5\uc81c(Replication)",date:"2023-08-22T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 22\uc77c",tags:[{label:"mysql",permalink:"/tags/mysql"},{label:"replication",permalink:"/tags/replication"}],readingTime:21,hasTruncateMarker:!1,authors:[],frontMatter:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",slug:"db-replication",tags:["mysql","replication"]},unlisted:!1,prevItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",permalink:"/woowacourse-level3-retrospective"}},u={authorsImageUrls:[]},d=[{value:"\ubcf5\uc81c(Replication)",id:"\ubcf5\uc81creplication",level:2},{value:"\ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720",id:"\ubcf5\uc81c\ub97c-\ud558\ub294-\uc774\uc720",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ud30c\uc77c-\uc704\uce58-\uae30\ubc18-\ubcf5\uc81c",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd\uc758-\ubb38\uc81c\uc810",level:3},{value:"\uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c",id:"\uae00\ub85c\ubc8c-\ud2b8\ub79c\uc7ad\uc158-\uc544\uc774\ub514gtid-\uae30\ubc18-\ubcf5\uc81c",level:3},{value:"\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0",id:"\ubcf5\uc81c-\ud1a0\ud3f4\ub85c\uc9c0",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd-replication-\uad6c\uc131\ud558\uae30",level:2},{value:"MySQL \ud658\uacbd \uad6c\uc131",id:"mysql-\ud658\uacbd-\uad6c\uc131",level:3},{value:"\ub3c4\ucee4 \uc2e4\ud589",id:"\ub3c4\ucee4-\uc2e4\ud589",level:3},{value:"replication slave \uad8c\ud55c \uc124\uc815",id:"replication-slave-\uad8c\ud55c-\uc124\uc815",level:3},{value:"SOURCE DB \uc815\ubcf4 \ud655\uc778",id:"source-db-\uc815\ubcf4-\ud655\uc778",level:3},{value:"SOURCE ip \uc8fc\uc18c \ud655\uc778",id:"source-ip-\uc8fc\uc18c-\ud655\uc778",level:3},{value:"replica mysql \uc811\uc18d",id:"replica-mysql-\uc811\uc18d",level:3},{value:"replica \uc124\uc815",id:"replica-\uc124\uc815",level:3},{value:"\uc124\uc815 \ud655\uc778",id:"\uc124\uc815-\ud655\uc778",level:3},{value:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30",id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8\ub85c-db-\uc811\uadfc\ud558\uae30",level:2},{value:"Environment \uc124\uc815",id:"environment-\uc124\uc815",level:3},{value:"DataSourceType \uc124\uc815",id:"datasourcetype-\uc124\uc815",level:3},{value:"AbstractRoutingDataSource \uc124\uc815",id:"abstractroutingdatasource-\uc124\uc815",level:3},{value:"DataSource \uc124\uc815",id:"datasource-\uc124\uc815",level:3},{value:"\ub3d9\uc791 \ud655\uc778",id:"\ub3d9\uc791-\ud655\uc778",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"\ubcf5\uc81creplication",children:"\ubcf5\uc81c(Replication)"}),"\n",(0,a.jsxs)(n.p,{children:["\ud55c \uc11c\ubc84\uc5d0\uc11c \ub2e4\ub978 \uc11c\ubc84\ub85c \ub370\uc774\ud130\ub97c \ub3d9\uae30\ud654\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc6d0\ubcf8 \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Primary \ub610\ub294 Source \ub77c\uace0 \ubd80\ub974\uace0, \ubcf5\uc81c\ub41c \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Secondary \ub610\ub294 Replica \ub77c\uace0 \ubd80\ub978\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ubcf5\uc81c\ub97c-\ud558\ub294-\uc774\uc720",children:"\ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"1. \uc2a4\ucf00\uc77c \uc544\uc6c3"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc0ac\uc6a9\uc790\uc758 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uac00\ud574\uc9c0\ub294 \ubd80\ud558\ub3c4 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc99d\uac00\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub97c \ucc98\ub9ac\ud558\uae30 \uc704\ud574 \ubcf5\uc81c\ub97c \ud1b5\ud55c \uc2a4\ucf00\uc77c \uc544\uc6c3\uc744 \uc801\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucffc\ub9ac\ub4e4\uc744 \uac01\uac01\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c \ubd84\uc0b0 \uc2dc\ud0ac \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"2. \ub370\uc774\ud130 \ubc31\uc5c5"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc2e4\uc81c \uc6b4\uc601\ub418\ub294 \uc11c\ube44\uc2a4\uac00 \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 DB\uc5d0\uc11c \ubc31\uc5c5\uc744 \uc9c4\ud589\ud558\ub294 \uacbd\uc6b0, \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc774 \uac00\uc9c0 \uc54a\ub3c4\ub85d \ubcf5\uc81c\ub97c \ud1b5\ud574 Replica \uc11c\ubc84\ub97c \uad6c\ucd95\ud558\uc5ec, Replica \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ub97c \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\uc73c\ub85c \uc601\ud5a5\uc744 \ucd5c\uc18c\ud654 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"3. \ub370\uc774\ud130 \ubd84\uc11d"})}),"\n",(0,a.jsxs)(n.p,{children:["\ubc31\uc5c5\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc7a1\ud558\uace0 \ubb34\uac70\uc6b4 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\uc758 \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc81c\ub97c \uc0ac\uc6a9\ud574 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"4. \ub370\uc774\ud130\uc758 \uc9c0\ub9ac\uc801 \ubd84\uc0b0"})}),"\n",(0,a.jsx)(n.p,{children:"\ube60\ub978 \uc751\ub2f5\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc11c\ubc84\uc5d0 \uac00\uae5d\uac8c \uc11c\ubc84\ub97c \uad6c\uc131\ud558\uac70\ub098, \uace0\uac00\uc6a9\uc131(High Availability)\uc744 \uc704\ud574\uc11c\ub3c4 \uc0ac\uc6a9\ub41c\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ud30c\uc77c-\uc704\uce58-\uae30\ubc18-\ubcf5\uc81c",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c"}),"\n",(0,a.jsxs)(n.p,{children:["MySQL \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub85c\uadf8 \ud30c\uc77c\uc744 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub77c\uace0 \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ud1b5\ud574 \ub370\uc774\ud130 \ubcc0\uacbd, \ud14c\uc774\ube14 \uad6c\uc870 \ubcc0\uacbd, \uacc4\uc815\uc774\ub098 \uad8c\ud55c \ubcc0\uacbd\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc800\uc7a5\ub41c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","MySQL\uc758 \ubcf5\uc81c\ub294 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. \uc774\ub97c Replica \uc11c\ubc84\ub85c \uc804\ub2ec\ud558\uace0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph Replica\n\t\tdirection TB\n\t\tIO[Replication I/O thread] -- save --\x3e RL[Relay Log]\n\t\tSQL[Replication SQL Thread] -- read --\x3e RL\n\tend\n\n\tsubgraph Source\n\t\tdirection TB\n\t\tBLD[Binary Log Dump Thread] -- Send Binary Log Dump--\x3e IO\n\tend\n"}),"\n",(0,a.jsx)(n.admonition,{title:"\uc2a4\ub808\ub4dc\ubcc4 \uc5ed\ud560",type:"note",children:(0,a.jsxs)(n.p,{children:["Binary Log Dump Thread: \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc758 \ub0b4\uc6a9\uc744 Replica \uc11c\ubc84\ub85c \uc804\ub2ec",(0,a.jsx)(n.br,{}),"\n","Replication I/O Thread: Binary \ub85c\uadf8 \uc774\ubca4\ud2b8\ub97c \uac00\uc838\uc640 \ub85c\uceec \uc11c\ubc84\uc758 \ud30c\uc77c(Relay Log)\ub85c \uc800\uc7a5",(0,a.jsx)(n.br,{}),"\n","Replication SQL Thread: \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc774\ubca4\ud2b8\ub97c \uc77d\uace0 \uc2e4\ud589"]})}),"\n",(0,a.jsx)(n.h3,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd\uc758-\ubb38\uc81c\uc810",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810"}),"\n",(0,a.jsxs)(n.p,{children:["\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc740 \uc11c\ubc84\uc5d0 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0 \ubcc0\uacbd\uc774 \uae4c\ub2e4\ub86d\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud1a0\ud3f4\ub85c\uc9c0\ub780 \ub124\ud2b8\uc6cc\ud06c\uc758 \uc694\uc18c\ub4e4\uc744 \ubb3c\ub9ac\uc801\uc73c\ub85c \uc5f0\uacb0\ud574 \ub193\uc740 \uac83, \ub610\ub294 \uadf8 \uc5f0\uacb0 \ubc29\uc2dd\uc744 \ub9d0\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph TD\n\tA[A binary-log:300] --\x3e B[B Binary-log:300]\n\tA[A binary-log:300] --\x3e C[C Binary-log:200]"}),"\n",(0,a.jsx)(n.p,{children:"\uc704\uc640 \uac19\uc774 Source \uc11c\ubc84, Replica 2\ub300\uac00 \uc874\uc7ac\ud558\uace0, C \uc11c\ubc84\uc5d0 \ubcf5\uc81c \uc9c0\uc5f0\uc774 \ub418\uc5c8\uc744 \ub54c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph TD\n\tA[A binary-log:300]\n\tB[B Binary-log:300] --\x3e C[C Binary-log:200 \ubb38\uc81c \ubc1c\uc0dd]"}),"\n",(0,a.jsxs)(n.p,{children:["A \uc11c\ubc84\uc5d0\uc11c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 B \uc11c\ubc84\ub97c Source \uc11c\ubc84\ub85c \uc2b9\uaca9\ud558\uace0, C\uc5d0\uac8c \uc870\ud68c \ucffc\ub9ac\ub97c \ubd84\uc0b0\uc2dc\ud0a8\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \uc5ec\uae30\uc11c C \uc11c\ubc84\uc5d0\ub294 A \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\uac00 \uc548\ub418\uc5c8\uc73c\ub2c8 \uc870\ud68c \uc2dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub4a4\ub2a6\uac8c B \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\ub97c \ud558\ub824\uace0 \ud574\ub3c4, \uc5b4\ub5a4 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8, \uc5b4\ub5a4 \uc704\uce58\uc640 \ub3d9\uae30\ud654\ud574\uc57c\ud558\ub294\uc9c0 \uc54c\uae30 \uc5b4\ub835\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\uae00\ub85c\ubc8c-\ud2b8\ub79c\uc7ad\uc158-\uc544\uc774\ub514gtid-\uae30\ubc18-\ubcf5\uc81c",children:"\uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c"}),"\n",(0,a.jsxs)(n.p,{children:["GTID \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ubc1c\uc0dd\ud55c \uc774\ubca4\ud2b8\uc5d0 \uace0\uc720\ud55c \uc2dd\ubcc4\uac12\uc744 \ubd80\uc5ec\ud55c\ub2e4\uba74, \ub3d9\uae30\ud654\uc5d0 \ub300\ud55c \ubb38\uc81c\ub97c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc704\uc758 \uc608\uc2dc\uc640 \uac19\uc774 \ubcf5\uc81c \uc9c0\uc5f0\uacfc \ud568\uaed8 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ud574\ub3c4 \ud2b9\uc815 GTID \ubd80\ud130 \ubcf5\uc81c\ub97c \uc7ac\uac1c\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,a.jsx)(n.admonition,{title:"GTID",type:"note",children:(0,a.jsxs)(n.p,{children:["\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\uc5d0 \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \uc11c\ubc84\uc5d0\uc11c \uace0\uc720\ud558\ub3c4\ub85d \uac01 \uc774\ubca4\ud2b8\uc5d0 \ubd80\uc5ec\ub41c \uc2dd\ubcc4\uac12",(0,a.jsx)(n.br,{}),"\n","[source_id]:[transaction_id]\ub85c \uad6c\uc131\ub418\uba70, source_id\ub294 \uc11c\ubc84\ub97c \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc774\uace0 transaction_id\ub294 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc73c\ub85c 1\uc529 \uc99d\uac00\ud558\ub294 \ud615\ud0dc\ub85c \ubc1c\uae09\ub41c\ub2e4."]})}),"\n",(0,a.jsx)(n.h3,{id:"\ubcf5\uc81c-\ud1a0\ud3f4\ub85c\uc9c0",children:"\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["\uac00\uc7a5 \uac04\ub2e8\ud55c \uad6c\uc131\uc73c\ub85c \uc81c\uc77c \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","replica \uc11c\ubc84\ub97c \uc77d\uae30 \uc804\uc6a9, \uc608\ube44 \uc11c\ubc84, \ubc31\uc5c5 \uc6a9\ub3c4\ub85c \ub9ce\uc774 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R\n S[Source] --\x3e R[Replica]"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uba40\ud2f0 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["2\uac1c\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\ub098\uc758 replica\ub294 \uc608\ube44 \uc6a9\ub3c4\ub85c \ub0a8\uaca8\ub450\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucd94\ud6c4\uc5d0 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 \uc608\ube44 \uc6a9\ub3c4\uc758 replica\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c \uc77d\uae30 \uc694\uccad\uc758 \ubd80\ud558 \ubd84\uc0b0\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R1\n S[Source] --\x3e R1[Replica1]\n S --\x3e R2[Replica2]"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uccb4\uc778 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["replica \uc11c\ubc84\uac00 \ub9ce\uc740 \uacbd\uc6b0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \uc804\ub2ec\ud558\ub294 \uc791\uc5c5 \uc790\uccb4\uac00 \ubd80\ud558\uac00 \ub420 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c 1:M",":M"," \uad6c\uc870\ub85c \uccb4\uc778 \ubcf5\uc81c \uad6c\uc131\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R1\n S[Source] --\x3e R1[Replica1]\n S --\x3e R2[Replica2]\n S --\x3e R3[Replica3]\n\n R3 --\x3e R3-1[Replica 3-1]\n R3 --\x3e R3-2[Replica 3-2]\n\n B[Batch Server] --\x3e R3-2"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\ub4c0\uc5bc \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["2\uac1c\uc758 MySQL \uc11c\ubc84 \ubaa8\ub450 \uc77d\uae30\uc640 \uc4f0\uae30\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d \ud558\ub294 \uad6c\uc131\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uac01 \uc11c\ubc84\uc5d0\uc11c \ubcc0\uacbd\ub41c \ub370\uc774\ud130\ub294 \ub2e4\ub978 \uc11c\ubc84\uc5d0 \ubc18\uc601\ub41c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ubaa9\uc801\uc5d0 \ub530\ub77c ACTIVE-ACTIVE \ud615\ud0dc \ub610\ub294 ACTIVE-PASSIVE \ud615\ud0dc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","ACTIVE-PASSIVE \ud615\ud0dc\uc778 \uacbd\uc6b0 \uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131\uacfc \ub3d9\uc77c\ud574\ubcf4\uc774\uc9c0\ub9cc, ACTIVE \uc11c\ubc84\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uba74 \uc124\uc815\uc758 \ubcc0\uacbd\uc5c6\uc774 PASSIVE \uc11c\ubc84\ub85c \uc4f0\uae30 \uc791\uc5c5\uc744 \uc804\ud658\ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc774 \uc7a5\uc810\uc774\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR1\n W -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR2\n SR1[Source/Replica 1] --\x3e SR2[Source/Replica 2]"}),"\n",(0,a.jsx)(n.admonition,{title:"ACTIVE-ACTIVE, ACTIVE-PASSIVE",type:"note",children:(0,a.jsxs)(n.p,{children:["ACTIVE-ACTIVE: 2\uac1c\uc758 \uc11c\ubc84 \ubaa8\ub450 \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc",(0,a.jsx)(n.br,{}),"\n","ACTIVE-PASSIVE: \ud558\ub098\uc758 \uc11c\ubc84\uc5d0\uc11c\ub9cc \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc"]})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uba40\ud2f0 \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc5ec\ub7ec\uac1c\uc758 source \uc11c\ubc84\uc640 \ud558\ub098\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \uad6c\uc131\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub294 source \uc11c\ubc84\uc758 \ub370\uc774\ud130\ub97c \ud55c \uacf3\uc5d0 \ubc31\uc5c5\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9, \uc5ec\ub7ec \uc11c\ubc84\uc5d0 \uc874\uc7ac\ud558\ub294 \ub370\uc774\ud130\ub97c \ud1b5\ud569, \uc0e4\ub529\ub418\uc5b4\uc788\ub294 \ud14c\uc774\ube14 \ub370\uc774\ud130\ub97c \ud1b5\ud569\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n S1[Source 1] --\x3e R[Replica]\n S2[Source 2] --\x3e R"}),"\n",(0,a.jsx)(n.h2,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd-replication-\uad6c\uc131\ud558\uae30",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30"}),"\n",(0,a.jsxs)(n.p,{children:["mysql 2\ub300\ub97c \uc774\uc6a9\ud558\uc5ec replication\uc744 \uad6c\uc131\ud558\uace0, spring boot application\uc73c\ub85c source, replica \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\ubcf4\ub294 \uc608\uc81c\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://github.com/bbiac/db-replication",children:"https://github.com/bbiac/db-replication"})]}),"\n",(0,a.jsx)(n.h3,{id:"mysql-\ud658\uacbd-\uad6c\uc131",children:"MySQL \ud658\uacbd \uad6c\uc131"}),"\n",(0,a.jsxs)(n.p,{children:["MySQL \ubc84\uc804\uc740 8.1\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","13306, 13307 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud574\uc11c MySQL \uc11c\ubc84 2\ub300\ub97c \ub744\uc6e0\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub610\ud55c \uc0ac\uc2e4 IP \ub300\uc5ed\uc73c\ub85c \ud1b5\uc2e0\ud560 \uc218 \uc788\ub3c4\ub85d \ucee4\uc2a4\ud140 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yml",children:"version: '3.8'\n\nservices:\n source:\n platform: linux/x86_64\n image: mysql:latest\n restart: always\n container_name: mysql-source\n environment:\n TZ: 'Asia/Seoul'\n MYSQL_DATABASE: 'db'\n MYSQL_USER: 'user'\n MYSQL_PASSWORD: 'password'\n MYSQL_ROOT_PASSWORD: 'password'\n ports:\n - \"13306:3306\"\n volumes:\n - db-source:/var/lib/mysql\n - db-source:/var/lib/mysql-files\n - ./docker/source.cnf:/etc/mysql/my.cnf\n networks:\n - mysql_network\n\n replica:\n platform: linux/x86_64\n image: mysql:latest\n restart: always\n container_name: mysql-replica\n environment:\n TZ: 'Asia/Seoul'\n MYSQL_DATABASE: 'db'\n MYSQL_USER: 'user'\n MYSQL_PASSWORD: 'password'\n MYSQL_ROOT_PASSWORD: 'password'\n ports:\n - \"13307:3306\"\n volumes:\n - db-replica:/var/lib/mysql\n - db-replica:/var/lib/mysql-files\n - ./docker/replica.cnf:/etc/mysql/my.cnf\n networks:\n - mysql_network\n\nvolumes:\n db-source:\n db-replica:\n\nnetworks:\n mysql_network:\n driver: bridge\n"})}),"\n",(0,a.jsx)(n.p,{children:"\ub610\ud55c source, replica \uac01\uac01 \ub2e4\uc74c\uacfc \uac19\uc774 db \uc124\uc815\uc744 \ud588\ub2e4."}),"\n",(0,a.jsxs)(n.table,{children:[(0,a.jsx)(n.thead,{children:(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.th,{children:"\uc124\uc815"}),(0,a.jsx)(n.th,{children:"\uc124\uba85"})]})}),(0,a.jsxs)(n.tbody,{children:[(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"server_id"}),(0,a.jsx)(n.td,{children:"\uac01\uac01\uc758 mysql \ub9c8\ub2e4 \uace0\uc720\ud55c \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"log_bin"}),(0,a.jsx)(n.td,{children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815\uc73c\ub85c \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 /var/lib/mysql \uc544\ub798 \ud574\ub2f9 log_bin\uc5d0 \uc124\uc815\ub41c \uac12\uc73c\ub85c \ub85c\uadf8\uac00 \uc0dd\uc131\ub41c\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"sync_binlog"}),(0,a.jsx)(n.td,{children:"N\uac1c\uc758 \ud2b8\ub79c\uc7ad\uc158 \ub2f9 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ub514\uc2a4\ud06c\uc640 \ub3d9\uae30\ud654 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d \ud55c\ub2e4.\xa01\uc740 \uae30\ubcf8\uac12\uc73c\ub85c \uc548\uc815\uc801\uc774\uc9c0\ub9cc, \uac00\uc7a5 \ub290\ub9ac\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"relay_log"}),(0,a.jsx)(n.td,{children:"\ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"relay_log_purge"}),(0,a.jsx)(n.td,{children:"\ud544\uc694 \uc5c6\ub294 \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \uc0ad\uc81c\ud558\ub294 \uc635\uc158"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"read_only"}),(0,a.jsx)(n.td,{children:"\uc77d\uae30 \uc804\uc6a9 \uc124\uc815"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"log_replica_updates"}),(0,a.jsx)(n.td,{children:"Replication SQL Thread\ub85c \uc778\ud574 \uc2e4\ud589\ub418\ub294 \uc815\ubcf4\ub97c \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc5d0 \uae30\ub85d \ucd94\ud6c4\uc5d0 \uc18c\uc2a4 \uc11c\ubc84\ub85c \uc2b9\uaca9\ub418\ub294 \uacbd\uc6b0\ub97c \uace0\ub824\ud558\uba74 \uc124\uc815\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."})]})]})]}),"\n","\n","\n",(0,a.jsxs)(i.Z,{children:[(0,a.jsx)(l.Z,{value:"Source",label:"Source",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-cnf",metastring:'title="/docker/source.cnf"',children:"[mysqld]\nserver_id=1\nlog_bin=mysql-bin\nsync_binlog=1\n"})})}),(0,a.jsx)(l.Z,{value:"Replica",label:"Replica",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-cnf",metastring:'title="/docker/replica.cnf"',children:"[mysqld]\nserver_id=2\nrelay_log=mysql-relay-bin\nrelay_log_purge=ON\nread_only\nlog_replica_updates\n"})})})]}),"\n",(0,a.jsx)(n.h3,{id:"\ub3c4\ucee4-\uc2e4\ud589",children:"\ub3c4\ucee4 \uc2e4\ud589"}),"\n",(0,a.jsxs)(n.p,{children:["docker-compose up \uba85\ub839\uc5b4\ub85c docker-compose \uc124\uc815\uc73c\ub85c docker\ub97c \ub744\uc6b4\ub2e4.",(0,a.jsx)(n.br,{}),"\n","-d \uc635\uc158\uc744 \ubd99\uc774\uba74 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ubaa8\ub4dc\ub85c \uc2e4\ud589\ub41c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"docker-compose up -d\n"})}),"\n",(0,a.jsx)(n.h3,{id:"replication-slave-\uad8c\ud55c-\uc124\uc815",children:"replication slave \uad8c\ud55c \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["REPLICATION SLAVE \uad8c\ud55c\uc774 \uc124\uc815\ub418\uc5b4 \uc788\uc5b4\uc57c replica \uc11c\ubc84\uc5d0\uc11c source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec \ub85c\uadf8\ub97c \uc77d\uc5b4\uc62c \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec user \uacc4\uc815\uc5d0 \ud574\ub2f9 \uad8c\ud55c\uc744 \uc124\uc815\ud574\uc900\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:"SOURCE \uc811\uc18d"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker exec -it mysql-source mysql -u root -p\n"})}),"\n",(0,a.jsx)(n.p,{children:"user \uacc4\uc815\uc5d0 REPLICATION SLAVE \uad8c\ud55c \ucd94\uac00"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"GRANT REPLICATION SLAVE ON *.* TO 'user'@'%';\nFLUSH PRIVILEGES;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"source-db-\uc815\ubcf4-\ud655\uc778",children:"SOURCE DB \uc815\ubcf4 \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["replica \uc124\uc815\uc5d0 \ud544\uc694\ud55c source db\uc758 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c\uba85\uacfc Position\uc744 \ud655\uc778\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","Position \uac12\uc740 \uc2e4\uc81c \ud30c\uc77c\uc758 \ubc14\uc774\ud2b8 \uc218\ub97c \uc758\ubbf8\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud655\uc778\ud55c File(SOURCE_LOG_FILE)\uacfc Position(SOURCE_LOG_POS) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"SHOW MASTER STATUS;\n\n+------------------+----------+--------------+------------------+-------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |\n+------------------+----------+--------------+------------------+-------------------+\n| mysql-bin.000003 | 1082 | | | |\n+------------------+----------+--------------+------------------+-------------------+\n"})}),"\n",(0,a.jsx)(n.h3,{id:"source-ip-\uc8fc\uc18c-\ud655\uc778",children:"SOURCE ip \uc8fc\uc18c \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["docker inspect -f \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ud574\ub2f9 \ucee8\ud14c\uc774\ub108\uc758 \uc138\ubd80 \uc815\ubcf4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud574 docker-compose \ud30c\uc77c\uc5d0 \uc124\uc815\ud574\ub454 mysql_network\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc124 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'docker inspect -f "{{with index .NetworkSettings.Networks \\"db-replication_mysql_network\\"}}{{.IPAddress}}{{end}}" mysql-source\n'})}),"\n",(0,a.jsxs)(n.p,{children:["ip \uc8fc\uc18c\uac00 \ub098\uc624\uc9c0 \uc54a\ub294 \uacbd\uc6b0 docker inspect mysql-source\ub85c \ud655\uc778\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud655\uc778\ud55c IP\uc8fc\uc18c(SOURCE_HOST) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"replica-mysql-\uc811\uc18d",children:"replica mysql \uc811\uc18d"}),"\n",(0,a.jsx)(n.p,{children:"source db\uc5d0 \uc811\uc18d\ud588\ub358 \ubc29\ubc95\uacfc \ub3d9\uc77c\ud558\uac8c replica db\uc5d0 \uc811\uc18d\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker exec -it mysql-replica mysql -u root -p\n"})}),"\n",(0,a.jsx)(n.h3,{id:"replica-\uc124\uc815",children:"replica \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\uc774\uc804\uc5d0 source db\uc5d0\uc11c \uc5bb\uc5c8\ub358 \uc815\ubcf4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc5ec replica \uc124\uc815\uc744 \uc9c4\ud589\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc2e4\uc81c DB \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc73c\ub85c source DB\uc758 \ud30c\uc77c\uc744 \ubcf5\uc81c\ud574\uc57c\ud558\uc9c0\ub9cc \ud604\uc7ac \ubcf5\uc81c\ud560 \ub370\uc774\ud130\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ubd80\ubd84\uc740 \uc0dd\ub7b5\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","SOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS \ub97c \uc801\uc808\ud788 \ubcc0\uacbd\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"STOP REPLICA;\n\nCHANGE REPLICATION SOURCE TO \nSOURCE_HOST='172.29.0.2', \nSOURCE_USER='user', \nSOURCE_PASSWORD='password', \nSOURCE_LOG_FILE='mysql-bin.000001', \nSOURCE_LOG_POS=0, \nGET_SOURCE_PUBLIC_KEY=1;\n\nSTART REPLICA;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"\uc124\uc815-\ud655\uc778",children:"\uc124\uc815 \ud655\uc778"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"SHOW REPLICA STATUS;\n\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n| Waiting for source to send event | 172.25.0.3 | user | 3306 | 60 | mysql-bin.000003 | 1082 | mysql-relay-bin.000002 | 868 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 1082 | 1078 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | | | 1 | |\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n"})}),"\n",(0,a.jsx)(n.p,{children:"Replica_IO_Running, Replica_SQL_Running \uac12\uc774 YES\ub77c\uba74 \uc815\uc0c1\uc801\uc73c\ub85c replication \uad6c\uc131\uc774 \uc644\ub8cc\ub41c \uac83\uc774\ub2e4."}),"\n",(0,a.jsxs)(n.p,{children:["\uc124\uc815\uc744 \ub9c8\uce5c \ud6c4 source db\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 create table \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","replica db\uc5d0 \ub3d9\uc77c\ud55c member table\uc774 \uc0dd\uc131\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE member\n(\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\n name VARCHAR(255)\n);\n"})}),"\n",(0,a.jsx)(n.h2,{id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8\ub85c-db-\uc811\uadfc\ud558\uae30",children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30"}),"\n",(0,a.jsx)(n.p,{children:"\uc77c\ubc18\uc801\uc778 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 source, \uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158\uc778 \uacbd\uc6b0 replica\ub85c \uc694\uccad\uc774 \uac00\ub3c4\ub85d \uad6c\uc131\ud574\ubcf4\uc790."}),"\n",(0,a.jsx)(n.h3,{id:"environment-\uc124\uc815",children:"Environment \uc124\uc815"}),"\n",(0,a.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 source, replica\ub85c \uad6c\ubd84\ud558\uc5ec \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yml",metastring:'title="application.yml"',children:"spring:\n datasource:\n source:\n username: user\n password: password\n driver-class-name: com.mysql.cj.jdbc.Driver\n jdbc-url: jdbc:mysql://localhost:13306/db\n replica:\n username: user\n password: password\n driver-class-name: com.mysql.cj.jdbc.Driver\n jdbc-url: jdbc:mysql://localhost:13307/db\n"})}),"\n",(0,a.jsx)(n.h3,{id:"datasourcetype-\uc124\uc815",children:"DataSourceType \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\ub2e8\uc21c \ubb38\uc790\uc5f4\ub85c\ub3c4 \uad6c\ubd84\ud560 \uc218 \uc788\uc9c0\ub9cc, enum\uc744 \uc774\uc6a9\ud574\uc11c \ud2b8\ub79c\uc7ad\uc158\uc744 \uad6c\ubd84\ud558\ub3c4\ub85d \uc0dd\uc131\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","Key\ub294 \ucd94\ud6c4\uc5d0 \ube48 \uc124\uc815\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="DataSourceType"',children:'public enum DataSourceType {\n SOURCE(SOURCE_NAME),\n REPLICA(REPLICA_NAME),\n ;\n\n private final String key;\n\n DataSourceType(String key) {\n this.key = key;\n }\n\n public static class Key {\n public static final String ROUTING_NAME = "ROUTING";\n public static final String SOURCE_NAME = "SOURCE";\n public static final String REPLICA_NAME = "REPLICA";\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"abstractroutingdatasource-\uc124\uc815",children:"AbstractRoutingDataSource \uc124\uc815"}),"\n",(0,a.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1\uc774 \uc9c0\uc6d0\ud574\uc8fc\ub294 AbstractRoutingDataSource\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSource\ub97c \ud5a5\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsxs)(n.p,{children:["\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub294 ",(0,a.jsx)(n.code,{children:"Map"}),"\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\uc744 \ubc1b\uc544 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"setDefaultTargetDataSource: \uae30\ubcf8 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"setTargetDataSources: \ub9f5 \ud615\ud0dc\ub85c \ubc1b\uc740 \ub370\uc774\ud130 \uc18c\uc2a4 \uac12\ub4e4\uc744 \uc124\uc815\ud55c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"determineCurrentLookupKey\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \ud2b8\ub79c\uc7ad\uc158\uc774 \uc77d\uae30 \uc804\uc6a9\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uace0, \ubc18\ud658\ud55c \uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ub370\uc774\ud130 \uc18c\uc2a4\uac00 \uc0ac\uc6a9\ub41c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="RoutingDataSource"',children:'public class RoutingDataSource extends AbstractRoutingDataSource {\n\n private final Logger log = LoggerFactory.getLogger(getClass());\n\n public static RoutingDataSource from(Map dataSources) {\n RoutingDataSource routingDataSource = new RoutingDataSource();\n routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));\n routingDataSource.setTargetDataSources(dataSources);\n return routingDataSource;\n }\n\n @Override\n protected Object determineCurrentLookupKey() {\n boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();\n\n if (readOnly) {\n log.info("readOnly = true, request to replica");\n return DataSourceType.REPLICA;\n }\n log.info("readOnly = false, request to source");\n return DataSourceType.SOURCE;\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"datasource-\uc124\uc815",children:"DataSource \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c\ubd80\ud130 \uc21c\uc11c\ub300\ub85c Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy \uc124\uc815\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc2a4\ud504\ub9c1\uc740 \ud2b8\ub79c\uc7ad\uc158 \uc2dc\uc791\uc2dc\uc5d0 \ucee4\ub125\uc158\uc758 \uc0ac\uc6a9\uc5ec\ubd80\uc640 \uc0c1\uad00\uc5c6\uc774 \ucee4\ub125\uc158\uc744 \ud655\ubcf4\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c readOnly \ud2b8\ub79c\uc7ad\uc158\uc774 \uc124\uc815\ub41c \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ubbf8\ub9ac \ud655\ubcf4\ub41c \ucee4\ub125\uc158\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 replica db\ub85c \uc694\uccad\uc744 \ud558\uc9c0 \uc54a\uace0 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4."]}),"\n",(0,a.jsxs)(n.p,{children:["TransactionSynchronizationManager.isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc \ud638\ucd9c \uc2dc currentTransactionReadOnly\ub77c\ub294 ",(0,a.jsx)(n.code,{children:"ThreadLocal"}),"\uc5d0 \uc124\uc815\ub41c \uac12\uc744 \ubc18\ud658\ud558\ub294\ub370 readOnly \uc124\uc815\uc774 \ub418\uba74 \uc774 \uac12\uc744 true\ub85c \uc124\uc815\ud55c\ub2e4. \ud558\uc9c0\ub9cc determineCurrentLookupKey\ub97c \ud638\ucd9c\ud558\uc5ec key \uac12\uc744 \uac00\uc838\uc624\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc774\ud6c4\uc5d0 \uc124\uc815\ub418\uae30 \ub54c\ubb38\uc5d0 determineCurrentLookupKey \uba54\uc11c\ub4dc\uc5d0\uc11c \ud56d\uc0c1 DataSourceType.SOURCE\uac00 \ubc18\ud658\ub418\uc5b4 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:"LazyConnectionDataSourceProxy\ub97c \uc124\uc815\ud558\ub294 \uacbd\uc6b0 \uc2e4\uc81c DataSource\ub97c \uc0ac\uc6a9\ud558\ub294 \uc2dc\uc810\uc5d0 \ucee4\ub125\uc158\uc744 \ud68d\ub4dd\ud574\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc124\uc815\ud55c\ub300\ub85c replica db\ub85c \uc870\ud68c \uc694\uccad\uc744 \ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="DataSourceConfiguration"',children:'@Configuration\npublic class DataSourceConfiguration {\n\n @Bean\n @Qualifier(SOURCE_NAME)\n @ConfigurationProperties(prefix = "spring.datasource.source")\n public DataSource sourceDataSource() {\n return DataSourceBuilder.create().build();\n }\n\n @Bean\n @Qualifier(REPLICA_NAME)\n @ConfigurationProperties(prefix = "spring.datasource.replica")\n public DataSource replicaDataSource() {\n return DataSourceBuilder.create().build();\n }\n\n @Bean\n @Qualifier(ROUTING_NAME)\n public DataSource routingDataSource(\n @Qualifier(SOURCE_NAME) DataSource sourceDataSource,\n @Qualifier(REPLICA_NAME) DataSource replicaDataSource\n ) {\n return RoutingDataSource.from(Map.of(\n DataSourceType.SOURCE, sourceDataSource,\n DataSourceType.REPLICA, replicaDataSource\n ));\n }\n\n @Bean\n @Primary\n public DataSource dataSource(\n @Qualifier(ROUTING_NAME) DataSource routingDataSource\n ) {\n return new LazyConnectionDataSourceProxy(routingDataSource);\n }\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"\ucd5c\uc885\uc801\uc73c\ub85c DataSource \ube48\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ud615\ud0dc\uac00 \ub41c\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n DSP[LazyConnectionDataSourceProxy] --\x3e RDS[RoutingDataSource]\n\tRDS --\x3e S[SourceDataSource]\n\tRDS --\x3e R[ReplicaDataSource]"}),"\n",(0,a.jsx)(n.h3,{id:"\ub3d9\uc791-\ud655\uc778",children:"\ub3d9\uc791 \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["\uac04\ub2e8\ud558\uac8c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\uc11c \uc124\uc815\ud55c\ub300\ub85c \ub3d9\uc791\uc774 \ub418\ub294\uc9c0 \ud655\uc778\ud574\ubcf4\uc558\ub2e4.",(0,a.jsx)(n.br,{}),"\n","save \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 ",(0,a.jsx)(n.code,{children:"@Transactional"}),", findById \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 ",(0,a.jsx)(n.code,{children:"@Transactional(readOnly = true)"}),"\uac00 \uc124\uc815\ub418\uc5b4\uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub85c\uadf8\ub97c \ud1b5\ud574 save\uc758 \uacbd\uc6b0 source db\ub85c findById\uc758 \uacbd\uc6b0 replica db\ub85c \uc694\uccad\uc744 \ud558\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="MemberServiceTest"',children:'@SpringBootTest\nclass MemberServiceTest {\n\n @Autowired\n private MemberService memberService;\n\n @Test\n void \uc0ac\uc6a9\uc790\ub97c_\uc800\uc7a5\ud55c\ub2e4() {\n // RoutingDataSource log: readOnly = false\n memberService.save("bbiac");\n }\n\n @Test\n void \uc0ac\uc6a9\uc790\ub97c_\uc870\ud68c\ud55c\ub2e4() {\n // RoutingDataSource log: readOnly = true\n assertThatThrownBy(() -> memberService.findById(MAX_VALUE))\n .isInstanceOf(NoSuchElementException.class);\n }\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"DB\uc5d0\uc11c\ub294 \ud655\uc778\ud558\ub824\uba74 root \uacc4\uc815\uc73c\ub85c \uc811\uc18d\ud55c \ud6c4 general log\ub97c \ud65c\uc131\ud654 \uc2dc\ud0a8\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SET GLOBAL log_output = 'table';\nSET GLOBAL general_log = 1;\n"})}),"\n",(0,a.jsxs)(n.p,{children:["general log\ub97c \ud65c\uc131\ud654 \ud55c \ud6c4 \uc77d\uae30 \uc804\uc6a9 \uba54\uc11c\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","server_id, \uc2e4\ud589\ud55c \ucffc\ub9ac\ubb38\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like '%select%';\n\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n| user_host | thread_id | server_id | convert(argument using utf8) |\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n| user[user] @ [172.25.0.1] | 277 | 2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n"})}),"\n",(0,a.jsx)(n.p,{children:"\ud655\uc778 \ud6c4 general log\ub97c \ube44\ud65c\uc131\ud654 \ud55c \ud6c4 \ube44\ud65c\uc131\ud654 \ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SET GLOBAL general_log = 0;\nSHOW VARIABLES LIKE '%general%';\n\n+------------------+---------------------------------+\n| Variable_name | Value |\n+------------------+---------------------------------+\n| general_log | OFF |\n| general_log_file | /var/lib/mysql/4b6b9db98290.log |\n+------------------+---------------------------------+\n"})}),"\n",(0,a.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(n.p,{children:["16\uc7a5 \ubcf5\uc81c, Real MySQL 8.0 - \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.1/en/replication.html",children:"Replication, MySQL Docs"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://huisam.tistory.com/entry/mysql-replication",children:"MySql - Master Slave Replication \uad6c\uc870 \ub9cc\ub4e4\uc5b4\ubcf4\uae30"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://cheese10yun.github.io/spring-transaction/",children:"Spring \ub808\ud50c\ub9ac\ucf00\uc774\uc158 \ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac \ubc29\uc2dd"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://github.com/kwon37xi/replication-datasource",children:"replication-datasource"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/pulse/simplified-guide-mysql-replication-docker-compose-rakesh-shekhawat/",children:"Simplified Guide to MySQL Replication with Docker Compose"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://www.daleseo.com/dockerfile/",children:"Dockerfile\uc5d0\uc11c \uc790\uc8fc \uc4f0\uc774\ub294 \uba85\ub839\uc5b4"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.1/en/change-replication-source-to.html",children:"CHANGE REPLICATION SOURCE TO Statement"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://kwonnam.pe.kr/wiki/springframework/lazyconnectiondatasourceproxy",children:"LazyConnectionDataSourceProxy"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://hudi.blog/database-replication-with-springboot-and-mysql/",children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ub808\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ud1b5\ud55c \ucffc\ub9ac \uc131\ub2a5 \uac1c\uc120 (feat. Mysql, SpringBoot)"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://chagokx2.tistory.com/100",children:"\ubd80\ud558 \ubd84\uc0b0\uc744 \uc704\ud55c MySQL Replication \uad6c\uc131 \ubc0f \ucffc\ub9ac \uc694\uccad \ubd84\uae30"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.docker.com/get-started/08_using_compose/",children:"Use Docker Compose, Docker"})]})]})}function h(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var a=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,a)}return r}function l(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var c=a.createContext({}),o=function(e){var n=a.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):l(l({},n),e)),r},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var r=e.components,t=e.mdxType,i=e.originalType,c=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=o(r),h=t,S=p["".concat(c,".").concat(h)]||p[h]||u[h]||i;return r?a.createElement(S,l(l({ref:n},d),{},{components:r})):a.createElement(S,l({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,r)=>{r.d(n,{Z:()=>l});r(67294);var a=r(86010);const t={tabItem:"tabItem_Ymn6"};var i=r(85893);function l(e){let{children:n,hidden:r,className:l}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,a.Z)(t.tabItem,l),hidden:r,children:n})}},74866:(e,n,r)=>{r.d(n,{Z:()=>R});var a=r(67294),t=r(86010),i=r(12466),l=r(16550),s=r(20469),c=r(91980),o=r(67392),u=r(50012);function d(e){return a.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:r}=e;return(0,a.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:r,attributes:a,default:t}}=e;return{value:n,label:r,attributes:a,default:t}}))}(r);return function(e){const n=(0,o.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,r])}function h(e){let{value:n,tabValues:r}=e;return r.some((e=>e.value===n))}function S(e){let{queryString:n=!1,groupId:r}=e;const t=(0,l.k6)(),i=function(e){let{queryString:n=!1,groupId:r}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!r)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return r??null}({queryString:n,groupId:r});return[(0,c._X)(i),(0,a.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(t.location.search);n.set(i,e),t.replace({...t.location,search:n.toString()})}),[i,t])]}function x(e){const{defaultValue:n,queryString:r=!1,groupId:t}=e,i=p(e),[l,c]=(0,a.useState)((()=>function(e){let{defaultValue:n,tabValues:r}=e;if(0===r.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:r}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${r.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const a=r.find((e=>e.default))??r[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:n,tabValues:i}))),[o,d]=S({queryString:r,groupId:t}),[x,m]=function(e){let{groupId:n}=e;const r=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,i]=(0,u.Nk)(r);return[t,(0,a.useCallback)((e=>{r&&i.set(e)}),[r,i])]}({groupId:t}),b=(()=>{const e=o??x;return h({value:e,tabValues:i})?e:null})();(0,s.Z)((()=>{b&&c(b)}),[b]);return{selectedValue:l,selectValue:(0,a.useCallback)((e=>{if(!h({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),d(e),m(e)}),[d,m,i]),tabValues:i}}var m=r(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var j=r(85893);function g(e){let{className:n,block:r,selectedValue:a,selectValue:l,tabValues:s}=e;const c=[],{blockElementScrollPositionUntilNextRender:o}=(0,i.o5)(),u=e=>{const n=e.currentTarget,r=c.indexOf(n),t=s[r].value;t!==a&&(o(n),l(t))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const r=c.indexOf(e.currentTarget)+1;n=c[r]??c[0];break}case"ArrowLeft":{const r=c.indexOf(e.currentTarget)-1;n=c[r]??c[c.length-1];break}}n?.focus()};return(0,j.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.Z)("tabs",{"tabs--block":r},n),children:s.map((e=>{let{value:n,label:r,attributes:i}=e;return(0,j.jsx)("li",{role:"tab",tabIndex:a===n?0:-1,"aria-selected":a===n,ref:e=>c.push(e),onKeyDown:d,onClick:u,...i,className:(0,t.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":a===n}),children:r??n},n)}))})}function _(e){let{lazy:n,children:r,selectedValue:t}=e;const i=(Array.isArray(r)?r:[r]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===t));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return(0,j.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function y(e){const n=x(e);return(0,j.jsxs)("div",{className:(0,t.Z)("tabs-container",b.tabList),children:[(0,j.jsx)(g,{...e,...n}),(0,j.jsx)(_,{...e,...n})]})}function R(e){const n=(0,m.Z)();return(0,j.jsx)(y,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2620],{43487:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>u,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>d});var a=r(85893),t=r(3905),i=r(74866),l=r(85162);const s={title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",slug:"db-replication",tags:["mysql","replication"]},c=void 0,o={permalink:"/db-replication",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",source:"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",description:"\ubcf5\uc81c(Replication)",date:"2023-08-22T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 22\uc77c",tags:[{label:"mysql",permalink:"/tags/mysql"},{label:"replication",permalink:"/tags/replication"}],readingTime:21,hasTruncateMarker:!1,authors:[],frontMatter:{title:"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30",slug:"db-replication",tags:["mysql","replication"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",permalink:"/woowacourse-level3-retrospective"},nextItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"}},u={authorsImageUrls:[]},d=[{value:"\ubcf5\uc81c(Replication)",id:"\ubcf5\uc81creplication",level:2},{value:"\ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720",id:"\ubcf5\uc81c\ub97c-\ud558\ub294-\uc774\uc720",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ud30c\uc77c-\uc704\uce58-\uae30\ubc18-\ubcf5\uc81c",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd\uc758-\ubb38\uc81c\uc810",level:3},{value:"\uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c",id:"\uae00\ub85c\ubc8c-\ud2b8\ub79c\uc7ad\uc158-\uc544\uc774\ub514gtid-\uae30\ubc18-\ubcf5\uc81c",level:3},{value:"\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0",id:"\ubcf5\uc81c-\ud1a0\ud3f4\ub85c\uc9c0",level:3},{value:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30",id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd-replication-\uad6c\uc131\ud558\uae30",level:2},{value:"MySQL \ud658\uacbd \uad6c\uc131",id:"mysql-\ud658\uacbd-\uad6c\uc131",level:3},{value:"\ub3c4\ucee4 \uc2e4\ud589",id:"\ub3c4\ucee4-\uc2e4\ud589",level:3},{value:"replication slave \uad8c\ud55c \uc124\uc815",id:"replication-slave-\uad8c\ud55c-\uc124\uc815",level:3},{value:"SOURCE DB \uc815\ubcf4 \ud655\uc778",id:"source-db-\uc815\ubcf4-\ud655\uc778",level:3},{value:"SOURCE ip \uc8fc\uc18c \ud655\uc778",id:"source-ip-\uc8fc\uc18c-\ud655\uc778",level:3},{value:"replica mysql \uc811\uc18d",id:"replica-mysql-\uc811\uc18d",level:3},{value:"replica \uc124\uc815",id:"replica-\uc124\uc815",level:3},{value:"\uc124\uc815 \ud655\uc778",id:"\uc124\uc815-\ud655\uc778",level:3},{value:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30",id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8\ub85c-db-\uc811\uadfc\ud558\uae30",level:2},{value:"Environment \uc124\uc815",id:"environment-\uc124\uc815",level:3},{value:"DataSourceType \uc124\uc815",id:"datasourcetype-\uc124\uc815",level:3},{value:"AbstractRoutingDataSource \uc124\uc815",id:"abstractroutingdatasource-\uc124\uc815",level:3},{value:"DataSource \uc124\uc815",id:"datasource-\uc124\uc815",level:3},{value:"\ub3d9\uc791 \ud655\uc778",id:"\ub3d9\uc791-\ud655\uc778",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function p(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"\ubcf5\uc81creplication",children:"\ubcf5\uc81c(Replication)"}),"\n",(0,a.jsxs)(n.p,{children:["\ud55c \uc11c\ubc84\uc5d0\uc11c \ub2e4\ub978 \uc11c\ubc84\ub85c \ub370\uc774\ud130\ub97c \ub3d9\uae30\ud654\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc6d0\ubcf8 \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Primary \ub610\ub294 Source \ub77c\uace0 \ubd80\ub974\uace0, \ubcf5\uc81c\ub41c \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Secondary \ub610\ub294 Replica \ub77c\uace0 \ubd80\ub978\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\ubcf5\uc81c\ub97c-\ud558\ub294-\uc774\uc720",children:"\ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"1. \uc2a4\ucf00\uc77c \uc544\uc6c3"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc0ac\uc6a9\uc790\uc758 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uac00\ud574\uc9c0\ub294 \ubd80\ud558\ub3c4 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc99d\uac00\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub97c \ucc98\ub9ac\ud558\uae30 \uc704\ud574 \ubcf5\uc81c\ub97c \ud1b5\ud55c \uc2a4\ucf00\uc77c \uc544\uc6c3\uc744 \uc801\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucffc\ub9ac\ub4e4\uc744 \uac01\uac01\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c \ubd84\uc0b0 \uc2dc\ud0ac \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"2. \ub370\uc774\ud130 \ubc31\uc5c5"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc2e4\uc81c \uc6b4\uc601\ub418\ub294 \uc11c\ube44\uc2a4\uac00 \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 DB\uc5d0\uc11c \ubc31\uc5c5\uc744 \uc9c4\ud589\ud558\ub294 \uacbd\uc6b0, \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc774 \uac00\uc9c0 \uc54a\ub3c4\ub85d \ubcf5\uc81c\ub97c \ud1b5\ud574 Replica \uc11c\ubc84\ub97c \uad6c\ucd95\ud558\uc5ec, Replica \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ub97c \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\uc73c\ub85c \uc601\ud5a5\uc744 \ucd5c\uc18c\ud654 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"3. \ub370\uc774\ud130 \ubd84\uc11d"})}),"\n",(0,a.jsxs)(n.p,{children:["\ubc31\uc5c5\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc7a1\ud558\uace0 \ubb34\uac70\uc6b4 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\uc758 \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc81c\ub97c \uc0ac\uc6a9\ud574 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"4. \ub370\uc774\ud130\uc758 \uc9c0\ub9ac\uc801 \ubd84\uc0b0"})}),"\n",(0,a.jsx)(n.p,{children:"\ube60\ub978 \uc751\ub2f5\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc11c\ubc84\uc5d0 \uac00\uae5d\uac8c \uc11c\ubc84\ub97c \uad6c\uc131\ud558\uac70\ub098, \uace0\uac00\uc6a9\uc131(High Availability)\uc744 \uc704\ud574\uc11c\ub3c4 \uc0ac\uc6a9\ub41c\ub2e4."}),"\n",(0,a.jsx)(n.h3,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ud30c\uc77c-\uc704\uce58-\uae30\ubc18-\ubcf5\uc81c",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c"}),"\n",(0,a.jsxs)(n.p,{children:["MySQL \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub85c\uadf8 \ud30c\uc77c\uc744 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub77c\uace0 \ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ud1b5\ud574 \ub370\uc774\ud130 \ubcc0\uacbd, \ud14c\uc774\ube14 \uad6c\uc870 \ubcc0\uacbd, \uacc4\uc815\uc774\ub098 \uad8c\ud55c \ubcc0\uacbd\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc800\uc7a5\ub41c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","MySQL\uc758 \ubcf5\uc81c\ub294 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. \uc774\ub97c Replica \uc11c\ubc84\ub85c \uc804\ub2ec\ud558\uace0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n\tsubgraph Replica\n\t\tdirection TB\n\t\tIO[Replication I/O thread] -- save --\x3e RL[Relay Log]\n\t\tSQL[Replication SQL Thread] -- read --\x3e RL\n\tend\n\n\tsubgraph Source\n\t\tdirection TB\n\t\tBLD[Binary Log Dump Thread] -- Send Binary Log Dump--\x3e IO\n\tend\n"}),"\n",(0,a.jsx)(n.admonition,{title:"\uc2a4\ub808\ub4dc\ubcc4 \uc5ed\ud560",type:"note",children:(0,a.jsxs)(n.p,{children:["Binary Log Dump Thread: \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc758 \ub0b4\uc6a9\uc744 Replica \uc11c\ubc84\ub85c \uc804\ub2ec",(0,a.jsx)(n.br,{}),"\n","Replication I/O Thread: Binary \ub85c\uadf8 \uc774\ubca4\ud2b8\ub97c \uac00\uc838\uc640 \ub85c\uceec \uc11c\ubc84\uc758 \ud30c\uc77c(Relay Log)\ub85c \uc800\uc7a5",(0,a.jsx)(n.br,{}),"\n","Replication SQL Thread: \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc774\ubca4\ud2b8\ub97c \uc77d\uace0 \uc2e4\ud589"]})}),"\n",(0,a.jsx)(n.h3,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd\uc758-\ubb38\uc81c\uc810",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810"}),"\n",(0,a.jsxs)(n.p,{children:["\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc740 \uc11c\ubc84\uc5d0 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0 \ubcc0\uacbd\uc774 \uae4c\ub2e4\ub86d\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud1a0\ud3f4\ub85c\uc9c0\ub780 \ub124\ud2b8\uc6cc\ud06c\uc758 \uc694\uc18c\ub4e4\uc744 \ubb3c\ub9ac\uc801\uc73c\ub85c \uc5f0\uacb0\ud574 \ub193\uc740 \uac83, \ub610\ub294 \uadf8 \uc5f0\uacb0 \ubc29\uc2dd\uc744 \ub9d0\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph TD\n\tA[A binary-log:300] --\x3e B[B Binary-log:300]\n\tA[A binary-log:300] --\x3e C[C Binary-log:200]"}),"\n",(0,a.jsx)(n.p,{children:"\uc704\uc640 \uac19\uc774 Source \uc11c\ubc84, Replica 2\ub300\uac00 \uc874\uc7ac\ud558\uace0, C \uc11c\ubc84\uc5d0 \ubcf5\uc81c \uc9c0\uc5f0\uc774 \ub418\uc5c8\uc744 \ub54c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph TD\n\tA[A binary-log:300]\n\tB[B Binary-log:300] --\x3e C[C Binary-log:200 \ubb38\uc81c \ubc1c\uc0dd]"}),"\n",(0,a.jsxs)(n.p,{children:["A \uc11c\ubc84\uc5d0\uc11c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 B \uc11c\ubc84\ub97c Source \uc11c\ubc84\ub85c \uc2b9\uaca9\ud558\uace0, C\uc5d0\uac8c \uc870\ud68c \ucffc\ub9ac\ub97c \ubd84\uc0b0\uc2dc\ud0a8\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\uc9c0\ub9cc \uc5ec\uae30\uc11c C \uc11c\ubc84\uc5d0\ub294 A \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\uac00 \uc548\ub418\uc5c8\uc73c\ub2c8 \uc870\ud68c \uc2dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub4a4\ub2a6\uac8c B \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\ub97c \ud558\ub824\uace0 \ud574\ub3c4, \uc5b4\ub5a4 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8, \uc5b4\ub5a4 \uc704\uce58\uc640 \ub3d9\uae30\ud654\ud574\uc57c\ud558\ub294\uc9c0 \uc54c\uae30 \uc5b4\ub835\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"\uae00\ub85c\ubc8c-\ud2b8\ub79c\uc7ad\uc158-\uc544\uc774\ub514gtid-\uae30\ubc18-\ubcf5\uc81c",children:"\uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c"}),"\n",(0,a.jsxs)(n.p,{children:["GTID \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ubc1c\uc0dd\ud55c \uc774\ubca4\ud2b8\uc5d0 \uace0\uc720\ud55c \uc2dd\ubcc4\uac12\uc744 \ubd80\uc5ec\ud55c\ub2e4\uba74, \ub3d9\uae30\ud654\uc5d0 \ub300\ud55c \ubb38\uc81c\ub97c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc704\uc758 \uc608\uc2dc\uc640 \uac19\uc774 \ubcf5\uc81c \uc9c0\uc5f0\uacfc \ud568\uaed8 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ud574\ub3c4 \ud2b9\uc815 GTID \ubd80\ud130 \ubcf5\uc81c\ub97c \uc7ac\uac1c\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,a.jsx)(n.admonition,{title:"GTID",type:"note",children:(0,a.jsxs)(n.p,{children:["\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\uc5d0 \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \uc11c\ubc84\uc5d0\uc11c \uace0\uc720\ud558\ub3c4\ub85d \uac01 \uc774\ubca4\ud2b8\uc5d0 \ubd80\uc5ec\ub41c \uc2dd\ubcc4\uac12",(0,a.jsx)(n.br,{}),"\n","[source_id]:[transaction_id]\ub85c \uad6c\uc131\ub418\uba70, source_id\ub294 \uc11c\ubc84\ub97c \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc774\uace0 transaction_id\ub294 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc73c\ub85c 1\uc529 \uc99d\uac00\ud558\ub294 \ud615\ud0dc\ub85c \ubc1c\uae09\ub41c\ub2e4."]})}),"\n",(0,a.jsx)(n.h3,{id:"\ubcf5\uc81c-\ud1a0\ud3f4\ub85c\uc9c0",children:"\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["\uac00\uc7a5 \uac04\ub2e8\ud55c \uad6c\uc131\uc73c\ub85c \uc81c\uc77c \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","replica \uc11c\ubc84\ub97c \uc77d\uae30 \uc804\uc6a9, \uc608\ube44 \uc11c\ubc84, \ubc31\uc5c5 \uc6a9\ub3c4\ub85c \ub9ce\uc774 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R\n S[Source] --\x3e R[Replica]"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uba40\ud2f0 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["2\uac1c\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud558\ub098\uc758 replica\ub294 \uc608\ube44 \uc6a9\ub3c4\ub85c \ub0a8\uaca8\ub450\ub294 \ud615\ud0dc\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ucd94\ud6c4\uc5d0 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 \uc608\ube44 \uc6a9\ub3c4\uc758 replica\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c \uc77d\uae30 \uc694\uccad\uc758 \ubd80\ud558 \ubd84\uc0b0\uc744 \ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R1\n S[Source] --\x3e R1[Replica1]\n S --\x3e R2[Replica2]"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uccb4\uc778 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["replica \uc11c\ubc84\uac00 \ub9ce\uc740 \uacbd\uc6b0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \uc804\ub2ec\ud558\ub294 \uc791\uc5c5 \uc790\uccb4\uac00 \ubd80\ud558\uac00 \ub420 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c 1:M",":M"," \uad6c\uc870\ub85c \uccb4\uc778 \ubcf5\uc81c \uad6c\uc131\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\n W -- \uc77d\uae30 --\x3e R1\n S[Source] --\x3e R1[Replica1]\n S --\x3e R2[Replica2]\n S --\x3e R3[Replica3]\n\n R3 --\x3e R3-1[Replica 3-1]\n R3 --\x3e R3-2[Replica 3-2]\n\n B[Batch Server] --\x3e R3-2"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\ub4c0\uc5bc \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["2\uac1c\uc758 MySQL \uc11c\ubc84 \ubaa8\ub450 \uc77d\uae30\uc640 \uc4f0\uae30\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d \ud558\ub294 \uad6c\uc131\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uac01 \uc11c\ubc84\uc5d0\uc11c \ubcc0\uacbd\ub41c \ub370\uc774\ud130\ub294 \ub2e4\ub978 \uc11c\ubc84\uc5d0 \ubc18\uc601\ub41c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ubaa9\uc801\uc5d0 \ub530\ub77c ACTIVE-ACTIVE \ud615\ud0dc \ub610\ub294 ACTIVE-PASSIVE \ud615\ud0dc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","ACTIVE-PASSIVE \ud615\ud0dc\uc778 \uacbd\uc6b0 \uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131\uacfc \ub3d9\uc77c\ud574\ubcf4\uc774\uc9c0\ub9cc, ACTIVE \uc11c\ubc84\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uba74 \uc124\uc815\uc758 \ubcc0\uacbd\uc5c6\uc774 PASSIVE \uc11c\ubc84\ub85c \uc4f0\uae30 \uc791\uc5c5\uc744 \uc804\ud658\ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc774 \uc7a5\uc810\uc774\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR1\n W -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR2\n SR1[Source/Replica 1] --\x3e SR2[Source/Replica 2]"}),"\n",(0,a.jsx)(n.admonition,{title:"ACTIVE-ACTIVE, ACTIVE-PASSIVE",type:"note",children:(0,a.jsxs)(n.p,{children:["ACTIVE-ACTIVE: 2\uac1c\uc758 \uc11c\ubc84 \ubaa8\ub450 \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc",(0,a.jsx)(n.br,{}),"\n","ACTIVE-PASSIVE: \ud558\ub098\uc758 \uc11c\ubc84\uc5d0\uc11c\ub9cc \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc"]})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"\uba40\ud2f0 \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131"})}),"\n",(0,a.jsxs)(n.p,{children:["\uc5ec\ub7ec\uac1c\uc758 source \uc11c\ubc84\uc640 \ud558\ub098\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \uad6c\uc131\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc774\ub294 source \uc11c\ubc84\uc758 \ub370\uc774\ud130\ub97c \ud55c \uacf3\uc5d0 \ubc31\uc5c5\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9, \uc5ec\ub7ec \uc11c\ubc84\uc5d0 \uc874\uc7ac\ud558\ub294 \ub370\uc774\ud130\ub97c \ud1b5\ud569, \uc0e4\ub529\ub418\uc5b4\uc788\ub294 \ud14c\uc774\ube14 \ub370\uc774\ud130\ub97c \ud1b5\ud569\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n S1[Source 1] --\x3e R[Replica]\n S2[Source 2] --\x3e R"}),"\n",(0,a.jsx)(n.h2,{id:"\ubc14\uc774\ub108\ub9ac-\ub85c\uadf8-\ubc29\uc2dd-replication-\uad6c\uc131\ud558\uae30",children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30"}),"\n",(0,a.jsxs)(n.p,{children:["mysql 2\ub300\ub97c \uc774\uc6a9\ud558\uc5ec replication\uc744 \uad6c\uc131\ud558\uace0, spring boot application\uc73c\ub85c source, replica \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\ubcf4\ub294 \uc608\uc81c\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://github.com/bbiac/db-replication",children:"https://github.com/bbiac/db-replication"})]}),"\n",(0,a.jsx)(n.h3,{id:"mysql-\ud658\uacbd-\uad6c\uc131",children:"MySQL \ud658\uacbd \uad6c\uc131"}),"\n",(0,a.jsxs)(n.p,{children:["MySQL \ubc84\uc804\uc740 8.1\uc744 \uc0ac\uc6a9\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","13306, 13307 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud574\uc11c MySQL \uc11c\ubc84 2\ub300\ub97c \ub744\uc6e0\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub610\ud55c \uc0ac\uc2e4 IP \ub300\uc5ed\uc73c\ub85c \ud1b5\uc2e0\ud560 \uc218 \uc788\ub3c4\ub85d \ucee4\uc2a4\ud140 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud588\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yml",children:"version: '3.8'\n\nservices:\n source:\n platform: linux/x86_64\n image: mysql:latest\n restart: always\n container_name: mysql-source\n environment:\n TZ: 'Asia/Seoul'\n MYSQL_DATABASE: 'db'\n MYSQL_USER: 'user'\n MYSQL_PASSWORD: 'password'\n MYSQL_ROOT_PASSWORD: 'password'\n ports:\n - \"13306:3306\"\n volumes:\n - db-source:/var/lib/mysql\n - db-source:/var/lib/mysql-files\n - ./docker/source.cnf:/etc/mysql/my.cnf\n networks:\n - mysql_network\n\n replica:\n platform: linux/x86_64\n image: mysql:latest\n restart: always\n container_name: mysql-replica\n environment:\n TZ: 'Asia/Seoul'\n MYSQL_DATABASE: 'db'\n MYSQL_USER: 'user'\n MYSQL_PASSWORD: 'password'\n MYSQL_ROOT_PASSWORD: 'password'\n ports:\n - \"13307:3306\"\n volumes:\n - db-replica:/var/lib/mysql\n - db-replica:/var/lib/mysql-files\n - ./docker/replica.cnf:/etc/mysql/my.cnf\n networks:\n - mysql_network\n\nvolumes:\n db-source:\n db-replica:\n\nnetworks:\n mysql_network:\n driver: bridge\n"})}),"\n",(0,a.jsx)(n.p,{children:"\ub610\ud55c source, replica \uac01\uac01 \ub2e4\uc74c\uacfc \uac19\uc774 db \uc124\uc815\uc744 \ud588\ub2e4."}),"\n",(0,a.jsxs)(n.table,{children:[(0,a.jsx)(n.thead,{children:(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.th,{children:"\uc124\uc815"}),(0,a.jsx)(n.th,{children:"\uc124\uba85"})]})}),(0,a.jsxs)(n.tbody,{children:[(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"server_id"}),(0,a.jsx)(n.td,{children:"\uac01\uac01\uc758 mysql \ub9c8\ub2e4 \uace0\uc720\ud55c \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"log_bin"}),(0,a.jsx)(n.td,{children:"\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815\uc73c\ub85c \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 /var/lib/mysql \uc544\ub798 \ud574\ub2f9 log_bin\uc5d0 \uc124\uc815\ub41c \uac12\uc73c\ub85c \ub85c\uadf8\uac00 \uc0dd\uc131\ub41c\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"sync_binlog"}),(0,a.jsx)(n.td,{children:"N\uac1c\uc758 \ud2b8\ub79c\uc7ad\uc158 \ub2f9 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ub514\uc2a4\ud06c\uc640 \ub3d9\uae30\ud654 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d \ud55c\ub2e4.\xa01\uc740 \uae30\ubcf8\uac12\uc73c\ub85c \uc548\uc815\uc801\uc774\uc9c0\ub9cc, \uac00\uc7a5 \ub290\ub9ac\ub2e4."})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"relay_log"}),(0,a.jsx)(n.td,{children:"\ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"relay_log_purge"}),(0,a.jsx)(n.td,{children:"\ud544\uc694 \uc5c6\ub294 \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \uc0ad\uc81c\ud558\ub294 \uc635\uc158"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"read_only"}),(0,a.jsx)(n.td,{children:"\uc77d\uae30 \uc804\uc6a9 \uc124\uc815"})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"log_replica_updates"}),(0,a.jsx)(n.td,{children:"Replication SQL Thread\ub85c \uc778\ud574 \uc2e4\ud589\ub418\ub294 \uc815\ubcf4\ub97c \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc5d0 \uae30\ub85d \ucd94\ud6c4\uc5d0 \uc18c\uc2a4 \uc11c\ubc84\ub85c \uc2b9\uaca9\ub418\ub294 \uacbd\uc6b0\ub97c \uace0\ub824\ud558\uba74 \uc124\uc815\ud558\ub294 \uac83\uc774 \uc88b\ub2e4."})]})]})]}),"\n","\n","\n",(0,a.jsxs)(i.Z,{children:[(0,a.jsx)(l.Z,{value:"Source",label:"Source",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-cnf",metastring:'title="/docker/source.cnf"',children:"[mysqld]\nserver_id=1\nlog_bin=mysql-bin\nsync_binlog=1\n"})})}),(0,a.jsx)(l.Z,{value:"Replica",label:"Replica",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-cnf",metastring:'title="/docker/replica.cnf"',children:"[mysqld]\nserver_id=2\nrelay_log=mysql-relay-bin\nrelay_log_purge=ON\nread_only\nlog_replica_updates\n"})})})]}),"\n",(0,a.jsx)(n.h3,{id:"\ub3c4\ucee4-\uc2e4\ud589",children:"\ub3c4\ucee4 \uc2e4\ud589"}),"\n",(0,a.jsxs)(n.p,{children:["docker-compose up \uba85\ub839\uc5b4\ub85c docker-compose \uc124\uc815\uc73c\ub85c docker\ub97c \ub744\uc6b4\ub2e4.",(0,a.jsx)(n.br,{}),"\n","-d \uc635\uc158\uc744 \ubd99\uc774\uba74 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ubaa8\ub4dc\ub85c \uc2e4\ud589\ub41c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"docker-compose up -d\n"})}),"\n",(0,a.jsx)(n.h3,{id:"replication-slave-\uad8c\ud55c-\uc124\uc815",children:"replication slave \uad8c\ud55c \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["REPLICATION SLAVE \uad8c\ud55c\uc774 \uc124\uc815\ub418\uc5b4 \uc788\uc5b4\uc57c replica \uc11c\ubc84\uc5d0\uc11c source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec \ub85c\uadf8\ub97c \uc77d\uc5b4\uc62c \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec user \uacc4\uc815\uc5d0 \ud574\ub2f9 \uad8c\ud55c\uc744 \uc124\uc815\ud574\uc900\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:"SOURCE \uc811\uc18d"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker exec -it mysql-source mysql -u root -p\n"})}),"\n",(0,a.jsx)(n.p,{children:"user \uacc4\uc815\uc5d0 REPLICATION SLAVE \uad8c\ud55c \ucd94\uac00"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"GRANT REPLICATION SLAVE ON *.* TO 'user'@'%';\nFLUSH PRIVILEGES;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"source-db-\uc815\ubcf4-\ud655\uc778",children:"SOURCE DB \uc815\ubcf4 \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["replica \uc124\uc815\uc5d0 \ud544\uc694\ud55c source db\uc758 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c\uba85\uacfc Position\uc744 \ud655\uc778\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","Position \uac12\uc740 \uc2e4\uc81c \ud30c\uc77c\uc758 \ubc14\uc774\ud2b8 \uc218\ub97c \uc758\ubbf8\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud655\uc778\ud55c File(SOURCE_LOG_FILE)\uacfc Position(SOURCE_LOG_POS) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"SHOW MASTER STATUS;\n\n+------------------+----------+--------------+------------------+-------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |\n+------------------+----------+--------------+------------------+-------------------+\n| mysql-bin.000003 | 1082 | | | |\n+------------------+----------+--------------+------------------+-------------------+\n"})}),"\n",(0,a.jsx)(n.h3,{id:"source-ip-\uc8fc\uc18c-\ud655\uc778",children:"SOURCE ip \uc8fc\uc18c \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["docker inspect -f \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ud574\ub2f9 \ucee8\ud14c\uc774\ub108\uc758 \uc138\ubd80 \uc815\ubcf4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud574 docker-compose \ud30c\uc77c\uc5d0 \uc124\uc815\ud574\ub454 mysql_network\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc124 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'docker inspect -f "{{with index .NetworkSettings.Networks \\"db-replication_mysql_network\\"}}{{.IPAddress}}{{end}}" mysql-source\n'})}),"\n",(0,a.jsxs)(n.p,{children:["ip \uc8fc\uc18c\uac00 \ub098\uc624\uc9c0 \uc54a\ub294 \uacbd\uc6b0 docker inspect mysql-source\ub85c \ud655\uc778\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ud655\uc778\ud55c IP\uc8fc\uc18c(SOURCE_HOST) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.h3,{id:"replica-mysql-\uc811\uc18d",children:"replica mysql \uc811\uc18d"}),"\n",(0,a.jsx)(n.p,{children:"source db\uc5d0 \uc811\uc18d\ud588\ub358 \ubc29\ubc95\uacfc \ub3d9\uc77c\ud558\uac8c replica db\uc5d0 \uc811\uc18d\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker exec -it mysql-replica mysql -u root -p\n"})}),"\n",(0,a.jsx)(n.h3,{id:"replica-\uc124\uc815",children:"replica \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\uc774\uc804\uc5d0 source db\uc5d0\uc11c \uc5bb\uc5c8\ub358 \uc815\ubcf4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc5ec replica \uc124\uc815\uc744 \uc9c4\ud589\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc2e4\uc81c DB \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc73c\ub85c source DB\uc758 \ud30c\uc77c\uc744 \ubcf5\uc81c\ud574\uc57c\ud558\uc9c0\ub9cc \ud604\uc7ac \ubcf5\uc81c\ud560 \ub370\uc774\ud130\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ubd80\ubd84\uc740 \uc0dd\ub7b5\ud588\ub2e4.",(0,a.jsx)(n.br,{}),"\n","SOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS \ub97c \uc801\uc808\ud788 \ubcc0\uacbd\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"STOP REPLICA;\n\nCHANGE REPLICATION SOURCE TO \nSOURCE_HOST='172.29.0.2', \nSOURCE_USER='user', \nSOURCE_PASSWORD='password', \nSOURCE_LOG_FILE='mysql-bin.000001', \nSOURCE_LOG_POS=0, \nGET_SOURCE_PUBLIC_KEY=1;\n\nSTART REPLICA;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"\uc124\uc815-\ud655\uc778",children:"\uc124\uc815 \ud655\uc778"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-mysql",children:"SHOW REPLICA STATUS;\n\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n| Waiting for source to send event | 172.25.0.3 | user | 3306 | 60 | mysql-bin.000003 | 1082 | mysql-relay-bin.000002 | 868 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 1082 | 1078 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | | | 1 | |\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\n"})}),"\n",(0,a.jsx)(n.p,{children:"Replica_IO_Running, Replica_SQL_Running \uac12\uc774 YES\ub77c\uba74 \uc815\uc0c1\uc801\uc73c\ub85c replication \uad6c\uc131\uc774 \uc644\ub8cc\ub41c \uac83\uc774\ub2e4."}),"\n",(0,a.jsxs)(n.p,{children:["\uc124\uc815\uc744 \ub9c8\uce5c \ud6c4 source db\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 create table \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","replica db\uc5d0 \ub3d9\uc77c\ud55c member table\uc774 \uc0dd\uc131\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE member\n(\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\n name VARCHAR(255)\n);\n"})}),"\n",(0,a.jsx)(n.h2,{id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8\ub85c-db-\uc811\uadfc\ud558\uae30",children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30"}),"\n",(0,a.jsx)(n.p,{children:"\uc77c\ubc18\uc801\uc778 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 source, \uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158\uc778 \uacbd\uc6b0 replica\ub85c \uc694\uccad\uc774 \uac00\ub3c4\ub85d \uad6c\uc131\ud574\ubcf4\uc790."}),"\n",(0,a.jsx)(n.h3,{id:"environment-\uc124\uc815",children:"Environment \uc124\uc815"}),"\n",(0,a.jsx)(n.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 source, replica\ub85c \uad6c\ubd84\ud558\uc5ec \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yml",metastring:'title="application.yml"',children:"spring:\n datasource:\n source:\n username: user\n password: password\n driver-class-name: com.mysql.cj.jdbc.Driver\n jdbc-url: jdbc:mysql://localhost:13306/db\n replica:\n username: user\n password: password\n driver-class-name: com.mysql.cj.jdbc.Driver\n jdbc-url: jdbc:mysql://localhost:13307/db\n"})}),"\n",(0,a.jsx)(n.h3,{id:"datasourcetype-\uc124\uc815",children:"DataSourceType \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\ub2e8\uc21c \ubb38\uc790\uc5f4\ub85c\ub3c4 \uad6c\ubd84\ud560 \uc218 \uc788\uc9c0\ub9cc, enum\uc744 \uc774\uc6a9\ud574\uc11c \ud2b8\ub79c\uc7ad\uc158\uc744 \uad6c\ubd84\ud558\ub3c4\ub85d \uc0dd\uc131\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","Key\ub294 \ucd94\ud6c4\uc5d0 \ube48 \uc124\uc815\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="DataSourceType"',children:'public enum DataSourceType {\n SOURCE(SOURCE_NAME),\n REPLICA(REPLICA_NAME),\n ;\n\n private final String key;\n\n DataSourceType(String key) {\n this.key = key;\n }\n\n public static class Key {\n public static final String ROUTING_NAME = "ROUTING";\n public static final String SOURCE_NAME = "SOURCE";\n public static final String REPLICA_NAME = "REPLICA";\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"abstractroutingdatasource-\uc124\uc815",children:"AbstractRoutingDataSource \uc124\uc815"}),"\n",(0,a.jsx)(n.p,{children:"\uc2a4\ud504\ub9c1\uc774 \uc9c0\uc6d0\ud574\uc8fc\ub294 AbstractRoutingDataSource\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSource\ub97c \ud5a5\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsxs)(n.p,{children:["\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub294 ",(0,a.jsx)(n.code,{children:"Map"}),"\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\uc744 \ubc1b\uc544 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"setDefaultTargetDataSource: \uae30\ubcf8 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"setTargetDataSources: \ub9f5 \ud615\ud0dc\ub85c \ubc1b\uc740 \ub370\uc774\ud130 \uc18c\uc2a4 \uac12\ub4e4\uc744 \uc124\uc815\ud55c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"determineCurrentLookupKey\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \ud2b8\ub79c\uc7ad\uc158\uc774 \uc77d\uae30 \uc804\uc6a9\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(n.li,{children:"DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uace0, \ubc18\ud658\ud55c \uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ub370\uc774\ud130 \uc18c\uc2a4\uac00 \uc0ac\uc6a9\ub41c\ub2e4."}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="RoutingDataSource"',children:'public class RoutingDataSource extends AbstractRoutingDataSource {\n\n private final Logger log = LoggerFactory.getLogger(getClass());\n\n public static RoutingDataSource from(Map dataSources) {\n RoutingDataSource routingDataSource = new RoutingDataSource();\n routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));\n routingDataSource.setTargetDataSources(dataSources);\n return routingDataSource;\n }\n\n @Override\n protected Object determineCurrentLookupKey() {\n boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();\n\n if (readOnly) {\n log.info("readOnly = true, request to replica");\n return DataSourceType.REPLICA;\n }\n log.info("readOnly = false, request to source");\n return DataSourceType.SOURCE;\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"datasource-\uc124\uc815",children:"DataSource \uc124\uc815"}),"\n",(0,a.jsxs)(n.p,{children:["\uc704\uc5d0\uc11c\ubd80\ud130 \uc21c\uc11c\ub300\ub85c Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy \uc124\uc815\uc774\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\uc2a4\ud504\ub9c1\uc740 \ud2b8\ub79c\uc7ad\uc158 \uc2dc\uc791\uc2dc\uc5d0 \ucee4\ub125\uc158\uc758 \uc0ac\uc6a9\uc5ec\ubd80\uc640 \uc0c1\uad00\uc5c6\uc774 \ucee4\ub125\uc158\uc744 \ud655\ubcf4\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c readOnly \ud2b8\ub79c\uc7ad\uc158\uc774 \uc124\uc815\ub41c \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ubbf8\ub9ac \ud655\ubcf4\ub41c \ucee4\ub125\uc158\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 replica db\ub85c \uc694\uccad\uc744 \ud558\uc9c0 \uc54a\uace0 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4."]}),"\n",(0,a.jsxs)(n.p,{children:["TransactionSynchronizationManager.isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc \ud638\ucd9c \uc2dc currentTransactionReadOnly\ub77c\ub294 ",(0,a.jsx)(n.code,{children:"ThreadLocal"}),"\uc5d0 \uc124\uc815\ub41c \uac12\uc744 \ubc18\ud658\ud558\ub294\ub370 readOnly \uc124\uc815\uc774 \ub418\uba74 \uc774 \uac12\uc744 true\ub85c \uc124\uc815\ud55c\ub2e4. \ud558\uc9c0\ub9cc determineCurrentLookupKey\ub97c \ud638\ucd9c\ud558\uc5ec key \uac12\uc744 \uac00\uc838\uc624\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc774\ud6c4\uc5d0 \uc124\uc815\ub418\uae30 \ub54c\ubb38\uc5d0 determineCurrentLookupKey \uba54\uc11c\ub4dc\uc5d0\uc11c \ud56d\uc0c1 DataSourceType.SOURCE\uac00 \ubc18\ud658\ub418\uc5b4 source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4."]}),"\n",(0,a.jsx)(n.p,{children:"LazyConnectionDataSourceProxy\ub97c \uc124\uc815\ud558\ub294 \uacbd\uc6b0 \uc2e4\uc81c DataSource\ub97c \uc0ac\uc6a9\ud558\ub294 \uc2dc\uc810\uc5d0 \ucee4\ub125\uc158\uc744 \ud68d\ub4dd\ud574\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc124\uc815\ud55c\ub300\ub85c replica db\ub85c \uc870\ud68c \uc694\uccad\uc744 \ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="DataSourceConfiguration"',children:'@Configuration\npublic class DataSourceConfiguration {\n\n @Bean\n @Qualifier(SOURCE_NAME)\n @ConfigurationProperties(prefix = "spring.datasource.source")\n public DataSource sourceDataSource() {\n return DataSourceBuilder.create().build();\n }\n\n @Bean\n @Qualifier(REPLICA_NAME)\n @ConfigurationProperties(prefix = "spring.datasource.replica")\n public DataSource replicaDataSource() {\n return DataSourceBuilder.create().build();\n }\n\n @Bean\n @Qualifier(ROUTING_NAME)\n public DataSource routingDataSource(\n @Qualifier(SOURCE_NAME) DataSource sourceDataSource,\n @Qualifier(REPLICA_NAME) DataSource replicaDataSource\n ) {\n return RoutingDataSource.from(Map.of(\n DataSourceType.SOURCE, sourceDataSource,\n DataSourceType.REPLICA, replicaDataSource\n ));\n }\n\n @Bean\n @Primary\n public DataSource dataSource(\n @Qualifier(ROUTING_NAME) DataSource routingDataSource\n ) {\n return new LazyConnectionDataSourceProxy(routingDataSource);\n }\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"\ucd5c\uc885\uc801\uc73c\ub85c DataSource \ube48\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ud615\ud0dc\uac00 \ub41c\ub2e4."}),"\n",(0,a.jsx)(n.mermaid,{value:"graph LR\n DSP[LazyConnectionDataSourceProxy] --\x3e RDS[RoutingDataSource]\n\tRDS --\x3e S[SourceDataSource]\n\tRDS --\x3e R[ReplicaDataSource]"}),"\n",(0,a.jsx)(n.h3,{id:"\ub3d9\uc791-\ud655\uc778",children:"\ub3d9\uc791 \ud655\uc778"}),"\n",(0,a.jsxs)(n.p,{children:["\uac04\ub2e8\ud558\uac8c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\uc11c \uc124\uc815\ud55c\ub300\ub85c \ub3d9\uc791\uc774 \ub418\ub294\uc9c0 \ud655\uc778\ud574\ubcf4\uc558\ub2e4.",(0,a.jsx)(n.br,{}),"\n","save \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 ",(0,a.jsx)(n.code,{children:"@Transactional"}),", findById \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 ",(0,a.jsx)(n.code,{children:"@Transactional(readOnly = true)"}),"\uac00 \uc124\uc815\ub418\uc5b4\uc788\ub2e4.",(0,a.jsx)(n.br,{}),"\n","\ub85c\uadf8\ub97c \ud1b5\ud574 save\uc758 \uacbd\uc6b0 source db\ub85c findById\uc758 \uacbd\uc6b0 replica db\ub85c \uc694\uccad\uc744 \ud558\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",metastring:'title="MemberServiceTest"',children:'@SpringBootTest\nclass MemberServiceTest {\n\n @Autowired\n private MemberService memberService;\n\n @Test\n void \uc0ac\uc6a9\uc790\ub97c_\uc800\uc7a5\ud55c\ub2e4() {\n // RoutingDataSource log: readOnly = false\n memberService.save("bbiac");\n }\n\n @Test\n void \uc0ac\uc6a9\uc790\ub97c_\uc870\ud68c\ud55c\ub2e4() {\n // RoutingDataSource log: readOnly = true\n assertThatThrownBy(() -> memberService.findById(MAX_VALUE))\n .isInstanceOf(NoSuchElementException.class);\n }\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"DB\uc5d0\uc11c\ub294 \ud655\uc778\ud558\ub824\uba74 root \uacc4\uc815\uc73c\ub85c \uc811\uc18d\ud55c \ud6c4 general log\ub97c \ud65c\uc131\ud654 \uc2dc\ud0a8\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SET GLOBAL log_output = 'table';\nSET GLOBAL general_log = 1;\n"})}),"\n",(0,a.jsxs)(n.p,{children:["general log\ub97c \ud65c\uc131\ud654 \ud55c \ud6c4 \uc77d\uae30 \uc804\uc6a9 \uba54\uc11c\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4.",(0,a.jsx)(n.br,{}),"\n","server_id, \uc2e4\ud589\ud55c \ucffc\ub9ac\ubb38\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like '%select%';\n\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n| user_host | thread_id | server_id | convert(argument using utf8) |\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n| user[user] @ [172.25.0.1] | 277 | 2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\n"})}),"\n",(0,a.jsx)(n.p,{children:"\ud655\uc778 \ud6c4 general log\ub97c \ube44\ud65c\uc131\ud654 \ud55c \ud6c4 \ube44\ud65c\uc131\ud654 \ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SET GLOBAL general_log = 0;\nSHOW VARIABLES LIKE '%general%';\n\n+------------------+---------------------------------+\n| Variable_name | Value |\n+------------------+---------------------------------+\n| general_log | OFF |\n| general_log_file | /var/lib/mysql/4b6b9db98290.log |\n+------------------+---------------------------------+\n"})}),"\n",(0,a.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(n.p,{children:["16\uc7a5 \ubcf5\uc81c, Real MySQL 8.0 - \ubc31\uc740\ube48, \uc774\uc131\uc6b1",(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.1/en/replication.html",children:"Replication, MySQL Docs"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://huisam.tistory.com/entry/mysql-replication",children:"MySql - Master Slave Replication \uad6c\uc870 \ub9cc\ub4e4\uc5b4\ubcf4\uae30"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://cheese10yun.github.io/spring-transaction/",children:"Spring \ub808\ud50c\ub9ac\ucf00\uc774\uc158 \ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac \ubc29\uc2dd"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://github.com/kwon37xi/replication-datasource",children:"replication-datasource"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/pulse/simplified-guide-mysql-replication-docker-compose-rakesh-shekhawat/",children:"Simplified Guide to MySQL Replication with Docker Compose"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://www.daleseo.com/dockerfile/",children:"Dockerfile\uc5d0\uc11c \uc790\uc8fc \uc4f0\uc774\ub294 \uba85\ub839\uc5b4"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://dev.mysql.com/doc/refman/8.1/en/change-replication-source-to.html",children:"CHANGE REPLICATION SOURCE TO Statement"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://kwonnam.pe.kr/wiki/springframework/lazyconnectiondatasourceproxy",children:"LazyConnectionDataSourceProxy"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://hudi.blog/database-replication-with-springboot-and-mysql/",children:"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ub808\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ud1b5\ud55c \ucffc\ub9ac \uc131\ub2a5 \uac1c\uc120 (feat. Mysql, SpringBoot)"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://chagokx2.tistory.com/100",children:"\ubd80\ud558 \ubd84\uc0b0\uc744 \uc704\ud55c MySQL Replication \uad6c\uc131 \ubc0f \ucffc\ub9ac \uc694\uccad \ubd84\uae30"}),(0,a.jsx)(n.br,{}),"\n",(0,a.jsx)(n.a,{href:"https://docs.docker.com/get-started/08_using_compose/",children:"Use Docker Compose, Docker"})]})]})}function h(e={}){const{wrapper:n}={...(0,t.ah)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>o});var a=r(67294);function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,a)}return r}function l(e){for(var n=1;n=0||(t[r]=e[r]);return t}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(t[r]=e[r])}return t}var c=a.createContext({}),o=function(e){var n=a.useContext(c),r=n;return e&&(r="function"==typeof e?e(n):l(l({},n),e)),r},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var r=e.components,t=e.mdxType,i=e.originalType,c=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=o(r),h=t,S=p["".concat(c,".").concat(h)]||p[h]||u[h]||i;return r?a.createElement(S,l(l({ref:n},d),{},{components:r})):a.createElement(S,l({ref:n},d))}));d.displayName="MDXCreateElement"},85162:(e,n,r)=>{r.d(n,{Z:()=>l});r(67294);var a=r(86010);const t={tabItem:"tabItem_Ymn6"};var i=r(85893);function l(e){let{children:n,hidden:r,className:l}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,a.Z)(t.tabItem,l),hidden:r,children:n})}},74866:(e,n,r)=>{r.d(n,{Z:()=>R});var a=r(67294),t=r(86010),i=r(12466),l=r(16550),s=r(20469),c=r(91980),o=r(67392),u=r(50012);function d(e){return a.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function p(e){const{values:n,children:r}=e;return(0,a.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:r,attributes:a,default:t}}=e;return{value:n,label:r,attributes:a,default:t}}))}(r);return function(e){const n=(0,o.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,r])}function h(e){let{value:n,tabValues:r}=e;return r.some((e=>e.value===n))}function S(e){let{queryString:n=!1,groupId:r}=e;const t=(0,l.k6)(),i=function(e){let{queryString:n=!1,groupId:r}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!r)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return r??null}({queryString:n,groupId:r});return[(0,c._X)(i),(0,a.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(t.location.search);n.set(i,e),t.replace({...t.location,search:n.toString()})}),[i,t])]}function x(e){const{defaultValue:n,queryString:r=!1,groupId:t}=e,i=p(e),[l,c]=(0,a.useState)((()=>function(e){let{defaultValue:n,tabValues:r}=e;if(0===r.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!h({value:n,tabValues:r}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${r.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const a=r.find((e=>e.default))??r[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:n,tabValues:i}))),[o,d]=S({queryString:r,groupId:t}),[x,m]=function(e){let{groupId:n}=e;const r=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,i]=(0,u.Nk)(r);return[t,(0,a.useCallback)((e=>{r&&i.set(e)}),[r,i])]}({groupId:t}),b=(()=>{const e=o??x;return h({value:e,tabValues:i})?e:null})();(0,s.Z)((()=>{b&&c(b)}),[b]);return{selectedValue:l,selectValue:(0,a.useCallback)((e=>{if(!h({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);c(e),d(e),m(e)}),[d,m,i]),tabValues:i}}var m=r(72389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var j=r(85893);function g(e){let{className:n,block:r,selectedValue:a,selectValue:l,tabValues:s}=e;const c=[],{blockElementScrollPositionUntilNextRender:o}=(0,i.o5)(),u=e=>{const n=e.currentTarget,r=c.indexOf(n),t=s[r].value;t!==a&&(o(n),l(t))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const r=c.indexOf(e.currentTarget)+1;n=c[r]??c[0];break}case"ArrowLeft":{const r=c.indexOf(e.currentTarget)-1;n=c[r]??c[c.length-1];break}}n?.focus()};return(0,j.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.Z)("tabs",{"tabs--block":r},n),children:s.map((e=>{let{value:n,label:r,attributes:i}=e;return(0,j.jsx)("li",{role:"tab",tabIndex:a===n?0:-1,"aria-selected":a===n,ref:e=>c.push(e),onKeyDown:d,onClick:u,...i,className:(0,t.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":a===n}),children:r??n},n)}))})}function _(e){let{lazy:n,children:r,selectedValue:t}=e;const i=(Array.isArray(r)?r:[r]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===t));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return(0,j.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function y(e){const n=x(e);return(0,j.jsxs)("div",{className:(0,t.Z)("tabs-container",b.tabList),children:[(0,j.jsx)(g,{...e,...n}),(0,j.jsx)(_,{...e,...n})]})}function R(e){const n=(0,m.Z)();return(0,j.jsx)(y,{...e,children:d(e.children)},String(n))}}}]); \ No newline at end of file diff --git a/assets/js/f25de701.7bd01fad.js b/assets/js/f25de701.ca61418d.js similarity index 98% rename from assets/js/f25de701.7bd01fad.js rename to assets/js/f25de701.ca61418d.js index f5ff61f32..06c669168 100644 --- a/assets/js/f25de701.7bd01fad.js +++ b/assets/js/f25de701.ca61418d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2245],{45414:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var a=n(85893),c=n(3905);const r={title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"cloudwatch",tags:["cloudwatch","log","monitoring"]},s=void 0,l={permalink:"/cloudwatch",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",source:"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",description:"CloudWatch",date:"2023-08-17T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 17\uc77c",tags:[{label:"cloudwatch",permalink:"/tags/cloudwatch"},{label:"log",permalink:"/tags/log"},{label:"monitoring",permalink:"/tags/monitoring"}],readingTime:5.35,hasTruncateMarker:!1,authors:[],frontMatter:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"cloudwatch",tags:["cloudwatch","log","monitoring"]},unlisted:!1,prevItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",permalink:"/woowacourse-level3-retrospective"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",permalink:"/route-image-async-with-event"}},o={authorsImageUrls:[]},d=[{value:"CloudWatch",id:"cloudwatch",level:2},{value:"CloudWatch Metrics",id:"cloudwatch-metrics",level:2},{value:"CloudWatch Agent \uc124\uce58",id:"cloudwatch-agent-\uc124\uce58",level:2},{value:"IAM \uc5ed\ud560 \uc124\uc815",id:"iam-\uc5ed\ud560-\uc124\uc815",level:3},{value:"\uc124\uce58",id:"\uc124\uce58",level:3},{value:"Wizard",id:"wizard",level:3},{value:"\uc124\uc815 \ud30c\uc77c \uc801\uc6a9",id:"\uc124\uc815-\ud30c\uc77c-\uc801\uc6a9",level:3},{value:"types.db: no such file or directory \uc5d0\ub7ec",id:"typesdb-no-such-file-or-directory-\uc5d0\ub7ec",level:3},{value:"\uc9c0\ud45c \ud655\uc778",id:"\uc9c0\ud45c-\ud655\uc778",level:3},{value:"\ub85c\uadf8",id:"\ub85c\uadf8",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function i(e){const t={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h2,{id:"cloudwatch",children:"CloudWatch"}),"\n",(0,a.jsxs)(t.p,{children:["AWS \ub9ac\uc18c\uc2a4\uc640 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc9c0\ud45c\uc640 \ub85c\uadf8\uc5d0 \ub300\ud55c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc81c\uacf5\ud558\ub294 \uc11c\ube44\uc2a4\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc9c0\ud45c\ub97c \uac10\uc2dc\ud558\uc5ec \uc54c\ub9bc\uc744 \ubcf4\ub0b4\ub294 \uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ud504\ub9ac\ud2f0\uc5b4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \ub300\uc2dc\ubcf4\ub4dc\ub2f9 3$/M \uc758 \ube44\uc6a9\uc774 \uccad\uad6c\ub418\uace0, \uc9c0\ud45c\ub098 \ub85c\uadf8\uc758 \uc591\uc5d0 \ub530\ub77c \ube44\uc6a9\uc774 \ucd94\uac00\uc801\uc73c\ub85c \uccad\uad6c\ub41c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc694\uae08 \uc815\ubcf4\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \uc815\ubcf4\ub294 ",(0,a.jsx)(t.a,{href:"https://aws.amazon.com/ko/cloudwatch/pricing/",children:"\ub2e4\uc74c \ub9c1\ud06c"}),"\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.h2,{id:"cloudwatch-metrics",children:"CloudWatch Metrics"}),"\n",(0,a.jsxs)(t.p,{children:["\uae30\ubcf8\uc801\uc73c\ub85c 5\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc218\uc9d1\ub41c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc138\ubd80 \ubaa8\ub2c8\ud130\ub9c1(Detailed Monitoring)\uc744 \ud65c\uc131\ud654\ud558\uba74 1\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\ub97c \uc218\uc9d1\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub300\uc2dc\ubcf4\ub4dc\uc5d0\uc11c InstanceId\ub85c \uac80\uc0c9\ud558\uc5ec \uc218\uc9d1\ub41c \uc9c0\ud45c\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch1.png",src:n(86344).Z+"",width:"3214",height:"1636"})}),"\n",(0,a.jsx)(t.p,{children:"CPUUtilization, NetworkIn, NetworkOut\uacfc \uac19\uc740 \uae30\ubcf8\uc801\uc778 \uc9c0\ud45c\ub97c \uc81c\uacf5\ud558\uace0, \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud06c \uacf5\uac04\uacfc \uac19\uc740 \uc9c0\ud45c\ub97c \ud655\uc778\ud558\ub824\uba74 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\ub97c \uc124\uc815\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,a.jsx)(t.h2,{id:"cloudwatch-agent-\uc124\uce58",children:"CloudWatch Agent \uc124\uce58"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch Agent \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\uc640 \ub85c\uadf8\ub97c \uc218\uc9d1\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.h3,{id:"iam-\uc5ed\ud560-\uc124\uc815",children:"IAM \uc5ed\ud560 \uc124\uc815"}),"\n",(0,a.jsxs)(t.p,{children:["\uae30\ubcf8\uc801\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4\uac00 CloudWatchAgentServerPolicy\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","IAM \u2192 \uc5ed\ud560\uc5d0\uc11c \uc5ed\ud560 \uc0dd\uc131\uc744 \ud074\ub9ad\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch2.png",src:n(35939).Z+"",width:"2614",height:"1602"})}),"\n",(0,a.jsx)(t.p,{children:"CloudWatchAgentServerPolicy \uad8c\ud55c \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uace0, \uc801\ub2f9\ud55c \uc5ed\ud560 \uc774\ub984\uc744 \uc785\ub825\ud574\uc11c \uc5ed\ud560\uc744 \uc0dd\uc131\ud55c\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch3.png",src:n(5001).Z+"",width:"2650",height:"1616"})}),"\n",(0,a.jsxs)(t.p,{children:["EC2 \uc778\uc2a4\ud134\uc2a4 \ubaa9\ub85d\uc73c\ub85c \ub4e4\uc5b4\uac00\uc11c, CloudWatch Agent\ub97c \uc124\uce58\ud560 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud074\ub9ad\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc5d0\uc11c \uc774\uc804\uc5d0 \uc0dd\uc131\ud55c \uc5ed\ud560\uc744 \uc9c0\uc815\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch4.png",src:n(55693).Z+"",width:"1764",height:"800"})}),"\n",(0,a.jsx)(t.h3,{id:"\uc124\uce58",children:"\uc124\uce58"}),"\n",(0,a.jsx)(t.p,{children:"\ud658\uacbd\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,a.jsxs)(t.p,{children:["OS: ubuntu 22.04",(0,a.jsx)(t.br,{}),"\n","\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small (ARM64)"]}),"\n",(0,a.jsx)(t.p,{children:"\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uce58\ud55c\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb\nsudo dpkg -i -E ./amazon-cloudwatch-agent.deb\n"})}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html",children:"\uc0ac\uc6a9 \uc124\uba85\uc11c"}),"\uc5d0 \uac01 \uc778\uc2a4\ud134\uc2a4 \uc720\ud615\ub9c8\ub2e4 \ub2e4\uc6b4\ub85c\ub4dc \ub9c1\ud06c\uac00 \uc790\uc138\ud558\uac8c \uc548\ub0b4\ub418\uc5b4 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.h3,{id:"wizard",children:"Wizard"}),"\n",(0,a.jsxs)(t.p,{children:["CloudWatch Wizard\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uc124\uc815 \ud30c\uc77c \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub85c\uadf8\ub97c \uc218\uc9d1\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub294 \uacbd\uc6b0 Wizard \uc2e4\ud589 \uba85\ub839\uc5b4 \uc785\ub825 \uc804 log \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \ubcf5\uc0ac\ud574\ub450\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec Wizard\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard\n"})}),"\n",(0,a.jsxs)(t.p,{children:["\uc124\uc815\uc744 \uc9c4\ud589\ud558\ub2e4 \ubcf4\uba74 \uc124\uc815 \ud30c\uc77c\uc774 \uc5b4\ub5bb\uac8c \uad6c\uc131\ub420\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub85c\uadf8\ub97c \ucd94\uac00\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \uc785\ub825\ucc3d\uc774 \ub098\uc624\uba74 \uc900\ube44\ud574\ub480\ub358 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \uc785\ub825\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch5.png",src:n(41733).Z+"",width:"2320",height:"1328"})}),"\n",(0,a.jsx)(t.p,{children:"\uc911\uac04\uc5d0 SSM parameter store\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"Do you want to store the config in the SSM parameter store?\n1. yes\n2. no\n"})}),"\n",(0,a.jsxs)(t.p,{children:["\ucd94\uac00\uc801\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 2\ubc88\uc744 \uc120\ud0dd\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","Parameter Store \uad00\ub9ac\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc758 ",(0,a.jsx)(t.a,{href:"https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/",children:"\ubb38\uc11c"}),"\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac70 \uac19\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 ",(0,a.jsx)(t.code,{children:"/opt/aws/amazon-cloudwatch-agent/bin/config.json"})," \uc5d0 \uc124\uc815\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774 \uc800\uc7a5\ub41c\ub2e4."]}),"\n",(0,a.jsx)(t.h3,{id:"\uc124\uc815-\ud30c\uc77c-\uc801\uc6a9",children:"\uc124\uc815 \ud30c\uc77c \uc801\uc6a9"}),"\n",(0,a.jsxs)(t.p,{children:["\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uc815\ud30c\uc77c\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","file \ub4a4\uc5d0\ub294 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \uc808\ub300\uacbd\ub85c(\uc544\ub798 \uba85\ub839\uc5b4 \uae30\uc900 \uae30\ubcf8 \uc0dd\uc131 \uc704\uce58)\ub97c \uc785\ub825\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json\n"})}),"\n",(0,a.jsx)(t.h3,{id:"typesdb-no-such-file-or-directory-\uc5d0\ub7ec",children:"types.db: no such file or directory \uc5d0\ub7ec"}),"\n",(0,a.jsx)(t.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc740 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 types.db \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"Error running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory\n"})}),"\n",(0,a.jsx)(t.p,{children:"types.db \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo mkdir /usr/share/collectd\nsudo touch /usr/share/collectd/types.db\n"})}),"\n",(0,a.jsx)(t.h3,{id:"\uc9c0\ud45c-\ud655\uc778",children:"\uc9c0\ud45c \ud655\uc778"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch Metrics\uc5d0 \uac00\ubcf4\uba74 CWAgent\ub77c\ub294 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uac00 \ucd94\uac00\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch6.png",src:n(40721).Z+"",width:"2638",height:"708"})}),"\n",(0,a.jsx)(t.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ucd94\uac00\ud558\uc5ec \uc9c0\ud45c\uc5d0 \ub300\ud55c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-json",children:'{\n "metrics": {\n "namespace": "2023-hello-world",\n ......\n },\n} \n'})}),"\n",(0,a.jsx)(t.h3,{id:"\ub85c\uadf8",children:"\ub85c\uadf8"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch \u2192 \ub85c\uadf8 \uadf8\ub8f9\uc73c\ub85c \uac00\uba74 Wizard\ub85c \ucd94\uac00\ud55c \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch7.png",src:n(95994).Z+"",width:"2792",height:"1652"})}),"\n",(0,a.jsx)(t.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html",children:"CloudWatch\ub780 \ubb34\uc5c7\uc785\ub2c8\uae4c?"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://aws.amazon.com/ko/cloudwatch/pricing/",children:"Amazon CloudWatch \uc694\uae08"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html",children:"Linux \uc778\uc2a4\ud134\uc2a4 \uc9c0\ud45c"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html",children:"\uc11c\ubc84\uc5d0 CloudWatch \uc5d0\uc774\uc804\ud2b8 \uc124\uce58 \ubc0f \uc2e4\ud589"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/",children:"CloudWatch Agent\ub97c Parameter Store\uc5d0\uc11c \uad00\ub9ac\ud574 \ubcf4\uae30"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html",children:"CloudWatch\uc5d0\uc774\uc804\ud2b8 \uad6c\uc131 \ud30c\uc77c"})]})]})}function h(e={}){const{wrapper:t}={...(0,c.ah)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(i,{...e})}):i(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>d});var a=n(67294);function c(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(c[n]=e[n]);return c}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(c[n]=e[n])}return c}var o=a.createContext({}),d=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},i={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,c=e.mdxType,r=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),u=d(n),p=c,g=u["".concat(o,".").concat(p)]||u[p]||i[p]||r;return n?a.createElement(g,s(s({ref:t},h),{},{components:n})):a.createElement(g,s({ref:t},h))}));h.displayName="MDXCreateElement"},86344:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch1-859296155df6c20d0846f1388022a86c.png"},35939:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch2-ca9c26868dec08ea7133e2774f49798a.png"},5001:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch3-da10422b87e1901286b6d3e85e2c01cc.png"},55693:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch4-1e7eddc7e8dd890ac18352e900df8e07.png"},41733:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch5-67d1bd59d4552f4fe481452eddc78a5e.png"},40721:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch6-06ead809f7510938baee41505bc72b97.png"},95994:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch7-a86dfc0db307ddf7d1660d2b9e419c96.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2245],{45414:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var a=n(85893),c=n(3905);const r={title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"cloudwatch",tags:["cloudwatch","log","monitoring"]},s=void 0,l={permalink:"/cloudwatch",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",source:"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",description:"CloudWatch",date:"2023-08-17T00:00:00.000Z",formattedDate:"2023\ub144 8\uc6d4 17\uc77c",tags:[{label:"cloudwatch",permalink:"/tags/cloudwatch"},{label:"log",permalink:"/tags/log"},{label:"monitoring",permalink:"/tags/monitoring"}],readingTime:5.35,hasTruncateMarker:!1,authors:[],frontMatter:{title:"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"cloudwatch",tags:["cloudwatch","log","monitoring"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac",permalink:"/route-image-async-with-event"},nextItem:{title:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0",permalink:"/woowacourse-level3-retrospective"}},o={authorsImageUrls:[]},d=[{value:"CloudWatch",id:"cloudwatch",level:2},{value:"CloudWatch Metrics",id:"cloudwatch-metrics",level:2},{value:"CloudWatch Agent \uc124\uce58",id:"cloudwatch-agent-\uc124\uce58",level:2},{value:"IAM \uc5ed\ud560 \uc124\uc815",id:"iam-\uc5ed\ud560-\uc124\uc815",level:3},{value:"\uc124\uce58",id:"\uc124\uce58",level:3},{value:"Wizard",id:"wizard",level:3},{value:"\uc124\uc815 \ud30c\uc77c \uc801\uc6a9",id:"\uc124\uc815-\ud30c\uc77c-\uc801\uc6a9",level:3},{value:"types.db: no such file or directory \uc5d0\ub7ec",id:"typesdb-no-such-file-or-directory-\uc5d0\ub7ec",level:3},{value:"\uc9c0\ud45c \ud655\uc778",id:"\uc9c0\ud45c-\ud655\uc778",level:3},{value:"\ub85c\uadf8",id:"\ub85c\uadf8",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function i(e){const t={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",img:"img",p:"p",pre:"pre",...(0,c.ah)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h2,{id:"cloudwatch",children:"CloudWatch"}),"\n",(0,a.jsxs)(t.p,{children:["AWS \ub9ac\uc18c\uc2a4\uc640 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc9c0\ud45c\uc640 \ub85c\uadf8\uc5d0 \ub300\ud55c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc81c\uacf5\ud558\ub294 \uc11c\ube44\uc2a4\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc9c0\ud45c\ub97c \uac10\uc2dc\ud558\uc5ec \uc54c\ub9bc\uc744 \ubcf4\ub0b4\ub294 \uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ud504\ub9ac\ud2f0\uc5b4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \ub300\uc2dc\ubcf4\ub4dc\ub2f9 3$/M \uc758 \ube44\uc6a9\uc774 \uccad\uad6c\ub418\uace0, \uc9c0\ud45c\ub098 \ub85c\uadf8\uc758 \uc591\uc5d0 \ub530\ub77c \ube44\uc6a9\uc774 \ucd94\uac00\uc801\uc73c\ub85c \uccad\uad6c\ub41c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc694\uae08 \uc815\ubcf4\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \uc815\ubcf4\ub294 ",(0,a.jsx)(t.a,{href:"https://aws.amazon.com/ko/cloudwatch/pricing/",children:"\ub2e4\uc74c \ub9c1\ud06c"}),"\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.h2,{id:"cloudwatch-metrics",children:"CloudWatch Metrics"}),"\n",(0,a.jsxs)(t.p,{children:["\uae30\ubcf8\uc801\uc73c\ub85c 5\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc218\uc9d1\ub41c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc138\ubd80 \ubaa8\ub2c8\ud130\ub9c1(Detailed Monitoring)\uc744 \ud65c\uc131\ud654\ud558\uba74 1\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\ub97c \uc218\uc9d1\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub300\uc2dc\ubcf4\ub4dc\uc5d0\uc11c InstanceId\ub85c \uac80\uc0c9\ud558\uc5ec \uc218\uc9d1\ub41c \uc9c0\ud45c\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch1.png",src:n(86344).Z+"",width:"3214",height:"1636"})}),"\n",(0,a.jsx)(t.p,{children:"CPUUtilization, NetworkIn, NetworkOut\uacfc \uac19\uc740 \uae30\ubcf8\uc801\uc778 \uc9c0\ud45c\ub97c \uc81c\uacf5\ud558\uace0, \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud06c \uacf5\uac04\uacfc \uac19\uc740 \uc9c0\ud45c\ub97c \ud655\uc778\ud558\ub824\uba74 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\ub97c \uc124\uc815\ud574\uc57c \ud55c\ub2e4."}),"\n",(0,a.jsx)(t.h2,{id:"cloudwatch-agent-\uc124\uce58",children:"CloudWatch Agent \uc124\uce58"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch Agent \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\uc640 \ub85c\uadf8\ub97c \uc218\uc9d1\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.h3,{id:"iam-\uc5ed\ud560-\uc124\uc815",children:"IAM \uc5ed\ud560 \uc124\uc815"}),"\n",(0,a.jsxs)(t.p,{children:["\uae30\ubcf8\uc801\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4\uac00 CloudWatchAgentServerPolicy\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","IAM \u2192 \uc5ed\ud560\uc5d0\uc11c \uc5ed\ud560 \uc0dd\uc131\uc744 \ud074\ub9ad\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch2.png",src:n(35939).Z+"",width:"2614",height:"1602"})}),"\n",(0,a.jsx)(t.p,{children:"CloudWatchAgentServerPolicy \uad8c\ud55c \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uace0, \uc801\ub2f9\ud55c \uc5ed\ud560 \uc774\ub984\uc744 \uc785\ub825\ud574\uc11c \uc5ed\ud560\uc744 \uc0dd\uc131\ud55c\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch3.png",src:n(5001).Z+"",width:"2650",height:"1616"})}),"\n",(0,a.jsxs)(t.p,{children:["EC2 \uc778\uc2a4\ud134\uc2a4 \ubaa9\ub85d\uc73c\ub85c \ub4e4\uc5b4\uac00\uc11c, CloudWatch Agent\ub97c \uc124\uce58\ud560 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud074\ub9ad\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc5d0\uc11c \uc774\uc804\uc5d0 \uc0dd\uc131\ud55c \uc5ed\ud560\uc744 \uc9c0\uc815\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch4.png",src:n(55693).Z+"",width:"1764",height:"800"})}),"\n",(0,a.jsx)(t.h3,{id:"\uc124\uce58",children:"\uc124\uce58"}),"\n",(0,a.jsx)(t.p,{children:"\ud658\uacbd\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,a.jsxs)(t.p,{children:["OS: ubuntu 22.04",(0,a.jsx)(t.br,{}),"\n","\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small (ARM64)"]}),"\n",(0,a.jsx)(t.p,{children:"\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uce58\ud55c\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb\nsudo dpkg -i -E ./amazon-cloudwatch-agent.deb\n"})}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html",children:"\uc0ac\uc6a9 \uc124\uba85\uc11c"}),"\uc5d0 \uac01 \uc778\uc2a4\ud134\uc2a4 \uc720\ud615\ub9c8\ub2e4 \ub2e4\uc6b4\ub85c\ub4dc \ub9c1\ud06c\uac00 \uc790\uc138\ud558\uac8c \uc548\ub0b4\ub418\uc5b4 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.h3,{id:"wizard",children:"Wizard"}),"\n",(0,a.jsxs)(t.p,{children:["CloudWatch Wizard\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uc124\uc815 \ud30c\uc77c \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub85c\uadf8\ub97c \uc218\uc9d1\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub294 \uacbd\uc6b0 Wizard \uc2e4\ud589 \uba85\ub839\uc5b4 \uc785\ub825 \uc804 log \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \ubcf5\uc0ac\ud574\ub450\ub294 \uac83\uc774 \uc88b\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec Wizard\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard\n"})}),"\n",(0,a.jsxs)(t.p,{children:["\uc124\uc815\uc744 \uc9c4\ud589\ud558\ub2e4 \ubcf4\uba74 \uc124\uc815 \ud30c\uc77c\uc774 \uc5b4\ub5bb\uac8c \uad6c\uc131\ub420\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\ub85c\uadf8\ub97c \ucd94\uac00\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \uc785\ub825\ucc3d\uc774 \ub098\uc624\uba74 \uc900\ube44\ud574\ub480\ub358 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \uc785\ub825\ud55c\ub2e4."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch5.png",src:n(41733).Z+"",width:"2320",height:"1328"})}),"\n",(0,a.jsx)(t.p,{children:"\uc911\uac04\uc5d0 SSM parameter store\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"Do you want to store the config in the SSM parameter store?\n1. yes\n2. no\n"})}),"\n",(0,a.jsxs)(t.p,{children:["\ucd94\uac00\uc801\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 2\ubc88\uc744 \uc120\ud0dd\ud55c\ub2e4.",(0,a.jsx)(t.br,{}),"\n","Parameter Store \uad00\ub9ac\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc758 ",(0,a.jsx)(t.a,{href:"https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/",children:"\ubb38\uc11c"}),"\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac70 \uac19\ub2e4.",(0,a.jsx)(t.br,{}),"\n","\uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 ",(0,a.jsx)(t.code,{children:"/opt/aws/amazon-cloudwatch-agent/bin/config.json"})," \uc5d0 \uc124\uc815\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774 \uc800\uc7a5\ub41c\ub2e4."]}),"\n",(0,a.jsx)(t.h3,{id:"\uc124\uc815-\ud30c\uc77c-\uc801\uc6a9",children:"\uc124\uc815 \ud30c\uc77c \uc801\uc6a9"}),"\n",(0,a.jsxs)(t.p,{children:["\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uc815\ud30c\uc77c\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4.",(0,a.jsx)(t.br,{}),"\n","file \ub4a4\uc5d0\ub294 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \uc808\ub300\uacbd\ub85c(\uc544\ub798 \uba85\ub839\uc5b4 \uae30\uc900 \uae30\ubcf8 \uc0dd\uc131 \uc704\uce58)\ub97c \uc785\ub825\ud558\uba74 \ub41c\ub2e4."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json\n"})}),"\n",(0,a.jsx)(t.h3,{id:"typesdb-no-such-file-or-directory-\uc5d0\ub7ec",children:"types.db: no such file or directory \uc5d0\ub7ec"}),"\n",(0,a.jsx)(t.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc740 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 types.db \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"Error running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory\n"})}),"\n",(0,a.jsx)(t.p,{children:"types.db \ud30c\uc77c \uc0dd\uc131"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"sudo mkdir /usr/share/collectd\nsudo touch /usr/share/collectd/types.db\n"})}),"\n",(0,a.jsx)(t.h3,{id:"\uc9c0\ud45c-\ud655\uc778",children:"\uc9c0\ud45c \ud655\uc778"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch Metrics\uc5d0 \uac00\ubcf4\uba74 CWAgent\ub77c\ub294 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uac00 \ucd94\uac00\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch6.png",src:n(40721).Z+"",width:"2638",height:"708"})}),"\n",(0,a.jsx)(t.p,{children:"\ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ucd94\uac00\ud558\uc5ec \uc9c0\ud45c\uc5d0 \ub300\ud55c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-json",children:'{\n "metrics": {\n "namespace": "2023-hello-world",\n ......\n },\n} \n'})}),"\n",(0,a.jsx)(t.h3,{id:"\ub85c\uadf8",children:"\ub85c\uadf8"}),"\n",(0,a.jsx)(t.p,{children:"CloudWatch \u2192 \ub85c\uadf8 \uadf8\ub8f9\uc73c\ub85c \uac00\uba74 Wizard\ub85c \ucd94\uac00\ud55c \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"./cloudwatch7.png",src:n(95994).Z+"",width:"2792",height:"1652"})}),"\n",(0,a.jsx)(t.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html",children:"CloudWatch\ub780 \ubb34\uc5c7\uc785\ub2c8\uae4c?"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://aws.amazon.com/ko/cloudwatch/pricing/",children:"Amazon CloudWatch \uc694\uae08"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html",children:"Linux \uc778\uc2a4\ud134\uc2a4 \uc9c0\ud45c"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html",children:"\uc11c\ubc84\uc5d0 CloudWatch \uc5d0\uc774\uc804\ud2b8 \uc124\uce58 \ubc0f \uc2e4\ud589"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/",children:"CloudWatch Agent\ub97c Parameter Store\uc5d0\uc11c \uad00\ub9ac\ud574 \ubcf4\uae30"}),(0,a.jsx)(t.br,{}),"\n",(0,a.jsx)(t.a,{href:"https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html",children:"CloudWatch\uc5d0\uc774\uc804\ud2b8 \uad6c\uc131 \ud30c\uc77c"})]})]})}function h(e={}){const{wrapper:t}={...(0,c.ah)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(i,{...e})}):i(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>d});var a=n(67294);function c(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(c[n]=e[n]);return c}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(c[n]=e[n])}return c}var o=a.createContext({}),d=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},i={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,c=e.mdxType,r=e.originalType,o=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),u=d(n),p=c,g=u["".concat(o,".").concat(p)]||u[p]||i[p]||r;return n?a.createElement(g,s(s({ref:t},h),{},{components:n})):a.createElement(g,s({ref:t},h))}));h.displayName="MDXCreateElement"},86344:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch1-859296155df6c20d0846f1388022a86c.png"},35939:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch2-ca9c26868dec08ea7133e2774f49798a.png"},5001:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch3-da10422b87e1901286b6d3e85e2c01cc.png"},55693:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch4-1e7eddc7e8dd890ac18352e900df8e07.png"},41733:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch5-67d1bd59d4552f4fe481452eddc78a5e.png"},40721:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch6-06ead809f7510938baee41505bc72b97.png"},95994:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/cloudwatch7-a86dfc0db307ddf7d1660d2b9e419c96.png"}}]); \ No newline at end of file diff --git a/assets/js/f8409a7e.dfd38fb7.js b/assets/js/f8409a7e.33b7f04e.js similarity index 97% rename from assets/js/f8409a7e.dfd38fb7.js rename to assets/js/f8409a7e.33b7f04e.js index 93a14f8e5..91438682e 100644 --- a/assets/js/f8409a7e.dfd38fb7.js +++ b/assets/js/f8409a7e.33b7f04e.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3206],{29325:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>l});var n=r(85893),o=r(3905);const i={id:"intro",title:"\ubb38\uc11c",slug:"/"},c=void 0,a={id:"intro",title:"\ubb38\uc11c",description:"\ub9c8\uc74c\uc5d0 \ub4e0 \ud0a4\uc6cc\ub4dc \uc815\ub9ac",source:"@site/docs/intro.mdx",sourceDirName:".",slug:"/",permalink:"/docs/",draft:!1,unlisted:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/intro.mdx",tags:[],version:"current",lastUpdatedAt:1699095400,formattedLastUpdatedAt:"2023\ub144 11\uc6d4 4\uc77c",frontMatter:{id:"intro",title:"\ubb38\uc11c",slug:"/"},sidebar:"tutorialSidebar",previous:{title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",permalink:"/docs/nginx/static-file"},next:{title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",permalink:"/docs/etc/healthful-growth"}},s={},l=[];function u(e){const t={p:"p",...(0,o.ah)(),...e.components};return(0,n.jsx)(t.p,{children:"\ub9c8\uc74c\uc5d0 \ub4e0 \ud0a4\uc6cc\ub4dc \uc815\ub9ac"})}function p(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},p=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,p=a(e,["components","mdxType","originalType","parentName"]),f=l(r),d=o,m=f["".concat(s,".").concat(d)]||f[d]||u[d]||i;return r?n.createElement(m,c(c({ref:t},p),{},{components:r})):n.createElement(m,c({ref:t},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3206],{29325:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>l});var n=r(85893),o=r(3905);const i={id:"intro",title:"\ubb38\uc11c",slug:"/"},c=void 0,a={id:"intro",title:"\ubb38\uc11c",description:"\ub9c8\uc74c\uc5d0 \ub4e0 \ud0a4\uc6cc\ub4dc \uc815\ub9ac",source:"@site/docs/intro.mdx",sourceDirName:".",slug:"/",permalink:"/docs/",draft:!1,unlisted:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/intro.mdx",tags:[],version:"current",lastUpdatedAt:1699095857,formattedLastUpdatedAt:"2023\ub144 11\uc6d4 4\uc77c",frontMatter:{id:"intro",title:"\ubb38\uc11c",slug:"/"},sidebar:"tutorialSidebar",previous:{title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",permalink:"/docs/nginx/static-file"},next:{title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",permalink:"/docs/etc/healthful-growth"}},s={},l=[];function u(e){const t={p:"p",...(0,o.ah)(),...e.components};return(0,n.jsx)(t.p,{children:"\ub9c8\uc74c\uc5d0 \ub4e0 \ud0a4\uc6cc\ub4dc \uc815\ub9ac"})}function p(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},3905:(e,t,r)=>{r.d(t,{ah:()=>l});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},p=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,p=a(e,["components","mdxType","originalType","parentName"]),f=l(r),d=o,m=f["".concat(s,".").concat(d)]||f[d]||u[d]||i;return r?n.createElement(m,c(c({ref:t},p),{},{components:r})):n.createElement(m,c({ref:t},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/f87bdf62.b1ec672d.js b/assets/js/f87bdf62.d26f8bee.js similarity index 98% rename from assets/js/f87bdf62.b1ec672d.js rename to assets/js/f87bdf62.d26f8bee.js index 61b349f17..3281ff427 100644 --- a/assets/js/f87bdf62.b1ec672d.js +++ b/assets/js/f87bdf62.d26f8bee.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6750],{52449:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>c,metadata:()=>s,toc:()=>a});var r=n(85893),o=n(3905);const c={title:"\uc6f9\uc18c\ucf13",slug:"websocket",tags:["WebSocket"]},i=void 0,s={permalink:"/websocket",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-26-WebSocket.mdx",source:"@site/blog/2023-2/2023-06-26-WebSocket.mdx",title:"\uc6f9\uc18c\ucf13",description:"\uc6f9\uc18c\ucf13",date:"2023-06-26T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 26\uc77c",tags:[{label:"WebSocket",permalink:"/tags/web-socket"}],readingTime:4.165,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9\uc18c\ucf13",slug:"websocket",tags:["WebSocket"]},unlisted:!1,prevItem:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",permalink:"/java-spring-springboot"},nextItem:{title:"Docusaurus",permalink:"/docusaurus"}},l={authorsImageUrls:[]},a=[{value:"\uc6f9\uc18c\ucf13",id:"\uc6f9\uc18c\ucf13",level:3},{value:"\uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd",id:"\uc6f9\uc18c\ucf13-\ub4f1\uc7a5-\ubc30\uacbd",level:3},{value:"\uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791",id:"\uc6f9\uc18c\ucf13\uc758-\ub3d9\uc791",level:3},{value:"1. Upgrade \uc694\uccad",id:"1-upgrade-\uc694\uccad",level:3},{value:"2. Switching Protocols",id:"2-switching-protocols",level:3},{value:"3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc",id:"3-\ud1b5\uc2e0-\ud6c4-\uc885\ub8cc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",ul:"ul",...(0,o.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13",children:"\uc6f9\uc18c\ucf13"}),"\n",(0,r.jsxs)(t.p,{children:["\ub2e8\uc77c TCP \uc5f0\uacb0\uc744 \ud1b5\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04 \uc804\uc774\uc911 \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\ud1a0\ucf5c",(0,r.jsx)(t.br,{}),"\n","\uc6f9 \ud658\uacbd\uc5d0\uc11c \uc5f0\uc18d\ub41c \ub370\uc774\ud130\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:"\uc6f9\uc18c\ucf13\uc740 HTTP\uc758 \ud3ec\ud2b8\ub97c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud558\uace0 \uac01\uac01 \ud3ec\ud2b8 80\uacfc \ud3ec\ud2b8 443\uc744 \uc0ac\uc6a9\ud558\uc5ec HTTP(ws://) \ubc0f HTTPS(wss://)\ub85c \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud55c\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13-\ub4f1\uc7a5-\ubc30\uacbd",children:"\uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd"}),"\n",(0,r.jsxs)(t.p,{children:["\uc6f9\uc18c\ucf13\uc774 \ub4f1\uc7a5\ud558\uae30 \uc774\uc804, \uc2e4\uc2dc\uac04\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 Polling, Long polling, Streaming \uac19\uc740 \uae30\uc220\uc744 \uc0ac\uc6a9\ud588\uc5b4\uc57c \ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \uc2e4\uc2dc\uac04\uc131\uc774\ub098 \uc591\ubc29\ud5a5\uc131\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \ubabb\ud588\uace0, HTTP\ub97c \uc774\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uacfc\ub3c4\ud55c \uc624\ubc84\ud5e4\ub4dc\uac00 \ubc1c\uc0dd\ud588\ub2e4."]}),"\n",(0,r.jsxs)(t.admonition,{title:"polling, long polling, streaming",type:"note",children:[(0,r.jsx)(t.p,{children:"Polling: \uc8fc\uae30\uc801\uc73c\ub85c \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ubcf4\ub0b4 \uc218\uc2e0\ud560 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\uc11c\ubc84\uc5d0\uc11c \ubcf4\ub0bc \ub0b4\uc6a9\uc774 \uc5c6\uc5b4\ub3c4 \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc54c \uc218 \uc5c6\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\uacc4\uc18d\ud574\uc11c \uc694\uccad\uc744 \ubcf4\ub0b4 \ud655\uc778\uc744 \ud574\uc57c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ubd88\ud544\uc694\ud55c \ubd80\ud558\ub97c \uc8fc\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),(0,r.jsx)(t.p,{children:"Long Polling: \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc5d0 \ub300\ud574 \uc751\ub2f5\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uace0 \uc788\ub2e4\uac00 \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud588\uc744\ub54c \uc751\ub2f5\ud558\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud3f4\ub9c1 \ubc29\uc2dd\ubcf4\ub2e4 \uc11c\ubc84\uc5d0 \uc801\uc740 \ubd80\ud558\ub97c \uc904 \uc218 \uc788\uc9c0\ub9cc, \uc694\uccad\uc758 \uc8fc\uae30\uac00 \uc9e7\uc73c\uba74 \ud3f4\ub9c1\uacfc \ucc28\uc774\uac00 \uc5c6\uc5b4\uc9c4\ub2e4."}),"\n"]}),(0,r.jsx)(t.p,{children:"Streaming: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 request\ub97c \ubcf4\ub0b4\uba74 \ucee4\ub125\uc158\uc744 \ub9fa\uace0, \uc774 \ucee4\ub125\uc158\uc744 \uc720\uc9c0\ud558\uba74\uc11c \uc11c\ubc84\uac00 \uacc4\uc18d \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ud558\uace0 \uc2f6\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ucee4\ub125\uc158\uc744 \ub9fa\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]})]}),"\n",(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13\uc758-\ub3d9\uc791",children:"\uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791"}),"\n",(0,r.jsx)(t.mermaid,{value:"sequenceDiagram\n participant Client\n participant Server\n Client->>Server: Handshake - Upgrade\ub97c \uc774\uc6a9\ud55c WebSocket \uc804\ud658 \uc694\uccad\n Server->>Client: Handshake - HttpStatus 101(Switching Protocols)\n\n Client->>Server: \uc591\ubc29\ud5a5 \ud1b5\uc2e0\n Server->>Client: \n\n Client->>Server: \uc885\ub8cc\n Server->>Client: "}),"\n",(0,r.jsx)(t.h3,{id:"1-upgrade-\uc694\uccad",children:"1. Upgrade \uc694\uccad"}),"\n",(0,r.jsxs)(t.p,{children:["WebSocket \ud504\ub85c\ud1a0\ucf5c\ub85c \uc804\ud658\ud558\ub294 HTTP \uc694\uccad\uc744 \ubcf4\ub0b8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 HTTP\uc640 \uac19\uc774 80, 443 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc6f9\uc18c\ucf13\uc73c\ub85c \uc804\ud658\ud558\uae30 \uc704\ud574\uc11c\ub294 Upgrade: websocket, Connection: Upgrade \ud5e4\ub354\uac00 \ud544\uc694\ud558\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Key\ub294 \uc11c\ubc84\uc5d0\uc11c Sec-WebSocket-Accept\ub97c \uacc4\uc0b0\ud558\uc5ec \uc751\ub2f5\ud558\uace0 \uc774 \uac12\uc774 \uc608\uc0c1\ud55c \uac12\uacfc \ub2e4\ub974\uba74 \uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Protocol\uc758 \uacbd\uc6b0 \uc11c\ube0c\ud504\ub85c\ud1a0\ucf5c\uc758 \ubaa9\ub85d\uc73c\ub85c \uc11c\ubc84 \uce21\uc5d0\uc11c\ub294 \ud574\ub2f9 \ubaa9\ub85d \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud558\uc5ec \ubc18\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub9cc\uc57d \uc11c\ubc84\uce21\uc5d0\uc11c \uc5ec\ub7ec \uac1c \uc9c0\uc6d0\uc774 \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc9c0\uc6d0 \uac00\ub2a5\ud55c \ud504\ub85c\ud1a0\ucf5c \uc911 \uccab\ubc88\uc9f8 \ud504\ub85c\ud1a0\ucf5c\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc73c\ub85c \ubcf4\ub0b8\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"GET /chats HTTP/1.1\nHost: localhost:8080\nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==\nSec-WebSocket-Protocol: v10.stomp, v11.stomp\nSec-WebSocket-Version: 13\nOrigin: http://localhost:8080\n"})}),"\n",(0,r.jsx)(t.h3,{id:"2-switching-protocols",children:"2. Switching Protocols"}),"\n",(0,r.jsxs)(t.p,{children:["\uc11c\ubc84\ub294 101 Switching Protocols \uc751\ub2f5\uc744 \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Accept\uc740 Sec-WebSocket-Key \ub4a4\uc5d0 ",(0,r.jsx)(t.code,{children:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"}),"\ub97c \ubd99\uc774\uace0 SHA1\ub85c \ud574\uc2f1 \ud6c4 Base64\ub85c \uc778\ucf54\ub529\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \uc11c\ubc84 \uc6f9\uc18c\ucf13 \ud504\ub85c\ud1a0\ucf5c\uc758 \uc9c0\uc6d0 \uc5ec\ubd80\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uba85\ud655\ud788 \uc54c\ub9ac\uae30 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"HTTP/1.1 101 Switching Protocols \nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=\nSec-WebSocket-Protocol: v10.stomp\n"})}),"\n",(0,r.jsx)(t.h3,{id:"3-\ud1b5\uc2e0-\ud6c4-\uc885\ub8cc",children:"3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:["\uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uba74 \uc6f9\uc18c\ucf13 \ud504\ub808\uc784 \ub2e8\uc704\ub85c \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc5f0\uacb0 \uc885\ub8cc\ub97c \uc6d0\ud558\ub294 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8, \uc11c\ubc84 \ubaa8\ub450 \uc5f0\uacb0 \uc885\ub8cc\ub97c \uc694\uccad\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://datatracker.ietf.org/doc/html/rfc6455",children:"https://datatracker.ietf.org/doc/html/rfc6455"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications",children:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers",children:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://docs.spring.io/spring-framework/reference/web/websocket.html",children:"https://docs.spring.io/spring-framework/reference/web/websocket.html"})]})]})}function d(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>a});var r=n(67294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),a=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),h=a(n),b=o,g=h["".concat(l,".").concat(b)]||h[b]||p[b]||c;return n?r.createElement(g,i(i({ref:t},d),{},{components:n})):r.createElement(g,i({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6750],{52449:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>c,metadata:()=>s,toc:()=>a});var r=n(85893),o=n(3905);const c={title:"\uc6f9\uc18c\ucf13",slug:"websocket",tags:["WebSocket"]},i=void 0,s={permalink:"/websocket",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-26-WebSocket.mdx",source:"@site/blog/2023-2/2023-06-26-WebSocket.mdx",title:"\uc6f9\uc18c\ucf13",description:"\uc6f9\uc18c\ucf13",date:"2023-06-26T00:00:00.000Z",formattedDate:"2023\ub144 6\uc6d4 26\uc77c",tags:[{label:"WebSocket",permalink:"/tags/web-socket"}],readingTime:4.165,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc6f9\uc18c\ucf13",slug:"websocket",tags:["WebSocket"]},unlisted:!1,prevItem:{title:"Docusaurus",permalink:"/docusaurus"},nextItem:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",permalink:"/java-spring-springboot"}},l={authorsImageUrls:[]},a=[{value:"\uc6f9\uc18c\ucf13",id:"\uc6f9\uc18c\ucf13",level:3},{value:"\uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd",id:"\uc6f9\uc18c\ucf13-\ub4f1\uc7a5-\ubc30\uacbd",level:3},{value:"\uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791",id:"\uc6f9\uc18c\ucf13\uc758-\ub3d9\uc791",level:3},{value:"1. Upgrade \uc694\uccad",id:"1-upgrade-\uc694\uccad",level:3},{value:"2. Switching Protocols",id:"2-switching-protocols",level:3},{value:"3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc",id:"3-\ud1b5\uc2e0-\ud6c4-\uc885\ub8cc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}];function p(e){const t={a:"a",admonition:"admonition",br:"br",code:"code",h3:"h3",li:"li",mermaid:"mermaid",p:"p",pre:"pre",ul:"ul",...(0,o.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13",children:"\uc6f9\uc18c\ucf13"}),"\n",(0,r.jsxs)(t.p,{children:["\ub2e8\uc77c TCP \uc5f0\uacb0\uc744 \ud1b5\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04 \uc804\uc774\uc911 \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\ud1a0\ucf5c",(0,r.jsx)(t.br,{}),"\n","\uc6f9 \ud658\uacbd\uc5d0\uc11c \uc5f0\uc18d\ub41c \ub370\uc774\ud130\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.p,{children:"\uc6f9\uc18c\ucf13\uc740 HTTP\uc758 \ud3ec\ud2b8\ub97c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud558\uace0 \uac01\uac01 \ud3ec\ud2b8 80\uacfc \ud3ec\ud2b8 443\uc744 \uc0ac\uc6a9\ud558\uc5ec HTTP(ws://) \ubc0f HTTPS(wss://)\ub85c \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud55c\ub2e4."}),"\n",(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13-\ub4f1\uc7a5-\ubc30\uacbd",children:"\uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd"}),"\n",(0,r.jsxs)(t.p,{children:["\uc6f9\uc18c\ucf13\uc774 \ub4f1\uc7a5\ud558\uae30 \uc774\uc804, \uc2e4\uc2dc\uac04\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 Polling, Long polling, Streaming \uac19\uc740 \uae30\uc220\uc744 \uc0ac\uc6a9\ud588\uc5b4\uc57c \ud588\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \uc2e4\uc2dc\uac04\uc131\uc774\ub098 \uc591\ubc29\ud5a5\uc131\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \ubabb\ud588\uace0, HTTP\ub97c \uc774\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uacfc\ub3c4\ud55c \uc624\ubc84\ud5e4\ub4dc\uac00 \ubc1c\uc0dd\ud588\ub2e4."]}),"\n",(0,r.jsxs)(t.admonition,{title:"polling, long polling, streaming",type:"note",children:[(0,r.jsx)(t.p,{children:"Polling: \uc8fc\uae30\uc801\uc73c\ub85c \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ubcf4\ub0b4 \uc218\uc2e0\ud560 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\uc11c\ubc84\uc5d0\uc11c \ubcf4\ub0bc \ub0b4\uc6a9\uc774 \uc5c6\uc5b4\ub3c4 \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc54c \uc218 \uc5c6\ub2e4."}),"\n",(0,r.jsx)(t.li,{children:"\uacc4\uc18d\ud574\uc11c \uc694\uccad\uc744 \ubcf4\ub0b4 \ud655\uc778\uc744 \ud574\uc57c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ubd88\ud544\uc694\ud55c \ubd80\ud558\ub97c \uc8fc\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]}),(0,r.jsx)(t.p,{children:"Long Polling: \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc5d0 \ub300\ud574 \uc751\ub2f5\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uace0 \uc788\ub2e4\uac00 \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud588\uc744\ub54c \uc751\ub2f5\ud558\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud3f4\ub9c1 \ubc29\uc2dd\ubcf4\ub2e4 \uc11c\ubc84\uc5d0 \uc801\uc740 \ubd80\ud558\ub97c \uc904 \uc218 \uc788\uc9c0\ub9cc, \uc694\uccad\uc758 \uc8fc\uae30\uac00 \uc9e7\uc73c\uba74 \ud3f4\ub9c1\uacfc \ucc28\uc774\uac00 \uc5c6\uc5b4\uc9c4\ub2e4."}),"\n"]}),(0,r.jsx)(t.p,{children:"Streaming: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 request\ub97c \ubcf4\ub0b4\uba74 \ucee4\ub125\uc158\uc744 \ub9fa\uace0, \uc774 \ucee4\ub125\uc158\uc744 \uc720\uc9c0\ud558\uba74\uc11c \uc11c\ubc84\uac00 \uacc4\uc18d \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95"}),(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"\ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ud558\uace0 \uc2f6\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ucee4\ub125\uc158\uc744 \ub9fa\uc5b4\uc57c \ud55c\ub2e4."}),"\n"]})]}),"\n",(0,r.jsx)(t.h3,{id:"\uc6f9\uc18c\ucf13\uc758-\ub3d9\uc791",children:"\uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791"}),"\n",(0,r.jsx)(t.mermaid,{value:"sequenceDiagram\n participant Client\n participant Server\n Client->>Server: Handshake - Upgrade\ub97c \uc774\uc6a9\ud55c WebSocket \uc804\ud658 \uc694\uccad\n Server->>Client: Handshake - HttpStatus 101(Switching Protocols)\n\n Client->>Server: \uc591\ubc29\ud5a5 \ud1b5\uc2e0\n Server->>Client: \n\n Client->>Server: \uc885\ub8cc\n Server->>Client: "}),"\n",(0,r.jsx)(t.h3,{id:"1-upgrade-\uc694\uccad",children:"1. Upgrade \uc694\uccad"}),"\n",(0,r.jsxs)(t.p,{children:["WebSocket \ud504\ub85c\ud1a0\ucf5c\ub85c \uc804\ud658\ud558\ub294 HTTP \uc694\uccad\uc744 \ubcf4\ub0b8\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 HTTP\uc640 \uac19\uc774 80, 443 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc6f9\uc18c\ucf13\uc73c\ub85c \uc804\ud658\ud558\uae30 \uc704\ud574\uc11c\ub294 Upgrade: websocket, Connection: Upgrade \ud5e4\ub354\uac00 \ud544\uc694\ud558\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Key\ub294 \uc11c\ubc84\uc5d0\uc11c Sec-WebSocket-Accept\ub97c \uacc4\uc0b0\ud558\uc5ec \uc751\ub2f5\ud558\uace0 \uc774 \uac12\uc774 \uc608\uc0c1\ud55c \uac12\uacfc \ub2e4\ub974\uba74 \uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Protocol\uc758 \uacbd\uc6b0 \uc11c\ube0c\ud504\ub85c\ud1a0\ucf5c\uc758 \ubaa9\ub85d\uc73c\ub85c \uc11c\ubc84 \uce21\uc5d0\uc11c\ub294 \ud574\ub2f9 \ubaa9\ub85d \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud558\uc5ec \ubc18\ud658\ud574\uc57c \ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\ub9cc\uc57d \uc11c\ubc84\uce21\uc5d0\uc11c \uc5ec\ub7ec \uac1c \uc9c0\uc6d0\uc774 \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc9c0\uc6d0 \uac00\ub2a5\ud55c \ud504\ub85c\ud1a0\ucf5c \uc911 \uccab\ubc88\uc9f8 \ud504\ub85c\ud1a0\ucf5c\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc73c\ub85c \ubcf4\ub0b8\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"GET /chats HTTP/1.1\nHost: localhost:8080\nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==\nSec-WebSocket-Protocol: v10.stomp, v11.stomp\nSec-WebSocket-Version: 13\nOrigin: http://localhost:8080\n"})}),"\n",(0,r.jsx)(t.h3,{id:"2-switching-protocols",children:"2. Switching Protocols"}),"\n",(0,r.jsxs)(t.p,{children:["\uc11c\ubc84\ub294 101 Switching Protocols \uc751\ub2f5\uc744 \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","Sec-WebSocket-Accept\uc740 Sec-WebSocket-Key \ub4a4\uc5d0 ",(0,r.jsx)(t.code,{children:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"}),"\ub97c \ubd99\uc774\uace0 SHA1\ub85c \ud574\uc2f1 \ud6c4 Base64\ub85c \uc778\ucf54\ub529\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc774\ub294 \uc11c\ubc84 \uc6f9\uc18c\ucf13 \ud504\ub85c\ud1a0\ucf5c\uc758 \uc9c0\uc6d0 \uc5ec\ubd80\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uba85\ud655\ud788 \uc54c\ub9ac\uae30 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"HTTP/1.1 101 Switching Protocols \nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=\nSec-WebSocket-Protocol: v10.stomp\n"})}),"\n",(0,r.jsx)(t.h3,{id:"3-\ud1b5\uc2e0-\ud6c4-\uc885\ub8cc",children:"3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:["\uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uba74 \uc6f9\uc18c\ucf13 \ud504\ub808\uc784 \ub2e8\uc704\ub85c \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \ud55c\ub2e4.",(0,r.jsx)(t.br,{}),"\n","\uc5f0\uacb0 \uc885\ub8cc\ub97c \uc6d0\ud558\ub294 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8, \uc11c\ubc84 \ubaa8\ub450 \uc5f0\uacb0 \uc885\ub8cc\ub97c \uc694\uccad\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(t.h3,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://datatracker.ietf.org/doc/html/rfc6455",children:"https://datatracker.ietf.org/doc/html/rfc6455"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications",children:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers",children:"https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers"}),(0,r.jsx)(t.br,{}),"\n",(0,r.jsx)(t.a,{href:"https://docs.spring.io/spring-framework/reference/web/websocket.html",children:"https://docs.spring.io/spring-framework/reference/web/websocket.html"})]})]})}function d(e={}){const{wrapper:t}={...(0,o.ah)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},3905:(e,t,n)=>{n.d(t,{ah:()=>a});var r=n(67294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),a=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),h=a(n),b=o,g=h["".concat(l,".").concat(b)]||h[b]||p[b]||c;return n?r.createElement(g,i(i({ref:t},d),{},{components:n})):r.createElement(g,i({ref:t},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/f90d0c52.7f1a329c.js b/assets/js/f90d0c52.52a08709.js similarity index 98% rename from assets/js/f90d0c52.7f1a329c.js rename to assets/js/f90d0c52.52a08709.js index b8f73e523..0d5ba03ce 100644 --- a/assets/js/f90d0c52.7f1a329c.js +++ b/assets/js/f90d0c52.52a08709.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5294],{47522:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var t=r(85893),l=r(3905);const i={title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",slug:"the-essence-of-object-orientation",tags:["Book"]},s=void 0,c={permalink:"/the-essence-of-object-orientation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",source:"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",description:"\ucc45 \uc815\ubcf4",date:"2023-01-07T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 7\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:5.415,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",slug:"the-essence-of-object-orientation",tags:["Book"]},unlisted:!1,prevItem:{title:"JSR-310",permalink:"/jsr-310"},nextItem:{title:"2022\ub144 \ud68c\uace0",permalink:"/2022-retrospective"}},o={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173",id:"\ucc45\uc784\uc758-\uc790\uc728\uc131\uc744-\uac15\uc870\ud558\ub294-\uc774\uc720-p173",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function p(e){const n={blockquote:"blockquote",br:"br",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,l.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",(0,t.jsx)(n.br,{}),"\n","\uc870\uc601\ud638"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc870\uc601\ud638\ub2d8\uc758 \uc624\ube0c\uc81d\ud2b8\ub97c \uc77d\uace0 \ub098\uc11c \ub2e4\uc2dc \ud55c \ubc88 \uc77d\uc5b4\ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc544\uc9c1 \uc774\ud574\uac00 \uc548\ub418\ub294 \ubd80\ubd84\uc774 \ub9ce\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ud56d\uc0c1 \uc0c8\ub85c\uc6c0\uc744 \ub290\ub080\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub354\ud560 \ub098\uc704 \uc5c6\uc774 \ud73c\ub96d\ud55c \uac1d\uccb4\uc9c0\ud5a5 \ucc45\uc774\uace0, \uc870\uae08 \ub354 \uacf5\ubd80\ud558\uace0 \ub2e4\uc2dc \uc77d\uc5b4\ubd10\uc57c\ub420 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ucee4\ud53c \uc804\ubb38\uc810, \uc9c0\ud558\ucca0 \ub178\uc120\ub3c4, \uc774\uc0c1\ud55c \ub098\ub77c\uc758 \uc5d8\ub9ac\uc2a4\ub97c \uc608\uc2dc\ub85c \ub4e0 \uc124\uba85\uc774 \ub108\ubb34 \uc88b\uc558\uace0",(0,t.jsx)(n.br,{}),"\n","\uc88b\uc740 \ub0b4\uc6a9\uc744 \ub2f4\uace0 \uc788\uc9c0\ub9cc \uadf8\ub807\ub2e4\uace0 \ub108\ubb34 \ubb34\uac81\uc9c0 \uc54a\uc544 \uac00\ubccd\uac8c \uc77d\uae30\ub3c4 \uc88b\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucc45\uc784\uc758-\uc790\uc728\uc131\uc744-\uac15\uc870\ud558\ub294-\uc774\uc720-p173",children:"\ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173"}),"\n",(0,t.jsx)(n.p,{children:"\ud611\ub825\uc744 \ub2e8\uc21c\ud558\uac8c \ub9cc\ub4e0\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604 \u2192 \ud611\ub825\uc758 \ubcf5\uc7a1\ud568 \uc800\ud558"}),"\n",(0,t.jsx)(n.li,{children:"\ucc45\uc784\uc758 \ucd94\uc0c1\ud654"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc678\ubd80\uc640 \ub0b4\ubd80\ub97c \uba85\ud655\ud558\uac8c \ubd84\ub9ac\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc694\uccad\ud558\ub294 \uac1d\uccb4\uac00 \ubab0\ub77c\ub3c4 \ub418\ub294 \ubd80\ubd84\uc774 \ucea1\uc290\ud654\ub428\uc73c\ub85c \uc778\ud130\ud398\uc774\uc2a4\uc640 \uad6c\ud604\uc758 \ubd84\ub9ac"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub0b4\ubd80\uc801\uc778 \ubc29\ubc95\uc744 \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 \uc678\ubd80\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ubcc0\uacbd\uc758 \ud30c\uae09\ud6a8\uacfc\ub97c \uac1d\uccb4 \ub0b4\ubd80\ub85c \ucea1\uc290\ud654 \u2192 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \uac1d\uccb4\uc640\uc758 \uacb0\ud569\ub3c4 \uc800\ud558"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ud611\ub825\uc758 \ub300\uc0c1\uc744 \ub2e4\uc591\ud558\uac8c \uc120\ud0dd\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\uc131\uc744 \uc81c\uacf5\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc720\uc5f0\ud55c \uc124\uacc4 \u2192 \uc7ac\uc0ac\uc6a9\uc131 \uc99d\uac00"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc758 \uc5ed\ud560\uc744 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc9c4\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc751\uc9d1\ub3c4\ub97c \ub192\uc740 \uc0c1\ud0dc\ub85c \uc720\uc9c0"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubaa9\ud45c\ub294 \uc2e4\uc138\uacc4\ub97c \ubaa8\ubc29\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\n\uc624\ud788\ub824 \uc0c8\ub85c\uc6b4 \uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc790\uc758 \uc5ed\ud560\uc740 \ub2e8\uc21c\ud788 \uc2e4\uc138\uacc4\ub97c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc548\uc73c\ub85c \uc62e\uaca8 \ub2f4\ub294 \uac83\uc774 \uc544\ub2c8\ub77c \uace0\uac1d\uacfc \uc0ac\uc6a9\uc790\ub97c \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\ub294 \uc2e0\uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\np.21"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uacfc\uac70\uc758 \uc804\ud1b5\uc801\uc778 \uac1c\ubc1c \ubc29\ubc95\uc740 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uc5c4\uaca9\ud558\uac8c \uad6c\ubd84\ud55c\ub2e4.\n\uc774\uc5d0 \ubc18\ud574 \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c\ub294 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uac1d\uccb4\ub77c\ub294 \ud558\ub098\uc758 \ud2c0 \uc548\uc5d0 \ud568\uaed8 \ubb36\uc5b4 \ub193\uc74c\uc73c\ub85c\uc368 \uac1d\uccb4\uc758 \uc790\uc728\uc131\uc744 \ubcf4\uc7a5\ud55c\ub2e4.\n\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub85c \uad6c\uc131\ub41c \uacf5\ub3d9\uccb4\ub294 \uc720\uc9c0 \ubcf4\uc218\uac00 \uc27d\uace0 \uc7ac\uc0ac\uc6a9\uc774 \uc6a9\uc774\ud55c \uc2dc\uc2a4\ud15c\uc744 \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uac00\ub2a5\uc131\uc744 \uc81c\uc2dc\ud55c\ub2e4.\np.33"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubcf8\uc9c8"})}),"\n",(0,t.jsx)(n.p,{children:"\uc2dc\uc2a4\ud15c\uc744 \uc0c1\ud638\uc791\uc6a9\ud558\ub294 \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub4e4\uc758 \uacf5\ub3d9\uccb4\ub85c \ubc14\ub77c\ubcf4\uace0 \uac1d\uccb4\ub97c \uc774\uc6a9\ud574 \uc2dc\uc2a4\ud15c\uc744 \ubd84\ud560\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.p,{children:"\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub780 \uc0c1\ud0dc\uc640 \ud589\uc704\ub97c \ud568\uaed8 \uc9c0\ub2c8\uba70 \uc2a4\uc2a4\ub85c \uc790\uae30 \uc790\uc2e0\uc744 \ucc45\uc784\uc9c0\ub294 \uac1d\uccb4\ub97c \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\ub294 \uc2dc\uc2a4\ud15c\uc758 \ud589\uc704\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud55c\ub2e4. \uac01 \uac1d\uccb4\ub294 \ud611\ub825 \ub0b4\uc5d0\uc11c \uc815\ud574\uc9c4 \uc5ed\ud560\uc744 \uc218\ud589\ud558\uba70 \uc5ed\ud560\uc740 \uad00\ub828\ub41c \ucc45\uc784\uc758 \uc9d1\ud569\uc774\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\ub294 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud558\uae30 \uc704\ud574 \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\uace0, \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c \uac1d\uccb4\ub294 \uba54\uc2dc\uc9c0\ub97c \ucc98\ub9ac\ud558\ub294 \ub370 \uc801\ud569\ud55c \uba54\uc11c\ub4dc\ub97c \uc790\uc728\uc801\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.\np.35"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ud074\ub798\uc2a4\uc758 \uad6c\uc870\uc640 \uba54\uc11c\ub4dc\uac00 \uc544\ub2c8\ub77c \uac1d\uccb4\uc758 \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc5d0 \uc9d1\uc911\ud558\ub77c.\n\uac1d\uccb4\uc9c0\ud5a5\uc740 \uac1d\uccb4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774\uc9c0 \ud074\ub798\uc2a4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\np.38"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub3d9\uc801\uc73c\ub85c \ubcc0\ud558\ub294 \uac1d\uccb4\uc758 \u2018\uc0c1\ud0dc\u2019\uc640 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \u2018\ud589\uc704\u2019\ub2e4.\n\ud074\ub798\uc2a4\ub294 \ud0c0\uc785\uc744 \uad6c\ud604\ud558\uae30 \uc704\ud574 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uad6c\ud604 \uba54\ucee4\ub2c8\uc998\uc774\ub77c\ub294 \uc0ac\uc2e4\uc744 \uae30\uc5b5\ud558\ub77c.\np.105"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ucc45\uc784 \uc8fc\ub3c4 \uc124\uacc4\uc758 \ud575\uc2ec\uc740 \uc5b4\ub5a4 \ud589\uc704\uac00 \ud544\uc694\ud55c\uc9c0\ub97c \uba3c\uc800 \uacb0\uc815\ud55c \ud6c4\uc5d0 \uc774 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac1d\uccb4\ub97c \uacb0\uc815\ud558\ub294 \uac83\uc774\ub2e4.\n\uc774 \uacfc\uc815\uc744 \ud754\ud788 What/Who \uc0ac\uc774\ud074\uc774\ub77c\uace0 \ud55c\ub2e4.\n\u2019\uc5b4\ub5a4 \ud589\uc704(What)\u2019\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud55c \ud6c4 \u2018\ub204\uac00(who)\u2019 \uadf8 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud574\uc57c \ud55c\ub2e4.\n\uc5ec\uae30\uc11c \u2018\uc5b4\ub5a4 \ud589\uc704\u2019\uac00 \ubc14\ub85c \uba54\uc2dc\uc9c0\ub2e4.\np.158"}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var o=t.createContext({}),a=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,l=e.mdxType,i=e.originalType,o=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=a(r),u=l,j=h["".concat(o,".").concat(u)]||h[u]||p[u]||i;return r?t.createElement(j,s(s({ref:n},d),{},{components:r})):t.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5294],{47522:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>a});var t=r(85893),l=r(3905);const i={title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",slug:"the-essence-of-object-orientation",tags:["Book"]},s=void 0,c={permalink:"/the-essence-of-object-orientation",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",source:"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",description:"\ucc45 \uc815\ubcf4",date:"2023-01-07T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 7\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:5.415,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",slug:"the-essence-of-object-orientation",tags:["Book"]},unlisted:!1,prevItem:{title:"2022\ub144 \ud68c\uace0",permalink:"/2022-retrospective"},nextItem:{title:"JSR-310",permalink:"/jsr-310"}},o={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173",id:"\ucc45\uc784\uc758-\uc790\uc728\uc131\uc744-\uac15\uc870\ud558\ub294-\uc774\uc720-p173",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function p(e){const n={blockquote:"blockquote",br:"br",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,l.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574",(0,t.jsx)(n.br,{}),"\n","\uc870\uc601\ud638"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc870\uc601\ud638\ub2d8\uc758 \uc624\ube0c\uc81d\ud2b8\ub97c \uc77d\uace0 \ub098\uc11c \ub2e4\uc2dc \ud55c \ubc88 \uc77d\uc5b4\ubcf4\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc544\uc9c1 \uc774\ud574\uac00 \uc548\ub418\ub294 \ubd80\ubd84\uc774 \ub9ce\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ud56d\uc0c1 \uc0c8\ub85c\uc6c0\uc744 \ub290\ub080\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub354\ud560 \ub098\uc704 \uc5c6\uc774 \ud73c\ub96d\ud55c \uac1d\uccb4\uc9c0\ud5a5 \ucc45\uc774\uace0, \uc870\uae08 \ub354 \uacf5\ubd80\ud558\uace0 \ub2e4\uc2dc \uc77d\uc5b4\ubd10\uc57c\ub420 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\ucee4\ud53c \uc804\ubb38\uc810, \uc9c0\ud558\ucca0 \ub178\uc120\ub3c4, \uc774\uc0c1\ud55c \ub098\ub77c\uc758 \uc5d8\ub9ac\uc2a4\ub97c \uc608\uc2dc\ub85c \ub4e0 \uc124\uba85\uc774 \ub108\ubb34 \uc88b\uc558\uace0",(0,t.jsx)(n.br,{}),"\n","\uc88b\uc740 \ub0b4\uc6a9\uc744 \ub2f4\uace0 \uc788\uc9c0\ub9cc \uadf8\ub807\ub2e4\uace0 \ub108\ubb34 \ubb34\uac81\uc9c0 \uc54a\uc544 \uac00\ubccd\uac8c \uc77d\uae30\ub3c4 \uc88b\uc740 \uac83 \uac19\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ucc45\uc784\uc758-\uc790\uc728\uc131\uc744-\uac15\uc870\ud558\ub294-\uc774\uc720-p173",children:"\ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173"}),"\n",(0,t.jsx)(n.p,{children:"\ud611\ub825\uc744 \ub2e8\uc21c\ud558\uac8c \ub9cc\ub4e0\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604 \u2192 \ud611\ub825\uc758 \ubcf5\uc7a1\ud568 \uc800\ud558"}),"\n",(0,t.jsx)(n.li,{children:"\ucc45\uc784\uc758 \ucd94\uc0c1\ud654"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uc678\ubd80\uc640 \ub0b4\ubd80\ub97c \uba85\ud655\ud558\uac8c \ubd84\ub9ac\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc694\uccad\ud558\ub294 \uac1d\uccb4\uac00 \ubab0\ub77c\ub3c4 \ub418\ub294 \ubd80\ubd84\uc774 \ucea1\uc290\ud654\ub428\uc73c\ub85c \uc778\ud130\ud398\uc774\uc2a4\uc640 \uad6c\ud604\uc758 \ubd84\ub9ac"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub0b4\ubd80\uc801\uc778 \ubc29\ubc95\uc744 \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 \uc678\ubd80\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub294\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\ubcc0\uacbd\uc758 \ud30c\uae09\ud6a8\uacfc\ub97c \uac1d\uccb4 \ub0b4\ubd80\ub85c \ucea1\uc290\ud654 \u2192 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \uac1d\uccb4\uc640\uc758 \uacb0\ud569\ub3c4 \uc800\ud558"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\ud611\ub825\uc758 \ub300\uc0c1\uc744 \ub2e4\uc591\ud558\uac8c \uc120\ud0dd\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\uc131\uc744 \uc81c\uacf5\ud55c\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc720\uc5f0\ud55c \uc124\uacc4 \u2192 \uc7ac\uc0ac\uc6a9\uc131 \uc99d\uac00"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc758 \uc5ed\ud560\uc744 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc9c4\ub2e4."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"\uc751\uc9d1\ub3c4\ub97c \ub192\uc740 \uc0c1\ud0dc\ub85c \uc720\uc9c0"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubaa9\ud45c\ub294 \uc2e4\uc138\uacc4\ub97c \ubaa8\ubc29\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\n\uc624\ud788\ub824 \uc0c8\ub85c\uc6b4 \uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc790\uc758 \uc5ed\ud560\uc740 \ub2e8\uc21c\ud788 \uc2e4\uc138\uacc4\ub97c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc548\uc73c\ub85c \uc62e\uaca8 \ub2f4\ub294 \uac83\uc774 \uc544\ub2c8\ub77c \uace0\uac1d\uacfc \uc0ac\uc6a9\uc790\ub97c \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\ub294 \uc2e0\uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\np.21"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uacfc\uac70\uc758 \uc804\ud1b5\uc801\uc778 \uac1c\ubc1c \ubc29\ubc95\uc740 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uc5c4\uaca9\ud558\uac8c \uad6c\ubd84\ud55c\ub2e4.\n\uc774\uc5d0 \ubc18\ud574 \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c\ub294 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uac1d\uccb4\ub77c\ub294 \ud558\ub098\uc758 \ud2c0 \uc548\uc5d0 \ud568\uaed8 \ubb36\uc5b4 \ub193\uc74c\uc73c\ub85c\uc368 \uac1d\uccb4\uc758 \uc790\uc728\uc131\uc744 \ubcf4\uc7a5\ud55c\ub2e4.\n\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub85c \uad6c\uc131\ub41c \uacf5\ub3d9\uccb4\ub294 \uc720\uc9c0 \ubcf4\uc218\uac00 \uc27d\uace0 \uc7ac\uc0ac\uc6a9\uc774 \uc6a9\uc774\ud55c \uc2dc\uc2a4\ud15c\uc744 \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uac00\ub2a5\uc131\uc744 \uc81c\uc2dc\ud55c\ub2e4.\np.33"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubcf8\uc9c8"})}),"\n",(0,t.jsx)(n.p,{children:"\uc2dc\uc2a4\ud15c\uc744 \uc0c1\ud638\uc791\uc6a9\ud558\ub294 \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub4e4\uc758 \uacf5\ub3d9\uccb4\ub85c \ubc14\ub77c\ubcf4\uace0 \uac1d\uccb4\ub97c \uc774\uc6a9\ud574 \uc2dc\uc2a4\ud15c\uc744 \ubd84\ud560\ud558\ub294 \ubc29\ubc95"}),"\n",(0,t.jsx)(n.p,{children:"\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub780 \uc0c1\ud0dc\uc640 \ud589\uc704\ub97c \ud568\uaed8 \uc9c0\ub2c8\uba70 \uc2a4\uc2a4\ub85c \uc790\uae30 \uc790\uc2e0\uc744 \ucc45\uc784\uc9c0\ub294 \uac1d\uccb4\ub97c \uc758\ubbf8\ud55c\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\ub294 \uc2dc\uc2a4\ud15c\uc758 \ud589\uc704\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud55c\ub2e4. \uac01 \uac1d\uccb4\ub294 \ud611\ub825 \ub0b4\uc5d0\uc11c \uc815\ud574\uc9c4 \uc5ed\ud560\uc744 \uc218\ud589\ud558\uba70 \uc5ed\ud560\uc740 \uad00\ub828\ub41c \ucc45\uc784\uc758 \uc9d1\ud569\uc774\ub2e4."}),"\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\ub294 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud558\uae30 \uc704\ud574 \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\uace0, \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c \uac1d\uccb4\ub294 \uba54\uc2dc\uc9c0\ub97c \ucc98\ub9ac\ud558\ub294 \ub370 \uc801\ud569\ud55c \uba54\uc11c\ub4dc\ub97c \uc790\uc728\uc801\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.\np.35"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ud074\ub798\uc2a4\uc758 \uad6c\uc870\uc640 \uba54\uc11c\ub4dc\uac00 \uc544\ub2c8\ub77c \uac1d\uccb4\uc758 \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc5d0 \uc9d1\uc911\ud558\ub77c.\n\uac1d\uccb4\uc9c0\ud5a5\uc740 \uac1d\uccb4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774\uc9c0 \ud074\ub798\uc2a4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\np.38"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub3d9\uc801\uc73c\ub85c \ubcc0\ud558\ub294 \uac1d\uccb4\uc758 \u2018\uc0c1\ud0dc\u2019\uc640 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \u2018\ud589\uc704\u2019\ub2e4.\n\ud074\ub798\uc2a4\ub294 \ud0c0\uc785\uc744 \uad6c\ud604\ud558\uae30 \uc704\ud574 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uad6c\ud604 \uba54\ucee4\ub2c8\uc998\uc774\ub77c\ub294 \uc0ac\uc2e4\uc744 \uae30\uc5b5\ud558\ub77c.\np.105"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ucc45\uc784 \uc8fc\ub3c4 \uc124\uacc4\uc758 \ud575\uc2ec\uc740 \uc5b4\ub5a4 \ud589\uc704\uac00 \ud544\uc694\ud55c\uc9c0\ub97c \uba3c\uc800 \uacb0\uc815\ud55c \ud6c4\uc5d0 \uc774 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac1d\uccb4\ub97c \uacb0\uc815\ud558\ub294 \uac83\uc774\ub2e4.\n\uc774 \uacfc\uc815\uc744 \ud754\ud788 What/Who \uc0ac\uc774\ud074\uc774\ub77c\uace0 \ud55c\ub2e4.\n\u2019\uc5b4\ub5a4 \ud589\uc704(What)\u2019\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud55c \ud6c4 \u2018\ub204\uac00(who)\u2019 \uadf8 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud574\uc57c \ud55c\ub2e4.\n\uc5ec\uae30\uc11c \u2018\uc5b4\ub5a4 \ud589\uc704\u2019\uac00 \ubc14\ub85c \uba54\uc2dc\uc9c0\ub2e4.\np.158"}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,l.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function l(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(l[r]=e[r]);return l}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var o=t.createContext({}),a=function(e){var n=t.useContext(o),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},d=t.forwardRef((function(e,n){var r=e.components,l=e.mdxType,i=e.originalType,o=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),h=a(r),u=l,j=h["".concat(o,".").concat(u)]||h[u]||p[u]||i;return r?t.createElement(j,s(s({ref:n},d),{},{components:r})):t.createElement(j,s({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/fa3d3942.73543988.js b/assets/js/fa3d3942.7d5090c3.js similarity index 99% rename from assets/js/fa3d3942.73543988.js rename to assets/js/fa3d3942.7d5090c3.js index c00f73ae2..3a5238ad2 100644 --- a/assets/js/fa3d3942.73543988.js +++ b/assets/js/fa3d3942.7d5090c3.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[916],{28227:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>c,metadata:()=>l,toc:()=>a});var t=r(85893),o=r(3905);const c={title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",slug:"book-writer",tags:["Book"]},i=void 0,l={permalink:"/book-writer",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",source:"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",description:"\ucc45 \uc815\ubcf4",date:"2023-01-01T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 1\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:4.425,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",slug:"book-writer",tags:["Book"]},unlisted:!1,prevItem:{title:"2022\ub144 \ud68c\uace0",permalink:"/2022-retrospective"}},s={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function u(e){const n={blockquote:"blockquote",br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc15\uc194\ubbf8"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc800\uc790\uc758 \uacbd\ud5d8\uacfc \ud568\uaed8 \uae00\uc4f0\uae30\uc5d0 \ub300\ud55c \uac00\ubcbc\uc6b4 \uc870\uc5b8\uc774 \ub2f4\uaca8\uc788\uc5b4 \uac00\ubccd\uac8c \uc77d\uae30 \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae00\uc744 \uc798 \uc791\uc131\ud574 \ubcf4\uace0 \uc2f6\uc744 \ub54c \uc801\uc6a9\ud574 \ubcfc \uc218 \uc788\ub294 \uc815\ubcf4\uac00 \ub9ce\uc544\uc11c \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\uc758 \ud504\ub9ac\ucf54\uc2a4\ub97c \uc9c4\ud589\ud560 \ub54c \ud6c4\uae30\ub97c \uc791\uc131\ud558\uace0 \ub098\uba74 \ud56d\uc0c1 \uae00\uc774 \ub531\ub531\ud558\ub2e4\ub294 \ub290\ub08c\uc744 \ubc1b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub2e4\ub978 \uc9c0\uc6d0\uc790\ub4e4\uc758 \uc77d\uae30 \ud3b8\ud558\uace0, \ubc1d\uc740 \ub290\ub08c\uc744 \uc8fc\ub294 \uae00\uc744 \ubcf4\uba74 \ubd80\ub7ec\uc6b4 \ub9c8\uc74c\uc744 \uac00\uc9c0\uae30\ub3c4 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ucc45\uc744 \uc77d\uc5c8\uc73c\ub2c8 2023\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae00\uc744 \uc798 \uc801\uc5b4\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ubb38\uc7a5\uc774 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74\n\ub0b4\uc6a9\uc744 \uc77c\ubaa9\uc694\uc5f0\ud558\uac8c \uc815\ub9ac\ud588\uace0, \uae00\uc758 \uc758\ub3c4\ub3c4 \uc090\ub6a4\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub3c4 \uc801\uc808\ud55c \uac83\uc73c\ub85c \uace8\ub790\ub294\ub370\u2026 \uadf8\ub7f0\ub370\ub3c4 \uc5b4\ub518\uac00\uac00 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74? \ucd95\ucd95 \ucc98\uc9c0\uace0 \ub530\ubd84\ud558\ub2e4\uba74? \ub9d0\uaf2c\ub9ac\ub97c \ubaa8\uc870\ub9ac \u2018~\ub2e4\u2019\ub85c \ud1b5\uc77c\ud55c \uac74 \uc544\ub2cc\uc9c0 \uc810\uac80\ud574 \ubcf4\uc138\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ub9d0\uaf2c\ub9ac\ub97c \uc798 \uac16\uace0 \ub180\uc544\uc57c \ud569\ub2c8\ub2e4. \ubb38\uc7a5\uc758 \ub9c8\uc9c0\ub9c9 \uae00\uc790\ub97c \ub9e4\ubc88 \ub2e4\ub974\uac8c \uace0\uccd0\uc4f0\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uae00\uc5d0 \ud65c\uae30\ub97c \ub354\ud560 \uc218 \uc788\uc8e0. \ub54c\ub860 \ubb38\uc7a5\uc744 \ub2e4 \ub9c8\uce58\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub85c\ub9cc \ub05d\ub9fa\ub294 \uac83\ub3c4 \ubc29\ubc95. \ubb38\uc7a5\uacfc \ubb38\uc7a5 \uc0ac\uc774\uc5d0 \uc27c\ud45c\uac00 \ub4e4\uc5b4\uc11c\uba70 \uae00 \uc804\uccb4\uc5d0 \ud65c\uae30\uac00 \ub3cc\uac8c \ub3fc\uc694. \ubb38\uc7a5\uc758 \uae38\uc774\ub3c4 \ub2e4\ucc44\ub85c\uc6cc\uc9c0\ub294 \ub355\ubd84\uc5d0 \ub364\uc73c\ub85c \uc5bb\uac8c \ub418\ub294 \uac83\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ubc14\ub85c, \uae00\uc758 \ub9ac\ub4ec."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc774\uc804 \ubb38\uc7a5\uc5d0\uc11c \ub05d\ub09c \uae00\uc790\ub85c, \ub2e4\uc74c \ubb38\uc7a5\uc744 \ub05d\ub9fa\uc9c0 \uc54a\uae30. \ud55c\ub450 \ubb38\ub2e8\ub9c8\ub2e4 \ub2e8\uc5b4 \uc218\uc900\uc758 \uc544\uc8fc \uc9e7\uc740 \ubb38\uc7a5 \ubc30\uce58\ud558\uae30."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc758 \uc9c4\uc9dc \uc774\uc720, \uae00\uc758 \uc9c4\uc9dc \ubaa9\uc801, \uae00\uc758 \uc9c4\uc9dc \ub300\uc0c1\uc744 \ucc3e\uc73c\ub824\uace0 \uc560\uc37c\uc2b5\ub2c8\ub2e4. \uc9c0\uae08\ucc98\ub7fc \ud2c0\uc744 \ub5a0\uc62c\ub9b0\ub2e4\uac70\ub098, \ub208\uce58\ub97c \ubcf8\ub2e4\uac70\ub098, \uc815\uce58\uc801\uc778 \uc148\ub3c4 \ud558\uc9c0 \uc54a\uc558\uc5b4\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc81c\ubaa9\uc740 \uc9e7\uac8c, \ubcf4\uae30 \uc27d\uac8c, \uc77d\uae30 \uc27d\uac8c, \ubc1c\uc74c\uc774 \ube44\uc2b7\ud558\uac8c, \uc21c\uc11c\ub97c \ubc14\uafd4\uc11c"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc744 \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ub2e4\ub4ec\uc744 \ub54c, \ub178\ub798\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubd05\ub2c8\ub2e4. \uac10\ud788 \uac00 \ub2ff\uc744 \uc218 \uc5c6\ub294 \ubaa9\ud45c\uc774\uaca0\uc9c0\ub9cc, \ud560 \uc218 \uc788\ub294 \ucd5c\uc18c\ud55c\uc758 \ub9ac\ub4ec\uc774\ub77c\ub3c4 \ubd99\uc5ec\uc8fc\uace0 \uc2f6\uc5b4\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc5ec\ub294 \ub9d0\uacfc \ub9c8\uc9c0\ub9c9 \ub9d0\uc5d0 \uc791\uc815\ud558\uace0 \ub9c8\uc74c\uc744 \ub2f4\ub294 \uc5f0\uc2b5\uc744 \ud574\ubd05\uc2dc\ub2e4. \uae00\uc758 \uc5b4\ub290 \uad6c\uc11d\uc774\ub77c\ub3c4 \ubed4\ud55c \uae00\uc790\ub294 \ub0a8\uae30\uc9c0 \uc54a\uaca0\ub178\ub77c \ub2e4\uc9d0\ud558\uba70 \uc368\ubcf4\ub294 \uac81\ub2c8\ub2e4. \ub098\ub9cc\uc774 \uac00\uc9c4 \uc720\uc77c\ud55c \uba54\uc2dc\uc9c0\uc5d0 \uc9d1\uc911\ud558\uba74\uc11c\uc694. \uadf8\ub7fc \uc0dd\uac01\uc774 \ub2ec\ub77c\uc9c0\uace0, \uace0\ub974\ub294 \ub2e8\uc5b4\ub3c4 \ub2ec\ub77c\uc9c0\uace0, \ub0a8\uae34 \ubb38\uc7a5\ub3c4 \ub2ec\ub77c\uc838\uc694. \uacb0\uad6d\uc5d0\ub294 \uae00\uc744 \uc4f4 \uc0ac\ub78c\uc778 \ub098 \uc790\uc2e0\ub3c4 \ub0a8\ub2ec\ub77c\uc9c8 \uac81\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ub9de\ucda4\ubc95\uc740 \uc911\uc694\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub9de\ucda4\ubc95\ubcf4\ub2e4 \ub354 \uc911\uc694\ud55c \uac74 \uac70\uae30\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc785\ub2c8\ub2e4. \ub0b4 \ub9c8\uc74c\uc744 \uae00\uc5d0 \ub2f4\uc544 \uc2e4\uc5b4 \ubcf4\ub0b4\uae30 \uc804, \ub9de\ucda4\ubc95\uc744 \uc810\uac80\ud558\ub294 \uc774\uc720 \uc5ed\uc2dc \uadf8\uac81\ub2c8\ub2e4. \uc624\uc9c1 \ub0b4 \ub9c8\uc74c\uc774 \ub0a8\uc5d0\uac8c \uc77d\ud788\ub294 \ub3d9\uc548 \ubc29\ud574\uac00 \ub418\uc9c0 \uc54a\uae30\ub97c \ubc14\ub77c\uae30 \ub54c\ubb38\uc774\uc8e0. \ub0b4\uac00 \uc4f4 \uae00\ub3c4, \ub0a8\uc774 \uc4f4 \uae00\ub3c4. \uc5b8\uc81c\ub098 \uadf8 \uc548\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc774 \uba3c\uc800\uc785\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc744 \uc4f4\ub2e4\uace0 \uae00\uc774 \uc644\uc131\ub418\ub294 \uac8c \uc544\ub2c8\uc5d0\uc694. \uae00\uacfc \ub2ee\uc740 \ubaa8\uc2b5\uc73c\ub85c \uc0b4 \ub54c, \uae00\uc740 \ube44\ub85c\uc18c \uc644\uc131\ub429\ub2c8\ub2e4."}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function c(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=t.createContext({}),a=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=a(r),b=o,h=d["".concat(s,".").concat(b)]||d[b]||u[b]||c;return r?t.createElement(h,i(i({ref:n},p),{},{components:r})):t.createElement(h,i({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[916],{28227:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>c,metadata:()=>l,toc:()=>a});var t=r(85893),o=r(3905);const c={title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",slug:"book-writer",tags:["Book"]},i=void 0,l={permalink:"/book-writer",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",source:"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",description:"\ucc45 \uc815\ubcf4",date:"2023-01-01T00:00:00.000Z",formattedDate:"2023\ub144 1\uc6d4 1\uc77c",tags:[{label:"Book",permalink:"/tags/book"}],readingTime:4.425,hasTruncateMarker:!1,authors:[],frontMatter:{title:"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",slug:"book-writer",tags:["Book"]},unlisted:!1,nextItem:{title:"2022\ub144 \ud68c\uace0",permalink:"/2022-retrospective"}},s={authorsImageUrls:[]},a=[{value:"\ucc45 \uc815\ubcf4",id:"\ucc45-\uc815\ubcf4",level:3},{value:"\uc77d\uace0 \ub098\uc11c",id:"\uc77d\uace0-\ub098\uc11c",level:3},{value:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4",id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",level:3}];function u(e){const n={blockquote:"blockquote",br:"br",h3:"h3",p:"p",...(0,o.ah)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"\ucc45-\uc815\ubcf4",children:"\ucc45 \uc815\ubcf4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ubc15\uc194\ubbf8"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"\uc77d\uace0-\ub098\uc11c",children:"\uc77d\uace0 \ub098\uc11c"}),"\n",(0,t.jsxs)(n.p,{children:["\uc800\uc790\uc758 \uacbd\ud5d8\uacfc \ud568\uaed8 \uae00\uc4f0\uae30\uc5d0 \ub300\ud55c \uac00\ubcbc\uc6b4 \uc870\uc5b8\uc774 \ub2f4\uaca8\uc788\uc5b4 \uac00\ubccd\uac8c \uc77d\uae30 \uc88b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uae00\uc744 \uc798 \uc791\uc131\ud574 \ubcf4\uace0 \uc2f6\uc744 \ub54c \uc801\uc6a9\ud574 \ubcfc \uc218 \uc788\ub294 \uc815\ubcf4\uac00 \ub9ce\uc544\uc11c \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub2e4."]}),"\n",(0,t.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\uc758 \ud504\ub9ac\ucf54\uc2a4\ub97c \uc9c4\ud589\ud560 \ub54c \ud6c4\uae30\ub97c \uc791\uc131\ud558\uace0 \ub098\uba74 \ud56d\uc0c1 \uae00\uc774 \ub531\ub531\ud558\ub2e4\ub294 \ub290\ub08c\uc744 \ubc1b\uc558\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\ub2e4\ub978 \uc9c0\uc6d0\uc790\ub4e4\uc758 \uc77d\uae30 \ud3b8\ud558\uace0, \ubc1d\uc740 \ub290\ub08c\uc744 \uc8fc\ub294 \uae00\uc744 \ubcf4\uba74 \ubd80\ub7ec\uc6b4 \ub9c8\uc74c\uc744 \uac00\uc9c0\uae30\ub3c4 \ud588\ub2e4.",(0,t.jsx)(n.br,{}),"\n","\uc774 \ucc45\uc744 \uc77d\uc5c8\uc73c\ub2c8 2023\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae00\uc744 \uc798 \uc801\uc5b4\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,t.jsx)(n.h3,{id:"\ubc11\uc904-\uce5c-\ubb38\uc7a5\ub4e4",children:"\ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ubb38\uc7a5\uc774 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74\n\ub0b4\uc6a9\uc744 \uc77c\ubaa9\uc694\uc5f0\ud558\uac8c \uc815\ub9ac\ud588\uace0, \uae00\uc758 \uc758\ub3c4\ub3c4 \uc090\ub6a4\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub3c4 \uc801\uc808\ud55c \uac83\uc73c\ub85c \uace8\ub790\ub294\ub370\u2026 \uadf8\ub7f0\ub370\ub3c4 \uc5b4\ub518\uac00\uac00 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74? \ucd95\ucd95 \ucc98\uc9c0\uace0 \ub530\ubd84\ud558\ub2e4\uba74? \ub9d0\uaf2c\ub9ac\ub97c \ubaa8\uc870\ub9ac \u2018~\ub2e4\u2019\ub85c \ud1b5\uc77c\ud55c \uac74 \uc544\ub2cc\uc9c0 \uc810\uac80\ud574 \ubcf4\uc138\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ub9d0\uaf2c\ub9ac\ub97c \uc798 \uac16\uace0 \ub180\uc544\uc57c \ud569\ub2c8\ub2e4. \ubb38\uc7a5\uc758 \ub9c8\uc9c0\ub9c9 \uae00\uc790\ub97c \ub9e4\ubc88 \ub2e4\ub974\uac8c \uace0\uccd0\uc4f0\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uae00\uc5d0 \ud65c\uae30\ub97c \ub354\ud560 \uc218 \uc788\uc8e0. \ub54c\ub860 \ubb38\uc7a5\uc744 \ub2e4 \ub9c8\uce58\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub85c\ub9cc \ub05d\ub9fa\ub294 \uac83\ub3c4 \ubc29\ubc95. \ubb38\uc7a5\uacfc \ubb38\uc7a5 \uc0ac\uc774\uc5d0 \uc27c\ud45c\uac00 \ub4e4\uc5b4\uc11c\uba70 \uae00 \uc804\uccb4\uc5d0 \ud65c\uae30\uac00 \ub3cc\uac8c \ub3fc\uc694. \ubb38\uc7a5\uc758 \uae38\uc774\ub3c4 \ub2e4\ucc44\ub85c\uc6cc\uc9c0\ub294 \ub355\ubd84\uc5d0 \ub364\uc73c\ub85c \uc5bb\uac8c \ub418\ub294 \uac83\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ubc14\ub85c, \uae00\uc758 \ub9ac\ub4ec."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc774\uc804 \ubb38\uc7a5\uc5d0\uc11c \ub05d\ub09c \uae00\uc790\ub85c, \ub2e4\uc74c \ubb38\uc7a5\uc744 \ub05d\ub9fa\uc9c0 \uc54a\uae30. \ud55c\ub450 \ubb38\ub2e8\ub9c8\ub2e4 \ub2e8\uc5b4 \uc218\uc900\uc758 \uc544\uc8fc \uc9e7\uc740 \ubb38\uc7a5 \ubc30\uce58\ud558\uae30."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc758 \uc9c4\uc9dc \uc774\uc720, \uae00\uc758 \uc9c4\uc9dc \ubaa9\uc801, \uae00\uc758 \uc9c4\uc9dc \ub300\uc0c1\uc744 \ucc3e\uc73c\ub824\uace0 \uc560\uc37c\uc2b5\ub2c8\ub2e4. \uc9c0\uae08\ucc98\ub7fc \ud2c0\uc744 \ub5a0\uc62c\ub9b0\ub2e4\uac70\ub098, \ub208\uce58\ub97c \ubcf8\ub2e4\uac70\ub098, \uc815\uce58\uc801\uc778 \uc148\ub3c4 \ud558\uc9c0 \uc54a\uc558\uc5b4\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc81c\ubaa9\uc740 \uc9e7\uac8c, \ubcf4\uae30 \uc27d\uac8c, \uc77d\uae30 \uc27d\uac8c, \ubc1c\uc74c\uc774 \ube44\uc2b7\ud558\uac8c, \uc21c\uc11c\ub97c \ubc14\uafd4\uc11c"}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc744 \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ub2e4\ub4ec\uc744 \ub54c, \ub178\ub798\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubd05\ub2c8\ub2e4. \uac10\ud788 \uac00 \ub2ff\uc744 \uc218 \uc5c6\ub294 \ubaa9\ud45c\uc774\uaca0\uc9c0\ub9cc, \ud560 \uc218 \uc788\ub294 \ucd5c\uc18c\ud55c\uc758 \ub9ac\ub4ec\uc774\ub77c\ub3c4 \ubd99\uc5ec\uc8fc\uace0 \uc2f6\uc5b4\uc694."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uc5ec\ub294 \ub9d0\uacfc \ub9c8\uc9c0\ub9c9 \ub9d0\uc5d0 \uc791\uc815\ud558\uace0 \ub9c8\uc74c\uc744 \ub2f4\ub294 \uc5f0\uc2b5\uc744 \ud574\ubd05\uc2dc\ub2e4. \uae00\uc758 \uc5b4\ub290 \uad6c\uc11d\uc774\ub77c\ub3c4 \ubed4\ud55c \uae00\uc790\ub294 \ub0a8\uae30\uc9c0 \uc54a\uaca0\ub178\ub77c \ub2e4\uc9d0\ud558\uba70 \uc368\ubcf4\ub294 \uac81\ub2c8\ub2e4. \ub098\ub9cc\uc774 \uac00\uc9c4 \uc720\uc77c\ud55c \uba54\uc2dc\uc9c0\uc5d0 \uc9d1\uc911\ud558\uba74\uc11c\uc694. \uadf8\ub7fc \uc0dd\uac01\uc774 \ub2ec\ub77c\uc9c0\uace0, \uace0\ub974\ub294 \ub2e8\uc5b4\ub3c4 \ub2ec\ub77c\uc9c0\uace0, \ub0a8\uae34 \ubb38\uc7a5\ub3c4 \ub2ec\ub77c\uc838\uc694. \uacb0\uad6d\uc5d0\ub294 \uae00\uc744 \uc4f4 \uc0ac\ub78c\uc778 \ub098 \uc790\uc2e0\ub3c4 \ub0a8\ub2ec\ub77c\uc9c8 \uac81\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\ub9de\ucda4\ubc95\uc740 \uc911\uc694\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub9de\ucda4\ubc95\ubcf4\ub2e4 \ub354 \uc911\uc694\ud55c \uac74 \uac70\uae30\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc785\ub2c8\ub2e4. \ub0b4 \ub9c8\uc74c\uc744 \uae00\uc5d0 \ub2f4\uc544 \uc2e4\uc5b4 \ubcf4\ub0b4\uae30 \uc804, \ub9de\ucda4\ubc95\uc744 \uc810\uac80\ud558\ub294 \uc774\uc720 \uc5ed\uc2dc \uadf8\uac81\ub2c8\ub2e4. \uc624\uc9c1 \ub0b4 \ub9c8\uc74c\uc774 \ub0a8\uc5d0\uac8c \uc77d\ud788\ub294 \ub3d9\uc548 \ubc29\ud574\uac00 \ub418\uc9c0 \uc54a\uae30\ub97c \ubc14\ub77c\uae30 \ub54c\ubb38\uc774\uc8e0. \ub0b4\uac00 \uc4f4 \uae00\ub3c4, \ub0a8\uc774 \uc4f4 \uae00\ub3c4. \uc5b8\uc81c\ub098 \uadf8 \uc548\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc774 \uba3c\uc800\uc785\ub2c8\ub2e4."}),"\n"]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"\uae00\uc744 \uc4f4\ub2e4\uace0 \uae00\uc774 \uc644\uc131\ub418\ub294 \uac8c \uc544\ub2c8\uc5d0\uc694. \uae00\uacfc \ub2ee\uc740 \ubaa8\uc2b5\uc73c\ub85c \uc0b4 \ub54c, \uae00\uc740 \ube44\ub85c\uc18c \uc644\uc131\ub429\ub2c8\ub2e4."}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,o.ah)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},3905:(e,n,r)=>{r.d(n,{ah:()=>a});var t=r(67294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function c(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function i(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=t.createContext({}),a=function(e){var n=t.useContext(s),r=n;return e&&(r="function"==typeof e?e(n):i(i({},n),e)),r},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},p=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=a(r),b=o,h=d["".concat(s,".").concat(b)]||d[b]||u[b]||c;return r?t.createElement(h,i(i({ref:n},p),{},{components:r})):t.createElement(h,i({ref:n},p))}));p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/ff4c6c5e.8132bff2.js b/assets/js/ff4c6c5e.05d35921.js similarity index 98% rename from assets/js/ff4c6c5e.8132bff2.js rename to assets/js/ff4c6c5e.05d35921.js index f506d497c..88df41c12 100644 --- a/assets/js/ff4c6c5e.8132bff2.js +++ b/assets/js/ff4c6c5e.05d35921.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[820],{68007:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var r=t(85893),a=t(3905);const i={title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",slug:"java-spring-springboot",tags:["Java","Spring Boot","Spring"]},s=void 0,l={permalink:"/java-spring-springboot",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",source:"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",description:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",date:"2023-07-24T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 24\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Spring Boot",permalink:"/tags/spring-boot"},{label:"Spring",permalink:"/tags/spring"}],readingTime:4.725,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",slug:"java-spring-springboot",tags:["Java","Spring Boot","Spring"]},unlisted:!1,prevItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",permalink:"/route-image-intro"},nextItem:{title:"\uc6f9\uc18c\ucf13",permalink:"/websocket"}},o={authorsImageUrls:[]},c=[{value:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",id:"\uc790\ubc14-17-\uc2a4\ud504\ub9c1-60-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-31",level:2},{value:"\uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d",id:"\uc790\ubc14-\ubcc0\uacbd-\uc0ac\ud56d",level:2},{value:"Switch Expressions(Java 14)",id:"switch-expressionsjava-14",level:3},{value:"Text Block(Java 15)",id:"text-blockjava-15",level:3},{value:"NPE \uba54\uc2dc\uc9c0(Java 15)",id:"npe-\uba54\uc2dc\uc9c0java-15",level:3},{value:"Record(Java 16)",id:"recordjava-16",level:3},{value:"\ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d",id:"\ucd94\uac00\uc801\uc778-\ubcc0\uacbd\uc0ac\ud56d",level:3},{value:"\uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ubcc0\uacbd-\uc0ac\ud56d",level:2},{value:"\uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd",id:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4-\ubcc0\uacbd",level:3},{value:"PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c",id:"pathpatternparser---trailing-slash-\ud5c8\uc6a9\ud558\uc9c0-\uc54a\uc74c",level:3},{value:"HTTP interface client",id:"http-interface-client",level:3},{value:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ucd5c\uc18c-\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function h(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"\uc790\ubc14-17-\uc2a4\ud504\ub9c1-60-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-31",children:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1"}),"\n",(0,r.jsxs)(n.p,{children:["\ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\uc744 \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","2.7 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc5c8\uc9c0\ub9cc LTS \uae30\uac04\uacfc \ucde8\uc57d\uc810 \ud328\uce58\ub85c \uc778\ud55c \ubc84\uc804\uc5c5 \ub4f1\uc744 \uace0\ub824\ud588\uc744 \ub54c 3.1\uacfc \uc790\ubc14 17\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \ub354 \ud6a8\uc728\uc801\uc774\ub77c\uace0 \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uc790\ubc14-\ubcc0\uacbd-\uc0ac\ud56d",children:"\uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2\uae4c\uc9c0\ub294 \uc790\ubc14 11\uc744 \uc0ac\uc6a9\ud588\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc790\ubc14 11\ubd80\ud130 \uc790\ubc14 17\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d\uc744 \uc815\uc2dd \ub9b4\ub9ac\uc988 \uae30\uc900\uc73c\ub85c \uc815\ub9ac\ud574\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"switch-expressionsjava-14",children:"Switch Expressions(Java 14)"}),"\n",(0,r.jsx)(n.p,{children:"Java 14\uc5d0\uc11c\ub294 \uae30\uc874\uc758 Switch \ubb38\uc744 \uac04\uacb0\ud558\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub294 Switch \uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"enum RESULT {\n WIN, LOSE, DRAW\n}\n\nRESULT result = RESULT.WIN;\n\nint prize = switch (result) {\n case WIN -> 10_000_000;\n case LOSE, DRAW -> 5_000_000;\n\tdefault -> 0;\n};\n"})}),"\n",(0,r.jsx)(n.p,{children:"\uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"->"})," \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 case\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc14\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsxs)(n.li,{children:["case\ub97c \ucf64\ub9c8(",(0,r.jsx)(n.code,{children:","}),")\ub85c \uc5f0\uacb0\ud558\uc5ec \ud558\ub098\uc758 case\uc5d0 \uc5ec\ub7ec \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.li,{children:"break \ubb38\uc774 \ud544\uc694 \uc5c6\ub2e4."}),"\n",(0,r.jsx)(n.li,{children:"default \ube14\ub85d\uc744 \ud1b5\ud574 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"text-blockjava-15",children:"Text Block(Java 15)"}),"\n",(0,r.jsxs)(n.p,{children:["Java 15\uc5d0\ub294 \uc0c8\ub85c\uc6b4 \ubb38\uc790\uc5f4 \ud45c\ud604\ubc29\uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae34 \ubb38\uc790\uc5f4\uc744 + \uc5f0\uc0b0\uc790\uc758 \ub3c4\uc6c0 \uc5c6\uc774 \uac00\ub3c5\uc131\uc788\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'@Repository\npublic interface PostRepository extends JpaRepository {\n @Query("""\n SELECT p FROM Post p\n WHERE p.title LIKE %:keyword%\n OR p.content LIKE %:keyword%\n """)\n List findPostsByTitleOrContentContainingKeyword(String keyword);\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"npe-\uba54\uc2dc\uc9c0java-15",children:"NPE \uba54\uc2dc\uc9c0(Java 15)"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'String name = null;\nname.chars();\n\n/** \n# before\njava.lang.NullPointerException\n\tat com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)\n\n# after\nCannot invoke "String.chars()" because "name" is null\njava.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null\n*/\n'})}),"\n",(0,r.jsx)(n.h3,{id:"recordjava-16",children:"Record(Java 16)"}),"\n",(0,r.jsxs)(n.p,{children:["Lombok\uc758 ",(0,r.jsx)(n.code,{children:"@Data"}),", kotlin\uc758 data \ud074\ub798\uc2a4\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Record\ub97c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0 \uc811\uadfc\uc790, \uc0dd\uc131\uc790, equals & hashcode, toString\uc774 \uc81c\uacf5\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub370\uc774\ud130 \uc804\uc1a1 \uc6a9\ub3c4\ub85c \uc801\ud569\ud574 \ubcf4\uc778\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public record PostDto(String title, String content) {\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\ucd94\uac00\uc801\uc778-\ubcc0\uacbd\uc0ac\ud56d",children:"\ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d"}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uc678\uc5d0\ub3c4 stream\uc758 toList, \uc778\uc2a4\ud134\uc2a4\uc758 \ud0c0\uc785\uc744 \uac04\ud3b8\ud558\uac8c \uccb4\ud06c\ud558\ub294 Pattern Matching Instanceof, Sealed class \ub4f1\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.h2,{id:"\uc2a4\ud504\ub9c1-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ubcc0\uacbd-\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1\uacfc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\ub3c4 \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud544\uc694\ud574\ubcf4\uc774\ub294 \uba87\uac1c \uc815\ub3c4\ub9cc \uc815\ub9ac\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc2a4\ud504\ub9c1-\uc694\uad6c\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d"}),"\n",(0,r.jsx)(n.p,{children:"Java 17, Jakarta EE 9 \uc774\uc0c1\uc774\uc5b4\uc57c \ud55c\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4-\ubcc0\uacbd",children:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd"}),"\n",(0,r.jsx)(n.p,{children:"Jakarta EE 9\uac00 \uc801\uc6a9\ub418\uba74\uc11c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub3c4 \uc804\ubc18\uc801\uc73c\ub85c javax -> jakarta\ub85c \ubcc0\uacbd\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"pathpatternparser---trailing-slash-\ud5c8\uc6a9\ud558\uc9c0-\uc54a\uc74c",children:"PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c"}),"\n",(0,r.jsxs)(n.p,{children:["6.0 \uc774\uc804\uc758 \uacbd\uc6b0 \uae30\ubcf8 \uc124\uc815 \uae30\uc900\uc73c\ub85c ",(0,r.jsx)(n.code,{children:'@GetMapping("/hello")'}),"\uc640 ",(0,r.jsx)(n.code,{children:'@GetMapping("/hello/")'}),"\uac00 \ub3d9\uc77c\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","6.0 \uc774\ud6c4\uc758 PathPatternParser\uac00 \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0, ",(0,r.jsx)(n.code,{children:"/hello"}),"\uc640 ",(0,r.jsx)(n.code,{children:"/hello/"}),"\ub294 \uc11c\ub85c \ub2e4\ub978 URL\ub85c \ub9e4\uce6d\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"PathPatternParser used by default (with the ability to opt into PathMatcher)."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"http-interface-client",children:"HTTP interface client"}),"\n",(0,r.jsxs)(n.p,{children:["\uc790\ubc14 \uc778\ud130\ud398\uc774\uc2a4\uc640 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc774\uc6a9\ud558\uc5ec HTTP \uc694\uccad\uc744 \uc704\ud55c \uc11c\ube44\uc2a4\ub97c \uc815\uc758\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Kb37Q5GCyZs",children:"\ud1a0\ube44\ub2d8\uc758 \uac15\uc758"}),"\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ucd5c\uc18c-\uc694\uad6c\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6",(0,r.jsx)(n.br,{}),"\n","\uc774\uc678\uc5d0\ub3c4 \uc11c\ub4dc\ud30c\ud2f0\ub4e4\uc758 \ucd5c\uc2e0 \ub9b4\ub9ac\uc988 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud568\uc73c\ub85c, \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ubc84\uc804\uc5d0 \ub9de\ub294 \ub9b4\ub9ac\uc988 \ub178\ud2b8\ub97c \ucc38\uace0\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=1WT6oxchM9M",children:"\uc5b4\ub290\xa0\uc6d4\uae09\uc7c1\uc774\uac1c\ubc1c\uc790\xa0\uc758 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ub530\ub77c\uc7a1\uae30"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=7SlDdzVk6GE",children:"\uc790\ubc14 9-16 \uc8fc\uc694 \ud2b9\uc9d5 \ubcf5\uc2b5\ud558\uae30"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.samsungsds.com/kr/insights/java_jakarta.html",children:"Java EE\uc5d0\uc11c Jakarta EE\ub85c\uc758 \uc804\ud658"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Kb37Q5GCyZs",children:"Spring 6\uc758 \uc0c8\ub85c\uc6b4 HTTP Interface\uc640 3 \uac00\uc9c0 REST Clients \ub77c\uc774\ube0c \ucf54\ub529"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-6.x",children:"What's New in Spring Framework 6.x"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes",children:"Spring Boot 3.0 Release Notes"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes",children:"Spring Boot 3.1 Release Notes"})]})]})}function d(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var o=r.createContext({}),c=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},h={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),p=c(t),j=a,u=p["".concat(o,".").concat(j)]||p[j]||h[j]||i;return t?r.createElement(u,s(s({ref:n},d),{},{components:t})):r.createElement(u,s({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[820],{68007:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var r=t(85893),a=t(3905);const i={title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",slug:"java-spring-springboot",tags:["Java","Spring Boot","Spring"]},s=void 0,l={permalink:"/java-spring-springboot",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",source:"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",description:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",date:"2023-07-24T00:00:00.000Z",formattedDate:"2023\ub144 7\uc6d4 24\uc77c",tags:[{label:"Java",permalink:"/tags/java"},{label:"Spring Boot",permalink:"/tags/spring-boot"},{label:"Spring",permalink:"/tags/spring"}],readingTime:4.725,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",slug:"java-spring-springboot",tags:["Java","Spring Boot","Spring"]},unlisted:!1,prevItem:{title:"\uc6f9\uc18c\ucf13",permalink:"/websocket"},nextItem:{title:"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd",permalink:"/route-image-intro"}},o={authorsImageUrls:[]},c=[{value:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1",id:"\uc790\ubc14-17-\uc2a4\ud504\ub9c1-60-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-31",level:2},{value:"\uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d",id:"\uc790\ubc14-\ubcc0\uacbd-\uc0ac\ud56d",level:2},{value:"Switch Expressions(Java 14)",id:"switch-expressionsjava-14",level:3},{value:"Text Block(Java 15)",id:"text-blockjava-15",level:3},{value:"NPE \uba54\uc2dc\uc9c0(Java 15)",id:"npe-\uba54\uc2dc\uc9c0java-15",level:3},{value:"Record(Java 16)",id:"recordjava-16",level:3},{value:"\ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d",id:"\ucd94\uac00\uc801\uc778-\ubcc0\uacbd\uc0ac\ud56d",level:3},{value:"\uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ubcc0\uacbd-\uc0ac\ud56d",level:2},{value:"\uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd",id:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4-\ubcc0\uacbd",level:3},{value:"PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c",id:"pathpatternparser---trailing-slash-\ud5c8\uc6a9\ud558\uc9c0-\uc54a\uc74c",level:3},{value:"HTTP interface client",id:"http-interface-client",level:3},{value:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d",id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ucd5c\uc18c-\uc694\uad6c\uc0ac\ud56d",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}];function h(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.ah)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"\uc790\ubc14-17-\uc2a4\ud504\ub9c1-60-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-31",children:"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1"}),"\n",(0,r.jsxs)(n.p,{children:["\ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\uc744 \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","2.7 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc5c8\uc9c0\ub9cc LTS \uae30\uac04\uacfc \ucde8\uc57d\uc810 \ud328\uce58\ub85c \uc778\ud55c \ubc84\uc804\uc5c5 \ub4f1\uc744 \uace0\ub824\ud588\uc744 \ub54c 3.1\uacfc \uc790\ubc14 17\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \ub354 \ud6a8\uc728\uc801\uc774\ub77c\uace0 \ud310\ub2e8\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\uc790\ubc14-\ubcc0\uacbd-\uc0ac\ud56d",children:"\uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2\uae4c\uc9c0\ub294 \uc790\ubc14 11\uc744 \uc0ac\uc6a9\ud588\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \uc790\ubc14 11\ubd80\ud130 \uc790\ubc14 17\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d\uc744 \uc815\uc2dd \ub9b4\ub9ac\uc988 \uae30\uc900\uc73c\ub85c \uc815\ub9ac\ud574\ubcf4\ub824\uace0 \ud55c\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"switch-expressionsjava-14",children:"Switch Expressions(Java 14)"}),"\n",(0,r.jsx)(n.p,{children:"Java 14\uc5d0\uc11c\ub294 \uae30\uc874\uc758 Switch \ubb38\uc744 \uac04\uacb0\ud558\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub294 Switch \uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"enum RESULT {\n WIN, LOSE, DRAW\n}\n\nRESULT result = RESULT.WIN;\n\nint prize = switch (result) {\n case WIN -> 10_000_000;\n case LOSE, DRAW -> 5_000_000;\n\tdefault -> 0;\n};\n"})}),"\n",(0,r.jsx)(n.p,{children:"\uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"->"})," \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 case\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc14\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsxs)(n.li,{children:["case\ub97c \ucf64\ub9c8(",(0,r.jsx)(n.code,{children:","}),")\ub85c \uc5f0\uacb0\ud558\uc5ec \ud558\ub098\uc758 case\uc5d0 \uc5ec\ub7ec \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.li,{children:"break \ubb38\uc774 \ud544\uc694 \uc5c6\ub2e4."}),"\n",(0,r.jsx)(n.li,{children:"default \ube14\ub85d\uc744 \ud1b5\ud574 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"text-blockjava-15",children:"Text Block(Java 15)"}),"\n",(0,r.jsxs)(n.p,{children:["Java 15\uc5d0\ub294 \uc0c8\ub85c\uc6b4 \ubb38\uc790\uc5f4 \ud45c\ud604\ubc29\uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uae34 \ubb38\uc790\uc5f4\uc744 + \uc5f0\uc0b0\uc790\uc758 \ub3c4\uc6c0 \uc5c6\uc774 \uac00\ub3c5\uc131\uc788\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'@Repository\npublic interface PostRepository extends JpaRepository {\n @Query("""\n SELECT p FROM Post p\n WHERE p.title LIKE %:keyword%\n OR p.content LIKE %:keyword%\n """)\n List findPostsByTitleOrContentContainingKeyword(String keyword);\n}\n'})}),"\n",(0,r.jsx)(n.h3,{id:"npe-\uba54\uc2dc\uc9c0java-15",children:"NPE \uba54\uc2dc\uc9c0(Java 15)"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'String name = null;\nname.chars();\n\n/** \n# before\njava.lang.NullPointerException\n\tat com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)\n\n# after\nCannot invoke "String.chars()" because "name" is null\njava.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null\n*/\n'})}),"\n",(0,r.jsx)(n.h3,{id:"recordjava-16",children:"Record(Java 16)"}),"\n",(0,r.jsxs)(n.p,{children:["Lombok\uc758 ",(0,r.jsx)(n.code,{children:"@Data"}),", kotlin\uc758 data \ud074\ub798\uc2a4\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","Record\ub97c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0 \uc811\uadfc\uc790, \uc0dd\uc131\uc790, equals & hashcode, toString\uc774 \uc81c\uacf5\ub41c\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub370\uc774\ud130 \uc804\uc1a1 \uc6a9\ub3c4\ub85c \uc801\ud569\ud574 \ubcf4\uc778\ub2e4."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"public record PostDto(String title, String content) {\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"\ucd94\uac00\uc801\uc778-\ubcc0\uacbd\uc0ac\ud56d",children:"\ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d"}),"\n",(0,r.jsx)(n.p,{children:"\uc774\uc678\uc5d0\ub3c4 stream\uc758 toList, \uc778\uc2a4\ud134\uc2a4\uc758 \ud0c0\uc785\uc744 \uac04\ud3b8\ud558\uac8c \uccb4\ud06c\ud558\ub294 Pattern Matching Instanceof, Sealed class \ub4f1\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.h2,{id:"\uc2a4\ud504\ub9c1-\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ubcc0\uacbd-\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["\uc2a4\ud504\ub9c1\uacfc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\ub3c4 \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\ub530\ub77c\uc11c \ud544\uc694\ud574\ubcf4\uc774\ub294 \uba87\uac1c \uc815\ub3c4\ub9cc \uc815\ub9ac\ud588\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc2a4\ud504\ub9c1-\uc694\uad6c\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d"}),"\n",(0,r.jsx)(n.p,{children:"Java 17, Jakarta EE 9 \uc774\uc0c1\uc774\uc5b4\uc57c \ud55c\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4-\ubcc0\uacbd",children:"\ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd"}),"\n",(0,r.jsx)(n.p,{children:"Jakarta EE 9\uac00 \uc801\uc6a9\ub418\uba74\uc11c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub3c4 \uc804\ubc18\uc801\uc73c\ub85c javax -> jakarta\ub85c \ubcc0\uacbd\ub418\uc5c8\ub2e4."}),"\n",(0,r.jsx)(n.h3,{id:"pathpatternparser---trailing-slash-\ud5c8\uc6a9\ud558\uc9c0-\uc54a\uc74c",children:"PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c"}),"\n",(0,r.jsxs)(n.p,{children:["6.0 \uc774\uc804\uc758 \uacbd\uc6b0 \uae30\ubcf8 \uc124\uc815 \uae30\uc900\uc73c\ub85c ",(0,r.jsx)(n.code,{children:'@GetMapping("/hello")'}),"\uc640 ",(0,r.jsx)(n.code,{children:'@GetMapping("/hello/")'}),"\uac00 \ub3d9\uc77c\ud588\ub2e4.",(0,r.jsx)(n.br,{}),"\n","6.0 \uc774\ud6c4\uc758 PathPatternParser\uac00 \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0, ",(0,r.jsx)(n.code,{children:"/hello"}),"\uc640 ",(0,r.jsx)(n.code,{children:"/hello/"}),"\ub294 \uc11c\ub85c \ub2e4\ub978 URL\ub85c \ub9e4\uce6d\ub41c\ub2e4."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"PathPatternParser used by default (with the ability to opt into PathMatcher)."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"http-interface-client",children:"HTTP interface client"}),"\n",(0,r.jsxs)(n.p,{children:["\uc790\ubc14 \uc778\ud130\ud398\uc774\uc2a4\uc640 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc774\uc6a9\ud558\uc5ec HTTP \uc694\uccad\uc744 \uc704\ud55c \uc11c\ube44\uc2a4\ub97c \uc815\uc758\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,r.jsx)(n.br,{}),"\n","\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Kb37Q5GCyZs",children:"\ud1a0\ube44\ub2d8\uc758 \uac15\uc758"}),"\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(n.h3,{id:"\uc2a4\ud504\ub9c1-\ubd80\ud2b8-\ucd5c\uc18c-\uc694\uad6c\uc0ac\ud56d",children:"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d"}),"\n",(0,r.jsxs)(n.p,{children:["Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6",(0,r.jsx)(n.br,{}),"\n","\uc774\uc678\uc5d0\ub3c4 \uc11c\ub4dc\ud30c\ud2f0\ub4e4\uc758 \ucd5c\uc2e0 \ub9b4\ub9ac\uc988 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud568\uc73c\ub85c, \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ubc84\uc804\uc5d0 \ub9de\ub294 \ub9b4\ub9ac\uc988 \ub178\ud2b8\ub97c \ucc38\uace0\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4."]}),"\n",(0,r.jsx)(n.h2,{id:"\ucc38\uace0-\uc790\ub8cc",children:"\ucc38\uace0 \uc790\ub8cc"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=1WT6oxchM9M",children:"\uc5b4\ub290\xa0\uc6d4\uae09\uc7c1\uc774\uac1c\ubc1c\uc790\xa0\uc758 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ub530\ub77c\uc7a1\uae30"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=7SlDdzVk6GE",children:"\uc790\ubc14 9-16 \uc8fc\uc694 \ud2b9\uc9d5 \ubcf5\uc2b5\ud558\uae30"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.samsungsds.com/kr/insights/java_jakarta.html",children:"Java EE\uc5d0\uc11c Jakarta EE\ub85c\uc758 \uc804\ud658"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Kb37Q5GCyZs",children:"Spring 6\uc758 \uc0c8\ub85c\uc6b4 HTTP Interface\uc640 3 \uac00\uc9c0 REST Clients \ub77c\uc774\ube0c \ucf54\ub529"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-6.x",children:"What's New in Spring Framework 6.x"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes",children:"Spring Boot 3.0 Release Notes"}),(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.a,{href:"https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes",children:"Spring Boot 3.1 Release Notes"})]})]})}function d(e={}){const{wrapper:n}={...(0,a.ah)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3905:(e,n,t)=>{t.d(n,{ah:()=>c});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var o=r.createContext({}),c=function(e){var n=r.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},h={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),p=c(t),j=a,u=p["".concat(o,".").concat(j)]||p[j]||h[j]||i;return t?r.createElement(u,s(s({ref:n},d),{},{components:t})):r.createElement(u,s({ref:n},d))}));d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/assets/js/main.eea870a2.js b/assets/js/main.6df83e8f.js similarity index 73% rename from assets/js/main.eea870a2.js rename to assets/js/main.6df83e8f.js index 2acdeae1e..211d0730c 100644 --- a/assets/js/main.eea870a2.js +++ b/assets/js/main.6df83e8f.js @@ -1,2 +1,2 @@ -/*! For license information please see main.eea870a2.js.LICENSE.txt */ -(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[179],{20830:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});var a=n(67294);function r(){return a.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},a.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}},723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});n(67294);var a=n(68356),r=n.n(a),o=n(16887);const i={"00931cc3":[()=>n.e(5669).then(n.t.bind(n,92291,19)),"~blog/default/page-30-25c.json",92291],"01a85c17":[()=>Promise.all([n.e(532),n.e(4013)]).then(n.bind(n,24524)),"@theme/BlogTagsListPage",24524],"02689328":[()=>n.e(6346).then(n.t.bind(n,5577,19)),"~blog/default/tags-data-base-page-3-9db.json",5577],"0281109c":[()=>n.e(422).then(n.t.bind(n,25266,19)),"~blog/default/tags-jenkins-2e5-list.json",25266],"02ede3c9":[()=>n.e(4934).then(n.t.bind(n,51226,19)),"~blog/default/tags-retrospective-page-18-40f.json",51226],"04644f5f":[()=>n.e(2625).then(n.bind(n,37895)),"@site/docs/\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00.mdx",37895],"04c55e47":[()=>n.e(4275).then(n.t.bind(n,26888,19)),"~blog/default/page-49-c29.json",26888],"051528db":[()=>n.e(5753).then(n.bind(n,29837)),"@site/docs/\ub9ac\ub205\uc2a4/\ud130\ubbf8\ub110 \uc258 \ud504\ub86c\ud504\ud2b8 \uc124\uc815.md",29837],"0571a526":[()=>n.e(6204).then(n.bind(n,93516)),"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",93516],"05b907fc":[()=>n.e(734).then(n.t.bind(n,92943,19)),"~blog/default/tags-retrospective-page-8-5ab-list.json",92943],"0746167d":[()=>n.e(1113).then(n.t.bind(n,19758,19)),"~blog/default/tags-elastic-beanstalk-119-list.json",19758],"08726fcf":[()=>n.e(5487).then(n.t.bind(n,38441,19)),"~blog/default/tags-java-page-4-c22-list.json",38441],"087c46fa":[()=>n.e(96).then(n.t.bind(n,25774,19)),"~blog/default/tags-spring-boot-889.json",25774],"08e37dbc":[()=>n.e(1328).then(n.bind(n,95883)),"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",95883],"09fbb6bd":[()=>n.e(5964).then(n.t.bind(n,41679,19)),"~blog/default/page-16-d6c.json",41679],"0a2eaa84":[()=>n.e(8942).then(n.t.bind(n,52930,19)),"~blog/default/tags-data-base-4e8.json",52930],"0c071de2":[()=>n.e(321).then(n.t.bind(n,23125,19)),"~blog/default/page-2-b45.json",23125],"0c390f0d":[()=>n.e(6550).then(n.t.bind(n,13321,19)),"~blog/default/tags-retrospective-page-19-af8.json",13321],"0cb009d1":[()=>n.e(116).then(n.t.bind(n,66643,19)),"~blog/default/tags-event-f04.json",66643],"0e33a907":[()=>n.e(3092).then(n.bind(n,33520)),"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx?truncated=true",33520],"101b58de":[()=>n.e(6084).then(n.bind(n,86942)),"@site/blog/2023-1/2023-01-08-JSR-310.mdx",86942],"101cf32b":[()=>n.e(9239).then(n.t.bind(n,30880,19)),"~blog/default/page-45-7ec.json",30880],"1236fad7":[()=>n.e(6515).then(n.bind(n,38491)),"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",38491],"1251d98b":[()=>n.e(6276).then(n.bind(n,40469)),"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",40469],"12cbeba7":[()=>n.e(6508).then(n.t.bind(n,16134,19)),"~blog/default/page-29-e3c.json",16134],"130df38c":[()=>n.e(6493).then(n.bind(n,83278)),"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",83278],"1398b403":[()=>n.e(5652).then(n.t.bind(n,93561,19)),"~blog/default/tags-retrospective-page-20-737.json",93561],14164549:[()=>n.e(7268).then(n.t.bind(n,11279,19)),"~blog/default/tags-book-baf-list.json",11279],"14dc1923":[()=>n.e(7403).then(n.bind(n,40742)),"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",40742],"15eddcef":[()=>n.e(4209).then(n.t.bind(n,28539,19)),"~blog/default/page-47-adb.json",28539],"15f27552":[()=>n.e(1079).then(n.t.bind(n,11539,19)),"~blog/default/tags-retrospective-page-19-af8-list.json",11539],"1664646a":[()=>n.e(8036).then(n.bind(n,60367)),"@site/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx?truncated=true",60367],"16cc6f3a":[()=>n.e(425).then(n.t.bind(n,12946,19)),"~blog/default/tags-retrospective-page-15-26b.json",12946],"16f719ab":[()=>n.e(9875).then(n.bind(n,3081)),"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",3081],"1781b1c4":[()=>n.e(5785).then(n.bind(n,16865)),"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",16865],17896441:[()=>Promise.all([n.e(532),n.e(4926),n.e(7918)]).then(n.bind(n,78945)),"@theme/DocItem",78945],"1893cb59":[()=>n.e(286).then(n.t.bind(n,16269,19)),"~blog/default/tags-java-page-2-8c6.json",16269],"18c69d70":[()=>n.e(9171).then(n.t.bind(n,7085,19)),"/home/runner/work/greeng00se.github.io/greeng00se.github.io/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json",7085],"198f8d8a":[()=>n.e(9059).then(n.t.bind(n,17238,19)),"~blog/default/tags-java-page-3-b02-list.json",17238],"19f4ae8e":[()=>n.e(8161).then(n.t.bind(n,25680,19)),"~blog/default/tags-log-5ad.json",25680],"1a3abee6":[()=>n.e(5035).then(n.t.bind(n,87753,19)),"~blog/default/tags-retrospective-page-17-636.json",87753],"1a4e3797":[()=>Promise.all([n.e(532),n.e(7920)]).then(n.bind(n,39172)),"@theme/SearchPage",39172],"1a665c6f":[()=>n.e(454).then(n.t.bind(n,28767,19)),"~blog/default/tags-test-435-list.json",28767],"1a6b9123":[()=>n.e(9874).then(n.t.bind(n,14343,19)),"~blog/default/tags-teco-chat-page-3-007.json",14343],"1bb997fc":[()=>n.e(9713).then(n.t.bind(n,66014,19)),"~blog/default/page-44-cef.json",66014],"1c93669b":[()=>n.e(6526).then(n.t.bind(n,37579,19)),"~docs/default/tag-docs-tags-monitoring-149.json",37579],"1d81daa1":[()=>n.e(7681).then(n.t.bind(n,76725,19)),"~blog/default/tags-mock-330.json",76725],"1e8ecffe":[()=>n.e(3333).then(n.bind(n,58307)),"@site/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx",58307],"1f05d14a":[()=>Promise.all([n.e(532),n.e(656)]).then(n.bind(n,9938)),"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx?truncated=true",9938],"1f61820a":[()=>n.e(2233).then(n.bind(n,74123)),"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx?truncated=true",74123],"1fbde614":[()=>n.e(8243).then(n.t.bind(n,87304,19)),"~blog/default/tags-monitoring-a8a-list.json",87304],"20e99c2a":[()=>n.e(3530).then(n.t.bind(n,19507,19)),"~blog/default/tags-documentation-ee3-list.json",19507],"211d6170":[()=>n.e(3109).then(n.t.bind(n,41078,19)),"~docs/default/tag-docs-tags-package-d2b.json",41078],"21294bbb":[()=>n.e(9412).then(n.bind(n,72794)),"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",72794],"21d253a0":[()=>n.e(1853).then(n.t.bind(n,63986,19)),"~blog/default/tags-woowahan-techcourse-page-10-f03-list.json",63986],"21e890b0":[()=>n.e(8288).then(n.t.bind(n,551,19)),"~blog/default/tags-retrospective-page-14-99d-list.json",551],"226700de":[()=>n.e(6035).then(n.t.bind(n,41961,19)),"~blog/default/page-25-52d.json",41961],"24b9bc70":[()=>n.e(5798).then(n.bind(n,58346)),"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",58346],"255134d9":[()=>n.e(8151).then(n.t.bind(n,30753,19)),"~blog/default/tags-composite-240.json",30753],"269a2f75":[()=>n.e(1994).then(n.t.bind(n,52358,19)),"~blog/default/tags-static-b68.json",52358],"26dc40bf":[()=>n.e(5237).then(n.bind(n,55338)),"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx?truncated=true",55338],"270346fa":[()=>n.e(7975).then(n.t.bind(n,89424,19)),"~blog/default/page-28-907.json",89424],"274c9143":[()=>n.e(6984).then(n.t.bind(n,90058,19)),"~blog/default/tags-java-a6e.json",90058],"280572f1":[()=>n.e(324).then(n.t.bind(n,77874,19)),"~blog/default/tags-mysql-331.json",77874],"2832e534":[()=>n.e(2476).then(n.t.bind(n,69870,19)),"~blog/default/page-13-99f.json",69870],"28a1570f":[()=>n.e(448).then(n.t.bind(n,92252,19)),"~blog/default/tags-elastic-beanstalk-119.json",92252],"290b0a56":[()=>n.e(4212).then(n.bind(n,37260)),"@site/docs/Java/SequencedCollection.mdx",37260],"2a8faff0":[()=>n.e(7901).then(n.t.bind(n,1150,19)),"~blog/default/tags-test-435.json",1150],"2b22d492":[()=>n.e(7652).then(n.t.bind(n,56986,19)),"~blog/default/tags-retrospective-page-3-ee4-list.json",56986],"2b479afe":[()=>n.e(9591).then(n.t.bind(n,16973,19)),"~blog/default/tags-mockito-3c0-list.json",16973],"2bfe7c0b":[()=>n.e(1762).then(n.t.bind(n,82670,19)),"~blog/default/tags-book-page-2-bc6.json",82670],"2c446262":[()=>n.e(7797).then(n.t.bind(n,16402,19)),"~docs/default/tag-docs-tags-collection-64e.json",16402],"2c9f5501":[()=>n.e(7775).then(n.bind(n,75040)),"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx?truncated=true",75040],"2d3b202f":[()=>n.e(1196).then(n.t.bind(n,42524,19)),"~blog/default/tags-book-baf.json",42524],"2d9296e4":[()=>n.e(3483).then(n.t.bind(n,89429,19)),"~blog/default/tags-pattern-b4e.json",89429],"2e10a69c":[()=>n.e(7581).then(n.t.bind(n,9981,19)),"~blog/default/page-38-d34.json",9981],"2f43e44a":[()=>n.e(6743).then(n.t.bind(n,52396,19)),"~blog/default/tags-grasp-418-list.json",52396],"302370be":[()=>n.e(1883).then(n.bind(n,21779)),"@site/docs/\ud14c\uc2a4\ud2b8/FIRST.mdx",21779],"303c1e60":[()=>n.e(2656).then(n.t.bind(n,39529,19)),"~blog/default/tags-retrospective-page-4-3a3.json",39529],"309173fa":[()=>n.e(1793).then(n.t.bind(n,22684,19)),"~blog/default/tags-data-base-4e8-list.json",22684],"32397cb2":[()=>n.e(548).then(n.t.bind(n,22050,19)),"~blog/default/tags-awt-page-2-eb4-list.json",22050],"327fa616":[()=>n.e(3407).then(n.bind(n,79748)),"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",79748],"32b2299c":[()=>n.e(970).then(n.t.bind(n,5280,19)),"~blog/default/page-41-fe1.json",5280],33736670:[()=>n.e(2742).then(n.t.bind(n,80700,19)),"~blog/default/tags-class-eca.json",80700],"35293ec4":[()=>n.e(7697).then(n.t.bind(n,14,19)),"~blog/default/page-20-038.json",14],"35b2eb5a":[()=>n.e(372).then(n.t.bind(n,97815,19)),"~blog/default/tags-java-page-5-b71-list.json",97815],"366ddb85":[()=>n.e(3691).then(n.bind(n,33751)),"@site/docs/\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30.mdx",33751],"3680bd07":[()=>n.e(5173).then(n.t.bind(n,2003,19)),"~blog/default/tags-web-application-b52.json",2003],"3720c009":[()=>Promise.all([n.e(532),n.e(3751)]).then(n.bind(n,10727)),"@theme/DocTagsListPage",10727],"372ccfe9":[()=>n.e(9111).then(n.bind(n,21063)),"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx?truncated=true",21063],"38bf29ad":[()=>n.e(1285).then(n.t.bind(n,26514,19)),"~docs/default/tag-docs-tags-load-balancing-180.json",26514],"38d8699e":[()=>n.e(471).then(n.t.bind(n,97481,19)),"~blog/default/page-15-208.json",97481],"3972c49f":[()=>n.e(6629).then(n.t.bind(n,91782,19)),"~blog/default/tags-web-socket-c6e-list.json",91782],"39ee6679":[()=>n.e(5717).then(n.t.bind(n,83636,19)),"~blog/default/tags-woowahan-techcourse-b50.json",83636],"3b0f99e8":[()=>n.e(3553).then(n.t.bind(n,20034,19)),"~blog/default/tags-jenkins-2e5.json",20034],"3b12d42b":[()=>n.e(8107).then(n.t.bind(n,50244,19)),"~docs/default/tag-docs-tags-java-ce1.json",50244],"3b18521e":[()=>n.e(2773).then(n.t.bind(n,8086,19)),"~blog/default/tags-mockito-3c0.json",8086],"3c5aea38":[()=>n.e(6250).then(n.t.bind(n,56516,19)),"~blog/default/tags-retrospective-page-12-8cf.json",56516],"3c9c1743":[()=>n.e(5900).then(n.t.bind(n,1353,19)),"~blog/default/tags-woowahan-techcourse-page-15-e2a-list.json",1353],"3d6c40c1":[()=>n.e(8509).then(n.t.bind(n,3440,19)),"~blog/default/tags-monitoring-a8a.json",3440],"3dd4d232":[()=>n.e(7727).then(n.bind(n,22195)),"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",22195],"3ed04b60":[()=>n.e(7157).then(n.t.bind(n,84792,19)),"~blog/default/tags-spring-de1.json",84792],"3f6ea930":[()=>n.e(5186).then(n.bind(n,74818)),"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx",74818],"41b4728f":[()=>n.e(8628).then(n.t.bind(n,30171,19)),"~blog/default/tags-spring-boot-889-list.json",30171],"41c44b28":[()=>n.e(8106).then(n.bind(n,8819)),"@site/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd.mdx",8819],"42957a8d":[()=>n.e(9312).then(n.bind(n,62206)),"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",62206],"43a97218":[()=>n.e(4815).then(n.t.bind(n,65215,19)),"~blog/default/tags-retrospective-page-5-22d-list.json",65215],"43fcf0e9":[()=>n.e(6468).then(n.t.bind(n,94822,19)),"~blog/default/tags-woowahan-techcourse-page-9-065.json",94822],"4430ab79":[()=>n.e(5553).then(n.t.bind(n,2750,19)),"~docs/default/tag-docs-tags-zero-downtime-b1f.json",2750],"4485017c":[()=>n.e(1906).then(n.bind(n,36169)),"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",36169],"448c20a0":[()=>n.e(7680).then(n.bind(n,14079)),"@site/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md",14079],"4515250b":[()=>n.e(9304).then(n.t.bind(n,88767,19)),"~blog/default/tags-exception-644-list.json",88767],"451db21d":[()=>n.e(1475).then(n.bind(n,71904)),"@site/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uaddc\uce59.mdx",71904],"454a6d0d":[()=>n.e(4104).then(n.bind(n,98592)),"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",98592],"489347ff":[()=>n.e(2793).then(n.t.bind(n,40526,19)),"~blog/default/tags-web-socket-c6e.json",40526],"48faf148":[()=>n.e(7328).then(n.bind(n,50973)),"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx?truncated=true",50973],"492a6565":[()=>n.e(9702).then(n.t.bind(n,44929,19)),"~blog/default/tags-lock-page-2-819-list.json",44929],"494882d1":[()=>n.e(4471).then(n.t.bind(n,2098,19)),"~blog/default/page-37-cb2.json",2098],"4959fc42":[()=>n.e(240).then(n.t.bind(n,80897,19)),"~blog/default/page-14-0a2.json",80897],"49b8d9dd":[()=>n.e(1103).then(n.t.bind(n,64420,19)),"~blog/default/tags-inno-db-59e.json",64420],"49f0f498":[()=>n.e(4433).then(n.t.bind(n,40719,19)),"~blog/default/tags-retrospective-page-16-226.json",40719],"4a1c8300":[()=>n.e(3324).then(n.bind(n,74122)),"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",74122],"4b2fba3e":[()=>n.e(328).then(n.t.bind(n,98234,19)),"~blog/default/tags-image-page-3-942-list.json",98234],"4b79a3c9":[()=>Promise.all([n.e(532),n.e(5838)]).then(n.bind(n,261)),"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",261],"4d43abad":[()=>n.e(3365).then(n.bind(n,79766)),"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx?truncated=true",79766],"5088fe06":[()=>n.e(80).then(n.t.bind(n,86819,19)),"~blog/default/tags-log-5ad-list.json",86819],"509d519c":[()=>n.e(743).then(n.t.bind(n,24469,19)),"/home/runner/work/greeng00se.github.io/greeng00se.github.io/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json",24469],"52106a5f":[()=>n.e(9396).then(n.bind(n,68973)),"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx?truncated=true",68973],"530ffa4f":[()=>n.e(4818).then(n.bind(n,17804)),"@site/blog/2023-4/2023-10-31-\ub808\uac70\uc2dc \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",17804],"533bfc57":[()=>n.e(5100).then(n.t.bind(n,4371,19)),"~blog/default/tags-retrospective-page-2-e2b-list.json",4371],"537817cb":[()=>n.e(3457).then(n.bind(n,75088)),"@site/blog/2023-1/2023-01-08-JSR-310.mdx?truncated=true",75088],"53e4509a":[()=>n.e(4722).then(n.t.bind(n,32259,19)),"~blog/default/page-46-6b3.json",32259],"54150be7":[()=>n.e(5088).then(n.t.bind(n,98707,19)),"~blog/default/tags-java-page-2-8c6-list.json",98707],"546ec22f":[()=>n.e(5635).then(n.t.bind(n,34223,19)),"~blog/default/tags-performance-test-2b7.json",34223],"54cb095e":[()=>n.e(7009).then(n.t.bind(n,95159,19)),"~blog/default/page-26-a44.json",95159],"55960ee5":[()=>n.e(4121).then(n.t.bind(n,88070,19)),"~docs/default/tags-list-current-prop-15a.json",88070],"562496aa":[()=>n.e(6161).then(n.t.bind(n,68146,19)),"~blog/default/tags-image-page-2-cc3.json",68146],"564337ec":[()=>n.e(5649).then(n.t.bind(n,8563,19)),"~blog/default/tags-retrospective-page-7-3e2-list.json",8563],"56e576e5":[()=>n.e(8262).then(n.t.bind(n,86556,19)),"~blog/default/tags-performance-test-2b7-list.json",86556],"5a29fbab":[()=>n.e(7857).then(n.t.bind(n,25381,19)),"~blog/default/tags-woowahan-techcourse-b50-list.json",25381],"5a473bed":[()=>n.e(9686).then(n.bind(n,52857)),"@site/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",52857],"5a6c6934":[()=>n.e(5953).then(n.t.bind(n,48630,19)),"~blog/default/tags-dto-cb6.json",48630],"5c07bdab":[()=>n.e(6300).then(n.bind(n,50701)),"@site/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",50701],"5c38e66e":[()=>n.e(5521).then(n.t.bind(n,28638,19)),"~blog/default/tags-woowahan-techcourse-page-10-f03.json",28638],"5d4cff52":[()=>n.e(1252).then(n.bind(n,88653)),"@site/blog/2023-4/2023-10-07-MVC \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",88653],"5e95c892":[()=>n.e(9661).then(n.bind(n,41892)),"@theme/DocsRoot",41892],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,36809)),"@generated/docusaurus.config",36809],"5eed1665":[()=>n.e(8142).then(n.t.bind(n,19729,19)),"~blog/default/tags-lock-529-list.json",19729],"5f81b25c":[()=>n.e(4889).then(n.t.bind(n,29492,19)),"~blog/default/page-27-eb3.json",29492],"5feaaaeb":[()=>n.e(2967).then(n.t.bind(n,49978,19)),"~blog/default/tags-retrospective-page-20-737-list.json",49978],"5ffd2c10":[()=>n.e(2100).then(n.t.bind(n,86515,19)),"~docs/default/tag-docs-tags-jpa-c8c.json",86515],"6093f82b":[()=>n.e(6017).then(n.t.bind(n,30708,19)),"~blog/default/page-9-361.json",30708],"633582b9":[()=>n.e(2448).then(n.t.bind(n,32401,19)),"~blog/default/tags-kotlin-6ac.json",32401],"635a92d5":[()=>n.e(7891).then(n.t.bind(n,72126,19)),"~blog/default/page-24-fbb.json",72126],"6412e40a":[()=>n.e(5421).then(n.t.bind(n,97677,19)),"~blog/default/tags-woowahan-techcourse-page-12-5ba-list.json",97677],"6425a984":[()=>n.e(5467).then(n.t.bind(n,95377,19)),"~blog/default/tags-woowahan-techcourse-page-4-bcd-list.json",95377],"64868a43":[()=>n.e(1501).then(n.t.bind(n,33159,19)),"~blog/default/page-39-76c.json",33159],"64f377d6":[()=>n.e(732).then(n.t.bind(n,62898,19)),"~blog/default/tags-woowahan-techcourse-page-11-6c9-list.json",62898],"6552f31f":[()=>n.e(917).then(n.bind(n,84112)),"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",84112],"6675e9ab":[()=>n.e(1255).then(n.bind(n,29218)),"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",29218],"66d1c769":[()=>n.e(7476).then(n.t.bind(n,80122,19)),"~blog/default/tags-data-base-page-2-3a7-list.json",80122],"672a376b":[()=>n.e(2579).then(n.t.bind(n,41690,19)),"~blog/default/tags-woowahan-techcourse-page-8-93a.json",41690],"6875c492":[()=>Promise.all([n.e(532),n.e(4926),n.e(130),n.e(8610)]).then(n.bind(n,41714)),"@theme/BlogTagsPostsPage",41714],"69a75ff2":[()=>n.e(7181).then(n.t.bind(n,12761,19)),"~blog/default/page-48-ebc.json",12761],"69c28c32":[()=>n.e(1065).then(n.t.bind(n,99263,19)),"~blog/default/page-36-1da.json",99263],"6a19354d":[()=>n.e(693).then(n.t.bind(n,36232,19)),"~blog/default/tags-lock-529.json",36232],"6b4e1191":[()=>n.e(838).then(n.bind(n,88078)),"@site/docs/\uae30\ud0c0/\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30.mdx",88078],"6b54f6a4":[()=>Promise.all([n.e(532),n.e(4558)]).then(n.bind(n,57211)),"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx?truncated=true",57211],"6b69808d":[()=>n.e(5990).then(n.bind(n,35703)),"@site/docs/JPA/\uae30\ubcf8 \ud0a4 \ub9e4\ud551.mdx",35703],"6ba49b42":[()=>n.e(498).then(n.t.bind(n,64450,19)),"~blog/default/tags-test-page-2-d33-list.json",64450],"6bc709ad":[()=>n.e(9393).then(n.t.bind(n,81399,19)),"~blog/default/tags-retrospective-page-6-594-list.json",81399],"6c38e270":[()=>n.e(7247).then(n.t.bind(n,51914,19)),"~docs/default/tag-docs-tags-sequenced-12d.json",51914],"6c674d03":[()=>n.e(7600).then(n.t.bind(n,80372,19)),"~docs/default/tag-docs-tags-network-cb4.json",80372],"6cfe3a99":[()=>n.e(5319).then(n.t.bind(n,91227,19)),"~blog/default/tags-cloudwatch-6c7-list.json",91227],"6d4355d3":[()=>n.e(3122).then(n.t.bind(n,37438,19)),"~blog/default/tags-async-page-2-246.json",37438],"6dd1c948":[()=>n.e(7064).then(n.t.bind(n,76376,19)),"~blog/default/page-34-16c.json",76376],"6f385a52":[()=>n.e(6608).then(n.bind(n,54413)),"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx?truncated=true",54413],"70275fcd":[()=>n.e(7412).then(n.t.bind(n,81191,19)),"~blog/default/page-42-ca9.json",81191],70834889:[()=>n.e(7344).then(n.bind(n,56135)),"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx?truncated=true",56135],"70a12cc4":[()=>n.e(5682).then(n.t.bind(n,17085,19)),"~blog/default/tags-static-b68-list.json",17085],"7159c7ff":[()=>n.e(3287).then(n.bind(n,67219)),"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx?truncated=true",67219],"72657f57":[()=>n.e(9581).then(n.bind(n,32262)),"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",32262],"73688d5c":[()=>n.e(6908).then(n.bind(n,90465)),"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx?truncated=true",90465],"7405ea58":[()=>n.e(2345).then(n.t.bind(n,40702,19)),"~blog/default/tags-retrospective-page-11-e3c-list.json",40702],"75121fd5":[()=>n.e(5335).then(n.t.bind(n,30674,19)),"~blog/default/tags-image-97d.json",30674],"754fb852":[()=>n.e(988).then(n.t.bind(n,38242,19)),"~blog/default/page-32-596.json",38242],"75f50328":[()=>n.e(7511).then(n.t.bind(n,58695,19)),"~blog/default/tags-mysql-331-list.json",58695],"7762a24e":[()=>n.e(2753).then(n.t.bind(n,55095,19)),"~blog/default/page-4-365.json",55095],"77f5fc5d":[()=>n.e(3625).then(n.t.bind(n,32215,19)),"~blog/default/tags-retrospective-page-16-226-list.json",32215],"7881a85f":[()=>n.e(7108).then(n.t.bind(n,1855,19)),"~blog/default/page-51-74a.json",1855],"79a97f4e":[()=>n.e(6412).then(n.bind(n,13408)),"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx?truncated=true",13408],"7af1d52f":[()=>n.e(2334).then(n.t.bind(n,59565,19)),"~blog/default/page-6-d10.json",59565],"7bbc420e":[()=>n.e(4311).then(n.t.bind(n,41691,19)),"~blog/default/tags-documentation-ee3.json",41691],"7c660760":[()=>n.e(2087).then(n.t.bind(n,91870,19)),"~blog/default/tags-woowahan-techcourse-page-9-065-list.json",91870],"7e4c1ed7":[()=>n.e(1653).then(n.t.bind(n,83297,19)),"~docs/default/tag-docs-tags-postmortem-ede.json",83297],"7e59392d":[()=>n.e(7281).then(n.t.bind(n,33202,19)),"~blog/default/tags-retrospective-page-9-473-list.json",33202],"7fbacf84":[()=>n.e(5797).then(n.t.bind(n,58701,19)),"~blog/default/tags-spring-de1-list.json",58701],"7fd9a574":[()=>n.e(2889).then(n.t.bind(n,5863,19)),"~blog/default/tags-retrospective-page-14-99d.json",5863],"80960b4b":[()=>n.e(7599).then(n.t.bind(n,28386,19)),"~blog/default/page-21-7a8.json",28386],"814f3328":[()=>n.e(2535).then(n.t.bind(n,45641,19)),"~blog/default/blog-post-list-prop-default.json",45641],"829fa7b9":[()=>n.e(9391).then(n.bind(n,4565)),"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",4565],"86b4da3d":[()=>n.e(952).then(n.t.bind(n,44149,19)),"~blog/default/tags-woowahan-techcourse-page-2-567.json",44149],"87070fc3":[()=>n.e(6124).then(n.bind(n,4679)),"@site/docs/\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",4679],"871c1e5a":[()=>n.e(5966).then(n.t.bind(n,71247,19)),"~blog/default/page-23-651.json",71247],"8720c147":[()=>n.e(470).then(n.bind(n,75712)),"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",75712],"8a24850b":[()=>n.e(741).then(n.bind(n,86331)),"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",86331],"8a27aeff":[()=>n.e(71).then(n.bind(n,57041)),"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx?truncated=true",57041],"8ad2f007":[()=>n.e(8360).then(n.bind(n,6073)),"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx?truncated=true",6073],"8b79a48d":[()=>n.e(9287).then(n.t.bind(n,59070,19)),"~blog/default/tags-retrospective-page-9-473.json",59070],"8c6c0796":[()=>n.e(2816).then(n.t.bind(n,59123,19)),"~blog/default/tags-retrospective-2fb.json",59123],"8d05b77c":[()=>n.e(4149).then(n.t.bind(n,22801,19)),"~blog/default/page-5-264.json",22801],"8d7288fe":[()=>n.e(4801).then(n.t.bind(n,71830,19)),"~blog/default/tags-class-eca-list.json",71830],"8da65e83":[()=>n.e(9427).then(n.t.bind(n,1341,19)),"~blog/default/tags-woowahan-techcourse-page-4-bcd.json",1341],"8dc09bac":[()=>n.e(8338).then(n.t.bind(n,28881,19)),"~blog/default/tags-event-f04-list.json",28881],"8e498bb6":[()=>n.e(1436).then(n.t.bind(n,50257,19)),"~blog/default/tags-java-page-3-b02.json",50257],"8e9dc6b3":[()=>n.e(7709).then(n.t.bind(n,65548,19)),"~blog/default/tags-web-application-b52-list.json",65548],"8fbd512b":[()=>n.e(5873).then(n.t.bind(n,15,19)),"~blog/default/tags-async-326.json",15],"905ecccc":[()=>Promise.all([n.e(532),n.e(2939)]).then(n.bind(n,76306)),"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",76306],"92ade856":[()=>Promise.all([n.e(532),n.e(1772)]).then(n.bind(n,31824)),"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx?truncated=true",31824],"92fef07b":[()=>n.e(300).then(n.bind(n,41632)),"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",41632],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"96adae60":[()=>n.e(172).then(n.t.bind(n,54217,19)),"~blog/default/page-19-21b.json",54217],"981f7647":[()=>n.e(2947).then(n.bind(n,52070)),"@site/docs/\uc124\uacc4/\ud328\ud0a4\uc9c0.mdx",52070],"9b43eac8":[()=>n.e(9286).then(n.bind(n,8617)),"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",8617],"9b56b618":[()=>n.e(9538).then(n.t.bind(n,37e3,19)),"~blog/default/tags-awt-0e2-list.json",37e3],"9bad5ae7":[()=>n.e(2153).then(n.bind(n,27555)),"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx?truncated=true",27555],"9bbc65ac":[()=>n.e(7210).then(n.t.bind(n,51020,19)),"~docs/default/tag-docs-tags-test-8ab.json",51020],"9c6e5a12":[()=>n.e(2145).then(n.bind(n,81145)),"@site/docs/\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.mdx",81145],"9ca52986":[()=>n.e(3490).then(n.t.bind(n,92016,19)),"~blog/default/tags-lock-page-2-819.json",92016],"9cfe8fd1":[()=>n.e(7725).then(n.t.bind(n,97113,19)),"~blog/default/page-18-46d.json",97113],"9d1fd2b0":[()=>n.e(7972).then(n.bind(n,30138)),"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",30138],"9d8ee3a8":[()=>n.e(5962).then(n.t.bind(n,71297,19)),"~blog/default/tags-oop-03c.json",71297],"9dc4119a":[()=>n.e(6490).then(n.t.bind(n,4408,19)),"~blog/default/tags-retrospective-page-10-4a6-list.json",4408],"9dec6b67":[()=>n.e(8524).then(n.t.bind(n,88221,19)),"~blog/default/tags-data-base-page-2-3a7.json",88221],"9e2e3982":[()=>n.e(7617).then(n.bind(n,15448)),"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",15448],"9e4087bc":[()=>n.e(3608).then(n.bind(n,63169)),"@theme/BlogArchivePage",63169],"9e4ad429":[()=>n.e(5406).then(n.t.bind(n,16060,19)),"~docs/default/tag-docs-tags-performance-339.json",16060],"9f586ca3":[()=>n.e(3673).then(n.t.bind(n,41912,19)),"~blog/default/tags-async-page-2-246-list.json",41912],"9fae68e2":[()=>n.e(297).then(n.t.bind(n,77536,19)),"~blog/default/tags-kotlin-6ac-list.json",77536],a0410ab5:[()=>n.e(7843).then(n.t.bind(n,76970,19)),"~blog/default/tags-retrospective-page-7-3e2.json",76970],a14ec7b5:[()=>n.e(3833).then(n.bind(n,44720)),"@site/docs/\ud14c\uc2a4\ud2b8/\uacc4\ub2e8 \ud14c\uc2a4\ud2b8.mdx",44720],a1877440:[()=>n.e(7648).then(n.t.bind(n,23235,19)),"~blog/default/tags-async-326-list.json",23235],a3614f73:[()=>n.e(8474).then(n.bind(n,15899)),"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",15899],a3dddb77:[()=>n.e(475).then(n.t.bind(n,5479,19)),"~blog/default/tags-java-page-4-c22.json",5479],a4349a81:[()=>n.e(9623).then(n.t.bind(n,32318,19)),"~blog/default/tags-woowahan-techcourse-page-15-e2a.json",32318],a4a1e915:[()=>n.e(3671).then(n.t.bind(n,60166,19)),"~blog/default/tags-retrospective-2fb-list.json",60166],a539c018:[()=>n.e(5758).then(n.t.bind(n,99844,19)),"~blog/default/tags-woowahan-techcourse-page-16-b44.json",99844],a5557bb9:[()=>n.e(5991).then(n.t.bind(n,93885,19)),"~blog/default/index.json",93885],a59d28a9:[()=>n.e(2012).then(n.bind(n,63600)),"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx?truncated=true",63600],a6aa9e1f:[()=>Promise.all([n.e(532),n.e(4926),n.e(130),n.e(3089)]).then(n.bind(n,80046)),"@theme/BlogListPage",80046],a710d533:[()=>Promise.all([n.e(532),n.e(1711)]).then(n.bind(n,42089)),"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",42089],a7bd4aaa:[()=>n.e(8518).then(n.bind(n,8564)),"@theme/DocVersionRoot",8564],a7e0d18f:[()=>n.e(3519).then(n.t.bind(n,59462,19)),"~docs/default/tag-docs-tags-spring-3d9.json",59462],a85e626a:[()=>n.e(9092).then(n.t.bind(n,48458,19)),"~blog/default/tags-jdbc-4bd.json",48458],a896be03:[()=>n.e(2526).then(n.t.bind(n,64030,19)),"~blog/default/tags-woowahan-techcourse-page-6-429.json",64030],a8cba70f:[()=>n.e(2261).then(n.bind(n,58367)),"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx?truncated=true",58367],a9221bd5:[()=>n.e(5507).then(n.t.bind(n,40319,19)),"~blog/default/tags-inno-db-59e-list.json",40319],a94703ab:[()=>Promise.all([n.e(532),n.e(4368)]).then(n.bind(n,12674)),"@theme/DocRoot",12674],a9c2b81a:[()=>n.e(2266).then(n.t.bind(n,52882,19)),"~blog/default/tags-woowahan-techcourse-page-16-b44-list.json",52882],aa73a035:[()=>n.e(5371).then(n.bind(n,54717)),"@site/docs/\ub370\uc774\ud130\ubca0\uc774\uc2a4/Connection Pool.mdx",54717],aacfeabc:[()=>n.e(8909).then(n.bind(n,60965)),"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx?truncated=true",60965],abb0816f:[()=>n.e(4174).then(n.t.bind(n,82969,19)),"~blog/default/tags-woowahan-techcourse-page-7-5bd-list.json",82969],abc83b7f:[()=>n.e(2215).then(n.t.bind(n,8412,19)),"~blog/default/tags-retrospective-page-2-e2b.json",8412],ac23d7ee:[()=>n.e(3213).then(n.t.bind(n,43943,19)),"~blog/default/tags-woowahan-techcourse-page-3-9a8-list.json",43943],ac3fdf5d:[()=>n.e(8548).then(n.bind(n,40911)),"@site/blog/2023-3/2023-09-30-\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubc1c\uc804 \uacfc\uc815.mdx",40911],ad3b7b62:[()=>n.e(26).then(n.bind(n,76556)),"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",76556],ae1d6508:[()=>n.e(2181).then(n.t.bind(n,83486,19)),"~blog/default/tags-composite-240-list.json",83486],ae3384b2:[()=>n.e(2965).then(n.t.bind(n,15745,19)),"/home/runner/work/greeng00se.github.io/greeng00se.github.io/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json",15745],ae82353f:[()=>n.e(6420).then(n.bind(n,96046)),"@site/blog/2023-4/2023-10-03-\ud14c\uc2a4\ud2b8 \uaca9\ub9ac.md?truncated=true",96046],af81a133:[()=>n.e(7787).then(n.t.bind(n,13800,19)),"~blog/default/tags-teco-chat-d21.json",13800],b2b675dd:[()=>n.e(533).then(n.t.bind(n,28017,19)),"~blog/default/blog-c06.json",28017],b2c8756c:[()=>n.e(1213).then(n.bind(n,80936)),"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",80936],b2ebb6fd:[()=>n.e(4091).then(n.bind(n,8343)),"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",8343],b301b20b:[()=>n.e(3637).then(n.t.bind(n,83150,19)),"~blog/default/tags-replication-56b.json",83150],b36d2d1d:[()=>n.e(1257).then(n.t.bind(n,7903,19)),"~docs/default/tag-docs-tags-latency-735.json",7903],b41adc00:[()=>n.e(1391).then(n.bind(n,33849)),"@site/blog/2023-4/2023-10-10-Jdbc \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",33849],b421ebb7:[()=>n.e(9055).then(n.bind(n,37058)),"@site/docs/\uc131\ub2a5/Throughput\uacfc Latency.mdx",37058],b474adfe:[()=>n.e(573).then(n.t.bind(n,85419,19)),"~blog/default/tags-image-page-2-cc3-list.json",85419],b5f3dcc5:[()=>n.e(7723).then(n.t.bind(n,23005,19)),"~blog/default/tags-retrospective-page-15-26b-list.json",23005],b6ffb0cb:[()=>n.e(2156).then(n.bind(n,1738)),"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",1738],b7d33121:[()=>n.e(7153).then(n.t.bind(n,72005,19)),"~blog/default/tags-cloudwatch-6c7.json",72005],b88cb85b:[()=>n.e(2293).then(n.bind(n,95864)),"@site/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998.mdx",95864],b9bcab37:[()=>n.e(7688).then(n.t.bind(n,43632,19)),"~blog/default/tags-grasp-418.json",43632],bace0b37:[()=>n.e(2362).then(n.bind(n,10795)),"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",10795],bb221eab:[()=>n.e(711).then(n.bind(n,98886)),"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx?truncated=true",98886],bbc01ba0:[()=>n.e(3009).then(n.t.bind(n,12333,19)),"~blog/default/tags-retrospective-page-10-4a6.json",12333],bbc3f62a:[()=>n.e(8894).then(n.t.bind(n,51842,19)),"~blog/default/tags-woowahan-techcourse-page-13-8ae-list.json",51842],bbceb8f1:[()=>n.e(653).then(n.t.bind(n,26529,19)),"~blog/default/tags-woowahan-techcourse-page-5-ac5-list.json",26529],bbdd7e52:[()=>n.e(3396).then(n.bind(n,49725)),"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",49725],bd2d06b5:[()=>n.e(9763).then(n.t.bind(n,93081,19)),"~blog/default/tags-retrospective-page-3-ee4.json",93081],bd4db8ee:[()=>n.e(6883).then(n.bind(n,64855)),"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",64855],bd64a762:[()=>n.e(5463).then(n.bind(n,11365)),"@site/docs/\ub370\uc774\ud130\ubca0\uc774\uc2a4/\ucffc\ub9ac \uc2e4\ud589 \uad6c\uc870.mdx",11365],be497a8d:[()=>n.e(6172).then(n.bind(n,92971)),"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx?truncated=true",92971],bf933b37:[()=>n.e(3095).then(n.t.bind(n,52954,19)),"~blog/default/tags-my-sql-46a-list.json",52954],c037d168:[()=>n.e(6587).then(n.t.bind(n,41235,19)),"~blog/default/tags-transaction-ea3-list.json",41235],c08e7a0d:[()=>n.e(7404).then(n.t.bind(n,27625,19)),"~docs/default/tag-docs-tags-throughput-8fc.json",27625],c0cb7215:[()=>n.e(7966).then(n.t.bind(n,66109,19)),"~blog/default/tags-book-page-2-bc6-list.json",66109],c189d18f:[()=>n.e(4962).then(n.t.bind(n,3470,19)),"~docs/default/tag-docs-tags-etc-c52.json",3470],c1b17b3f:[()=>n.e(8927).then(n.bind(n,46681)),"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",46681],c29bedb9:[()=>n.e(9242).then(n.t.bind(n,44025,19)),"~blog/default/page-35-8fd.json",44025],c3ea66fe:[()=>n.e(6698).then(n.t.bind(n,63504,19)),"~blog/default/tags-isolation-79d.json",63504],c4f5d8e4:[()=>n.e(4195).then(n.bind(n,62841)),"@site/src/pages/index.js",62841],c55d205b:[()=>n.e(3438).then(n.bind(n,36712)),"@site/docs/Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4.mdx",36712],c573638f:[()=>n.e(964).then(n.t.bind(n,28866,19)),"~blog/default/tags-tags-c2b.json",28866],c6004f62:[()=>n.e(5892).then(n.t.bind(n,37567,19)),"~blog/default/tags-mock-330-list.json",37567],c60995f6:[()=>n.e(6199).then(n.t.bind(n,62474,19)),"~docs/default/tag-docs-tags-nginx-3b7.json",62474],c60ea0ff:[()=>n.e(3085).then(n.t.bind(n,14072,19)),"~blog/default/tags-teco-chat-page-2-d4f.json",14072],c6b037a5:[()=>n.e(3137).then(n.t.bind(n,4030,19)),"~blog/default/tags-woowahan-techcourse-page-14-c67.json",4030],c6d04683:[()=>n.e(5436).then(n.bind(n,29316)),"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",29316],c7015929:[()=>n.e(4185).then(n.t.bind(n,910,19)),"~blog/default/tags-python-687.json",910],c92f81ac:[()=>n.e(4393).then(n.t.bind(n,10767,19)),"~blog/default/tags-replication-56b-list.json",10767],caf1b628:[()=>n.e(7230).then(n.bind(n,36721)),"@site/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1.mdx",36721],cb6229c3:[()=>n.e(7204).then(n.bind(n,95940)),"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",95940],cc3bdf2f:[()=>n.e(8817).then(n.t.bind(n,11135,19)),"~blog/default/tags-exception-644.json",11135],cc519f63:[()=>n.e(5323).then(n.bind(n,75824)),"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",75824],ccc49370:[()=>Promise.all([n.e(532),n.e(4926),n.e(130),n.e(6103)]).then(n.bind(n,65203)),"@theme/BlogPostPage",65203],cd68cda1:[()=>n.e(8683).then(n.bind(n,2915)),"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx?truncated=true",2915],cec43d6a:[()=>n.e(1358).then(n.bind(n,41056)),"@site/docs/\ubb38\ud654/\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c.mdx",41056],cef46b76:[()=>n.e(8644).then(n.bind(n,91704)),"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",91704],cf8e491a:[()=>n.e(5870).then(n.t.bind(n,19799,19)),"~blog/default/tags-awt-0e2.json",19799],d0277431:[()=>n.e(846).then(n.t.bind(n,4838,19)),"~blog/default/tags-dto-cb6-list.json",4838],d0840b01:[()=>n.e(8037).then(n.t.bind(n,20317,19)),"~blog/default/tags-transaction-ea3.json",20317],d09f7e4b:[()=>n.e(3098).then(n.t.bind(n,84057,19)),"~blog/default/tags-teco-chat-page-3-007-list.json",84057],d0e4cdf1:[()=>n.e(5465).then(n.t.bind(n,64020,19)),"~blog/default/page-7-3c3.json",64020],d126aabd:[()=>n.e(1675).then(n.t.bind(n,7220,19)),"~blog/default/tags-retrospective-page-4-3a3-list.json",7220],d1cef389:[()=>n.e(9310).then(n.t.bind(n,40836,19)),"~blog/default/page-17-62c.json",40836],d1e1bea4:[()=>n.e(7945).then(n.bind(n,32228)),"@site/docs/MAC/\uc790\ubc14 \ubc84\uc804 \ubcc0\uacbd.md",32228],d202e2c5:[()=>n.e(7175).then(n.t.bind(n,3395,19)),"~blog/default/tags-oop-03c-list.json",3395],d2611248:[()=>n.e(8561).then(n.t.bind(n,81667,19)),"~blog/default/page-43-b0a.json",81667],d2770bf7:[()=>n.e(843).then(n.t.bind(n,41156,19)),"~blog/default/tags-woowahan-techcourse-page-11-6c9.json",41156],d28e30d7:[()=>Promise.all([n.e(532),n.e(6671)]).then(n.bind(n,70633)),"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",70633],d2935d14:[()=>n.e(3259).then(n.t.bind(n,92158,19)),"~blog/default/tags-isolation-79d-list.json",92158],d350f5d9:[()=>n.e(2098).then(n.t.bind(n,82622,19)),"~blog/default/tags-test-page-2-d33.json",82622],d361ad2d:[()=>n.e(2247).then(n.bind(n,14448)),"@site/docs/\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12.mdx",14448],d368e73e:[()=>n.e(7954).then(n.t.bind(n,71965,19)),"~blog/default/tags-image-97d-list.json",71965],d40f51e1:[()=>n.e(9633).then(n.t.bind(n,9415,19)),"~blog/default/tags-jdbc-4bd-list.json",9415],d50fd269:[()=>n.e(100).then(n.t.bind(n,38132,19)),"~blog/default/page-31-308.json",38132],d5bb232a:[()=>n.e(3651).then(n.bind(n,46116)),"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx?truncated=true",46116],d5dfecc2:[()=>n.e(1677).then(n.t.bind(n,83335,19)),"~blog/default/tags-teco-chat-page-2-d4f-list.json",83335],d60e2b0c:[()=>n.e(8174).then(n.t.bind(n,36927,19)),"~blog/default/tags-retrospective-page-17-636-list.json",36927],d65e25b7:[()=>Promise.all([n.e(532),n.e(7776)]).then(n.bind(n,60626)),"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx?truncated=true",60626],d6638f30:[()=>n.e(3476).then(n.bind(n,36022)),"@site/docs/\ubc30\ud3ec/\ubb34\uc911\ub2e8 \ubc30\ud3ec.mdx",36022],d6a3d698:[()=>n.e(2890).then(n.t.bind(n,39477,19)),"~blog/default/tags-image-page-3-942.json",39477],d7955594:[()=>Promise.all([n.e(532),n.e(588)]).then(n.bind(n,18751)),"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",18751],d86f7a37:[()=>n.e(3392).then(n.bind(n,98034)),"@site/docs/Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5.mdx",98034],d8775059:[()=>n.e(6387).then(n.bind(n,33604)),"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",33604],d88bdb28:[()=>n.e(9788).then(n.t.bind(n,29417,19)),"~blog/default/tags-retrospective-page-13-49c.json",29417],d8cdf5ef:[()=>n.e(5919).then(n.bind(n,79101)),"@site/docs/\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8.mdx",79101],da14f319:[()=>n.e(5485).then(n.bind(n,96893)),"@site/docs/\uc2a4\ud504\ub9c1/\uc2a4\ud504\ub9c1\uc758 \ud2b9\uc9d5.md",96893],dab4c683:[()=>n.e(6058).then(n.t.bind(n,67315,19)),"~blog/default/tags-woowahan-techcourse-page-3-9a8.json",67315],daff1d93:[()=>n.e(1659).then(n.bind(n,99239)),"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx?truncated=true",99239],db7928b3:[()=>n.e(5046).then(n.t.bind(n,11478,19)),"~blog/default/tags-intelli-j-2bf-list.json",11478],db86613e:[()=>n.e(9458).then(n.bind(n,82549)),"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx?truncated=true",82549],dca6a1e3:[()=>n.e(3239).then(n.bind(n,25386)),"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx?truncated=true",25386],dcf70953:[()=>n.e(1761).then(n.t.bind(n,83769,19)),"/home/runner/work/greeng00se.github.io/greeng00se.github.io/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",83769],ddf9e0bd:[()=>n.e(2542).then(n.t.bind(n,84039,19)),"~blog/default/tags-woowahan-techcourse-page-8-93a-list.json",84039],df147deb:[()=>n.e(5103).then(n.bind(n,43420)),"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",43420],df203c0f:[()=>Promise.all([n.e(532),n.e(9924)]).then(n.bind(n,40491)),"@theme/DocTagDocListPage",40491],df862072:[()=>n.e(7474).then(n.t.bind(n,24827,19)),"~blog/default/tags-book-page-3-a93.json",24827],dfa84138:[()=>n.e(1434).then(n.t.bind(n,22483,19)),"~blog/default/tags-data-base-page-3-9db-list.json",22483],dfc7013c:[()=>n.e(5857).then(n.bind(n,10032)),"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx?truncated=true",10032],e073eb07:[()=>n.e(5819).then(n.t.bind(n,57743,19)),"~blog/default/tags-retrospective-page-11-e3c.json",57743],e0d68441:[()=>n.e(628).then(n.t.bind(n,75301,19)),"~blog/default/tags-retrospective-page-12-8cf-list.json",75301],e0e4666e:[()=>n.e(4665).then(n.t.bind(n,16482,19)),"~blog/default/tags-my-sql-46a.json",16482],e1735da7:[()=>n.e(1611).then(n.bind(n,79784)),"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx?truncated=true",79784],e1a06456:[()=>n.e(9910).then(n.bind(n,54885)),"@site/blog/2023-2/2023-06-26-WebSocket.mdx",54885],e21c8cc4:[()=>n.e(6049).then(n.t.bind(n,48765,19)),"~blog/default/tags-retrospective-page-8-5ab.json",48765],e2326195:[()=>n.e(9467).then(n.bind(n,45682)),"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",45682],e2de2dbb:[()=>n.e(6710).then(n.t.bind(n,47023,19)),"~blog/default/tags-java-page-5-b71.json",47023],e4ebfe18:[()=>n.e(9940).then(n.t.bind(n,57954,19)),"~blog/default/page-3-02e.json",57954],e5e44a85:[()=>n.e(1253).then(n.t.bind(n,42310,19)),"~docs/default/tag-docs-tags-deploy-f3b.json",42310],e6a6ed43:[()=>n.e(5300).then(n.bind(n,66940)),"@site/blog/2023-1/2023-03-30-GRASP.mdx?truncated=true",66940],e6e259a5:[()=>n.e(3771).then(n.bind(n,9801)),"@site/docs/\ub9ac\ub205\uc2a4/Swap \uba54\ubaa8\ub9ac \uc124\uc815.md",9801],e7d2a655:[()=>n.e(8652).then(n.t.bind(n,71501,19)),"~blog/default/tags-woowahan-techcourse-page-2-567-list.json",71501],e8d6e7ce:[()=>n.e(3912).then(n.t.bind(n,65245,19)),"~blog/default/tags-retrospective-page-6-594.json",65245],e9624b4f:[()=>n.e(4564).then(n.t.bind(n,11780,19)),"~blog/default/tags-retrospective-page-13-49c-list.json",11780],e9eabc5d:[()=>n.e(1112).then(n.bind(n,40376)),"@site/blog/2023-1/2023-03-30-GRASP.mdx",40376],e9ff60ad:[()=>n.e(2530).then(n.t.bind(n,10242,19)),"~blog/default/tags-pattern-b4e-list.json",10242],eae2a611:[()=>n.e(6180).then(n.bind(n,47599)),"@site/docs/\uc544\ud0a4\ud14d\ucc98/\ubc84\ud2f0\uceec \uc2ac\ub77c\uc774\uc2a4 \uc544\ud0a4\ud14d\ucc98.mdx",47599],ee1dd2ad:[()=>n.e(5435).then(n.t.bind(n,48834,19)),"~blog/default/tags-woowahan-techcourse-page-13-8ae.json",48834],ee92877e:[()=>n.e(8716).then(n.t.bind(n,41106,19)),"~blog/default/tags-retrospective-page-5-22d.json",41106],eec33099:[()=>n.e(4953).then(n.t.bind(n,80133,19)),"~blog/default/page-40-397.json",80133],ef5b2427:[()=>n.e(9606).then(n.t.bind(n,50195,19)),"~blog/default/page-22-f33.json",50195],eff1d58f:[()=>n.e(4137).then(n.bind(n,68801)),"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx?truncated=true",68801],f01ceada:[()=>n.e(724).then(n.t.bind(n,62563,19)),"~blog/default/page-50-0b0.json",62563],f042b56c:[()=>n.e(8919).then(n.t.bind(n,27490,19)),"~blog/default/tags-teco-chat-d21-list.json",27490],f06cb3e2:[()=>Promise.all([n.e(532),n.e(2620)]).then(n.bind(n,43487)),"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",43487],f078e301:[()=>n.e(1926).then(n.t.bind(n,18385,19)),"~blog/default/tags-woowahan-techcourse-page-6-429-list.json",18385],f0978ee1:[()=>n.e(7740).then(n.t.bind(n,69366,19)),"~blog/default/tags-awt-page-2-eb4.json",69366],f156dfb9:[()=>n.e(5602).then(n.t.bind(n,83311,19)),"~blog/default/tags-time-471.json",83311],f25de701:[()=>n.e(2245).then(n.bind(n,45414)),"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md?truncated=true",45414],f332d221:[()=>n.e(2717).then(n.t.bind(n,99371,19)),"~blog/default/page-10-857.json",99371],f3493919:[()=>n.e(8476).then(n.bind(n,30169)),"@site/docs/\ub3c4\uc11c/\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30.mdx",30169],f3e308ad:[()=>n.e(6123).then(n.t.bind(n,16240,19)),"~blog/default/page-33-758.json",16240],f4c6e7e6:[()=>n.e(31).then(n.t.bind(n,77922,19)),"~docs/default/tag-docs-tags-book-8e4.json",77922],f4f49e13:[()=>n.e(6887).then(n.t.bind(n,26329,19)),"~blog/default/page-12-b6a.json",26329],f580a9d0:[()=>n.e(9887).then(n.t.bind(n,78989,19)),"~blog/default/tags-python-687-list.json",78989],f63a747b:[()=>n.e(5131).then(n.t.bind(n,81723,19)),"~blog/default/tags-woowahan-techcourse-page-7-5bd.json",81723],f6807fb4:[()=>n.e(4788).then(n.t.bind(n,39836,19)),"~docs/default/tag-docs-tags-architecture-68d.json",39836],f75a8651:[()=>n.e(8882).then(n.t.bind(n,44633,19)),"~blog/default/page-8-8c2.json",44633],f7b9d2f4:[()=>n.e(2958).then(n.t.bind(n,53122,19)),"~blog/default/tags-woowahan-techcourse-page-12-5ba.json",53122],f8409a7e:[()=>n.e(3206).then(n.bind(n,29325)),"@site/docs/intro.mdx",29325],f87bdf62:[()=>n.e(6750).then(n.bind(n,52449)),"@site/blog/2023-2/2023-06-26-WebSocket.mdx?truncated=true",52449],f90d0c52:[()=>n.e(5294).then(n.bind(n,47522)),"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",47522],fa3d3942:[()=>n.e(916).then(n.bind(n,28227)),"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",28227],fb48356a:[()=>n.e(9534).then(n.t.bind(n,78215,19)),"~blog/default/tags-retrospective-page-18-40f-list.json",78215],fb861301:[()=>n.e(7563).then(n.t.bind(n,17036,19)),"~blog/default/tags-woowahan-techcourse-page-14-c67-list.json",17036],fbd57548:[()=>n.e(6837).then(n.t.bind(n,30990,19)),"~blog/default/page-11-f65.json",30990],fd5d2408:[()=>n.e(3614).then(n.t.bind(n,64631,19)),"~blog/default/tags-time-471-list.json",64631],fe273484:[()=>n.e(8355).then(n.t.bind(n,53034,19)),"~blog/default/tags-java-a6e-list.json",53034],fe8cce0a:[()=>n.e(955).then(n.t.bind(n,78535,19)),"~blog/default/tags-intelli-j-2bf.json",78535],fed8bc04:[()=>n.e(8110).then(n.t.bind(n,96375,19)),"~blog/default/tags-woowahan-techcourse-page-5-ac5.json",96375],ff4c6c5e:[()=>n.e(820).then(n.bind(n,68007)),"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",68007],ffb0fa11:[()=>n.e(7400).then(n.t.bind(n,58214,19)),"~blog/default/tags-book-page-3-a93-list.json",58214]};var s=n(85893);function l(e){let{error:t,retry:n,pastDelay:a}=e;return t?(0,s.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):a?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(99670),u=n(30226);function d(e,t){if("*"===e)return r()({loading:l,loader:()=>n.e(7856).then(n.bind(n,51772)),modules:["@theme/NotFound"],webpack:()=>[51772],render(e,t){const n=e.default;return(0,s.jsx)(u.z,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const a=o[`${e}-${t}`],d={},p=[],f=[],g=(0,c.Z)(a);return Object.entries(g).forEach((e=>{let[t,n]=e;const a=i[n];a&&(d[t]=a[0],p.push(a[1]),f.push(a[2]))})),r().Map({loading:l,loader:d,modules:p,webpack:()=>f,render(t,n){const r=JSON.parse(JSON.stringify(a));Object.entries(t).forEach((t=>{let[n,a]=t;const o=a.default;if(!o)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof o&&"function"!=typeof o||Object.keys(a).filter((e=>"default"!==e)).forEach((e=>{o[e]=a[e]}));let i=r;const s=n.split(".");s.slice(0,-1).forEach((e=>{i=i[e]})),i[s[s.length-1]]=o}));const o=r.__comp;delete r.__comp;const i=r.__context;return delete r.__context,(0,s.jsx)(u.z,{value:i,children:(0,s.jsx)(o,{...r,...n})})}})}const p=[{path:"/2022-retrospective",component:d("/2022-retrospective","624"),exact:!0},{path:"/accidental-duplication",component:d("/accidental-duplication","d17"),exact:!0},{path:"/blackjack-retrospective",component:d("/blackjack-retrospective","595"),exact:!0},{path:"/blog",component:d("/blog","3d8"),exact:!0},{path:"/book-leadership-and-self-deception",component:d("/book-leadership-and-self-deception","ddd"),exact:!0},{path:"/book-writer",component:d("/book-writer","3c9"),exact:!0},{path:"/chess-retrospective",component:d("/chess-retrospective","168"),exact:!0},{path:"/cloudwatch",component:d("/cloudwatch","cb1"),exact:!0},{path:"/composite",component:d("/composite","302"),exact:!0},{path:"/custom-jdbc-template",component:d("/custom-jdbc-template","cfa"),exact:!0},{path:"/db-replication",component:d("/db-replication","6f2"),exact:!0},{path:"/docusaurus",component:d("/docusaurus","926"),exact:!0},{path:"/grasp",component:d("/grasp","f9b"),exact:!0},{path:"/innodb-lock",component:d("/innodb-lock","d18"),exact:!0},{path:"/intellij-settings",component:d("/intellij-settings","80e"),exact:!0},{path:"/java-class-file",component:d("/java-class-file","50e"),exact:!0},{path:"/java-spring-springboot",component:d("/java-spring-springboot","bed"),exact:!0},{path:"/jdbc-retrospective",component:d("/jdbc-retrospective","158"),exact:!0},{path:"/jenkins",component:d("/jenkins","48c"),exact:!0},{path:"/jsr-310",component:d("/jsr-310","7f9"),exact:!0},{path:"/kotlin-null",component:d("/kotlin-null","8d3"),exact:!0},{path:"/ladder-retrospective",component:d("/ladder-retrospective","7ea"),exact:!0},{path:"/level2-interview-retrospective",component:d("/level2-interview-retrospective","c75"),exact:!0},{path:"/log-async-exception",component:d("/log-async-exception","a44"),exact:!0},{path:"/mock-static-method",component:d("/mock-static-method","fd3"),exact:!0},{path:"/mvc-retrospective",component:d("/mvc-retrospective","96d"),exact:!0},{path:"/mysql-lock",component:d("/mysql-lock","3cb"),exact:!0},{path:"/order-retrospective",component:d("/order-retrospective","a11"),exact:!0},{path:"/page/10",component:d("/page/10","c2c"),exact:!0},{path:"/page/11",component:d("/page/11","89b"),exact:!0},{path:"/page/12",component:d("/page/12","155"),exact:!0},{path:"/page/13",component:d("/page/13","ece"),exact:!0},{path:"/page/14",component:d("/page/14","1f9"),exact:!0},{path:"/page/15",component:d("/page/15","cc0"),exact:!0},{path:"/page/16",component:d("/page/16","813"),exact:!0},{path:"/page/17",component:d("/page/17","843"),exact:!0},{path:"/page/18",component:d("/page/18","84a"),exact:!0},{path:"/page/19",component:d("/page/19","e4e"),exact:!0},{path:"/page/2",component:d("/page/2","256"),exact:!0},{path:"/page/20",component:d("/page/20","30e"),exact:!0},{path:"/page/21",component:d("/page/21","553"),exact:!0},{path:"/page/22",component:d("/page/22","a88"),exact:!0},{path:"/page/23",component:d("/page/23","edf"),exact:!0},{path:"/page/24",component:d("/page/24","915"),exact:!0},{path:"/page/25",component:d("/page/25","4aa"),exact:!0},{path:"/page/26",component:d("/page/26","ec5"),exact:!0},{path:"/page/27",component:d("/page/27","339"),exact:!0},{path:"/page/28",component:d("/page/28","376"),exact:!0},{path:"/page/29",component:d("/page/29","ea0"),exact:!0},{path:"/page/3",component:d("/page/3","d5c"),exact:!0},{path:"/page/30",component:d("/page/30","2ff"),exact:!0},{path:"/page/31",component:d("/page/31","d32"),exact:!0},{path:"/page/32",component:d("/page/32","02d"),exact:!0},{path:"/page/33",component:d("/page/33","3d4"),exact:!0},{path:"/page/34",component:d("/page/34","4d2"),exact:!0},{path:"/page/35",component:d("/page/35","b81"),exact:!0},{path:"/page/36",component:d("/page/36","598"),exact:!0},{path:"/page/37",component:d("/page/37","eda"),exact:!0},{path:"/page/38",component:d("/page/38","9cf"),exact:!0},{path:"/page/39",component:d("/page/39","27d"),exact:!0},{path:"/page/4",component:d("/page/4","b0c"),exact:!0},{path:"/page/40",component:d("/page/40","744"),exact:!0},{path:"/page/41",component:d("/page/41","793"),exact:!0},{path:"/page/42",component:d("/page/42","0ee"),exact:!0},{path:"/page/43",component:d("/page/43","345"),exact:!0},{path:"/page/44",component:d("/page/44","3c4"),exact:!0},{path:"/page/45",component:d("/page/45","6e5"),exact:!0},{path:"/page/46",component:d("/page/46","d10"),exact:!0},{path:"/page/47",component:d("/page/47","280"),exact:!0},{path:"/page/48",component:d("/page/48","8df"),exact:!0},{path:"/page/49",component:d("/page/49","282"),exact:!0},{path:"/page/5",component:d("/page/5","87c"),exact:!0},{path:"/page/50",component:d("/page/50","3c4"),exact:!0},{path:"/page/51",component:d("/page/51","658"),exact:!0},{path:"/page/6",component:d("/page/6","a58"),exact:!0},{path:"/page/7",component:d("/page/7","bb8"),exact:!0},{path:"/page/8",component:d("/page/8","2f3"),exact:!0},{path:"/page/9",component:d("/page/9","88d"),exact:!0},{path:"/parameterized-tests",component:d("/parameterized-tests","1fb"),exact:!0},{path:"/performance-test-type",component:d("/performance-test-type","df3"),exact:!0},{path:"/racing-car-retrospective",component:d("/racing-car-retrospective","ebc"),exact:!0},{path:"/refactoring-retrospective",component:d("/refactoring-retrospective","ab4"),exact:!0},{path:"/route-image-async-with-event",component:d("/route-image-async-with-event","832"),exact:!0},{path:"/route-image-implementation",component:d("/route-image-implementation","b0f"),exact:!0},{path:"/route-image-intro",component:d("/route-image-intro","7e7"),exact:!0},{path:"/route-image-python",component:d("/route-image-python","dfd"),exact:!0},{path:"/search",component:d("/search","c1e"),exact:!0},{path:"/shopping-cart-retrospective",component:d("/shopping-cart-retrospective","28b"),exact:!0},{path:"/spring-test-isolation",component:d("/spring-test-isolation","8ed"),exact:!0},{path:"/subway-retrospective",component:d("/subway-retrospective","7db"),exact:!0},{path:"/tags",component:d("/tags","4bf"),exact:!0},{path:"/tags/async",component:d("/tags/async","a21"),exact:!0},{path:"/tags/async/page/2",component:d("/tags/async/page/2","436"),exact:!0},{path:"/tags/awt",component:d("/tags/awt","9e3"),exact:!0},{path:"/tags/awt/page/2",component:d("/tags/awt/page/2","b68"),exact:!0},{path:"/tags/book",component:d("/tags/book","4df"),exact:!0},{path:"/tags/book/page/2",component:d("/tags/book/page/2","88a"),exact:!0},{path:"/tags/book/page/3",component:d("/tags/book/page/3","128"),exact:!0},{path:"/tags/class",component:d("/tags/class","d3d"),exact:!0},{path:"/tags/cloudwatch",component:d("/tags/cloudwatch","264"),exact:!0},{path:"/tags/composite",component:d("/tags/composite","931"),exact:!0},{path:"/tags/data-base",component:d("/tags/data-base","2fe"),exact:!0},{path:"/tags/data-base/page/2",component:d("/tags/data-base/page/2","049"),exact:!0},{path:"/tags/data-base/page/3",component:d("/tags/data-base/page/3","9ac"),exact:!0},{path:"/tags/documentation",component:d("/tags/documentation","86d"),exact:!0},{path:"/tags/dto",component:d("/tags/dto","bef"),exact:!0},{path:"/tags/elastic-beanstalk",component:d("/tags/elastic-beanstalk","164"),exact:!0},{path:"/tags/event",component:d("/tags/event","56a"),exact:!0},{path:"/tags/exception",component:d("/tags/exception","5b1"),exact:!0},{path:"/tags/grasp",component:d("/tags/grasp","130"),exact:!0},{path:"/tags/image",component:d("/tags/image","067"),exact:!0},{path:"/tags/image/page/2",component:d("/tags/image/page/2","88a"),exact:!0},{path:"/tags/image/page/3",component:d("/tags/image/page/3","acc"),exact:!0},{path:"/tags/inno-db",component:d("/tags/inno-db","2aa"),exact:!0},{path:"/tags/intelli-j",component:d("/tags/intelli-j","aaa"),exact:!0},{path:"/tags/isolation",component:d("/tags/isolation","bab"),exact:!0},{path:"/tags/java",component:d("/tags/java","60d"),exact:!0},{path:"/tags/java/page/2",component:d("/tags/java/page/2","d9f"),exact:!0},{path:"/tags/java/page/3",component:d("/tags/java/page/3","d2c"),exact:!0},{path:"/tags/java/page/4",component:d("/tags/java/page/4","c97"),exact:!0},{path:"/tags/java/page/5",component:d("/tags/java/page/5","6c7"),exact:!0},{path:"/tags/jdbc",component:d("/tags/jdbc","667"),exact:!0},{path:"/tags/jenkins",component:d("/tags/jenkins","590"),exact:!0},{path:"/tags/kotlin",component:d("/tags/kotlin","b84"),exact:!0},{path:"/tags/lock",component:d("/tags/lock","059"),exact:!0},{path:"/tags/lock/page/2",component:d("/tags/lock/page/2","2e3"),exact:!0},{path:"/tags/log",component:d("/tags/log","0ae"),exact:!0},{path:"/tags/mock",component:d("/tags/mock","9dd"),exact:!0},{path:"/tags/mockito",component:d("/tags/mockito","3de"),exact:!0},{path:"/tags/monitoring",component:d("/tags/monitoring","775"),exact:!0},{path:"/tags/my-sql",component:d("/tags/my-sql","214"),exact:!0},{path:"/tags/mysql",component:d("/tags/mysql","79d"),exact:!0},{path:"/tags/oop",component:d("/tags/oop","613"),exact:!0},{path:"/tags/pattern",component:d("/tags/pattern","5e4"),exact:!0},{path:"/tags/performance-test",component:d("/tags/performance-test","d3e"),exact:!0},{path:"/tags/python",component:d("/tags/python","7fe"),exact:!0},{path:"/tags/replication",component:d("/tags/replication","77b"),exact:!0},{path:"/tags/retrospective",component:d("/tags/retrospective","b64"),exact:!0},{path:"/tags/retrospective/page/10",component:d("/tags/retrospective/page/10","ba6"),exact:!0},{path:"/tags/retrospective/page/11",component:d("/tags/retrospective/page/11","c54"),exact:!0},{path:"/tags/retrospective/page/12",component:d("/tags/retrospective/page/12","443"),exact:!0},{path:"/tags/retrospective/page/13",component:d("/tags/retrospective/page/13","b71"),exact:!0},{path:"/tags/retrospective/page/14",component:d("/tags/retrospective/page/14","e01"),exact:!0},{path:"/tags/retrospective/page/15",component:d("/tags/retrospective/page/15","64b"),exact:!0},{path:"/tags/retrospective/page/16",component:d("/tags/retrospective/page/16","703"),exact:!0},{path:"/tags/retrospective/page/17",component:d("/tags/retrospective/page/17","2d8"),exact:!0},{path:"/tags/retrospective/page/18",component:d("/tags/retrospective/page/18","1fd"),exact:!0},{path:"/tags/retrospective/page/19",component:d("/tags/retrospective/page/19","d19"),exact:!0},{path:"/tags/retrospective/page/2",component:d("/tags/retrospective/page/2","8bf"),exact:!0},{path:"/tags/retrospective/page/20",component:d("/tags/retrospective/page/20","f75"),exact:!0},{path:"/tags/retrospective/page/3",component:d("/tags/retrospective/page/3","998"),exact:!0},{path:"/tags/retrospective/page/4",component:d("/tags/retrospective/page/4","23f"),exact:!0},{path:"/tags/retrospective/page/5",component:d("/tags/retrospective/page/5","b0c"),exact:!0},{path:"/tags/retrospective/page/6",component:d("/tags/retrospective/page/6","58e"),exact:!0},{path:"/tags/retrospective/page/7",component:d("/tags/retrospective/page/7","133"),exact:!0},{path:"/tags/retrospective/page/8",component:d("/tags/retrospective/page/8","c6e"),exact:!0},{path:"/tags/retrospective/page/9",component:d("/tags/retrospective/page/9","a37"),exact:!0},{path:"/tags/spring",component:d("/tags/spring","ab2"),exact:!0},{path:"/tags/spring-boot",component:d("/tags/spring-boot","eb7"),exact:!0},{path:"/tags/static",component:d("/tags/static","dd5"),exact:!0},{path:"/tags/teco-chat",component:d("/tags/teco-chat","7a9"),exact:!0},{path:"/tags/teco-chat/page/2",component:d("/tags/teco-chat/page/2","fbf"),exact:!0},{path:"/tags/teco-chat/page/3",component:d("/tags/teco-chat/page/3","c3d"),exact:!0},{path:"/tags/test",component:d("/tags/test","84f"),exact:!0},{path:"/tags/test/page/2",component:d("/tags/test/page/2","3a8"),exact:!0},{path:"/tags/time",component:d("/tags/time","f3d"),exact:!0},{path:"/tags/transaction",component:d("/tags/transaction","622"),exact:!0},{path:"/tags/web-application",component:d("/tags/web-application","4a3"),exact:!0},{path:"/tags/web-socket",component:d("/tags/web-socket","e59"),exact:!0},{path:"/tags/woowahan-techcourse",component:d("/tags/woowahan-techcourse","77a"),exact:!0},{path:"/tags/woowahan-techcourse/page/10",component:d("/tags/woowahan-techcourse/page/10","156"),exact:!0},{path:"/tags/woowahan-techcourse/page/11",component:d("/tags/woowahan-techcourse/page/11","703"),exact:!0},{path:"/tags/woowahan-techcourse/page/12",component:d("/tags/woowahan-techcourse/page/12","38f"),exact:!0},{path:"/tags/woowahan-techcourse/page/13",component:d("/tags/woowahan-techcourse/page/13","ddd"),exact:!0},{path:"/tags/woowahan-techcourse/page/14",component:d("/tags/woowahan-techcourse/page/14","65c"),exact:!0},{path:"/tags/woowahan-techcourse/page/15",component:d("/tags/woowahan-techcourse/page/15","a2e"),exact:!0},{path:"/tags/woowahan-techcourse/page/16",component:d("/tags/woowahan-techcourse/page/16","53e"),exact:!0},{path:"/tags/woowahan-techcourse/page/2",component:d("/tags/woowahan-techcourse/page/2","047"),exact:!0},{path:"/tags/woowahan-techcourse/page/3",component:d("/tags/woowahan-techcourse/page/3","d3f"),exact:!0},{path:"/tags/woowahan-techcourse/page/4",component:d("/tags/woowahan-techcourse/page/4","5b6"),exact:!0},{path:"/tags/woowahan-techcourse/page/5",component:d("/tags/woowahan-techcourse/page/5","135"),exact:!0},{path:"/tags/woowahan-techcourse/page/6",component:d("/tags/woowahan-techcourse/page/6","5e8"),exact:!0},{path:"/tags/woowahan-techcourse/page/7",component:d("/tags/woowahan-techcourse/page/7","a11"),exact:!0},{path:"/tags/woowahan-techcourse/page/8",component:d("/tags/woowahan-techcourse/page/8","a7b"),exact:!0},{path:"/tags/woowahan-techcourse/page/9",component:d("/tags/woowahan-techcourse/page/9","be6"),exact:!0},{path:"/tecochat-retrospective-1",component:d("/tecochat-retrospective-1","ed9"),exact:!0},{path:"/tecochat-retrospective-2",component:d("/tecochat-retrospective-2","fc4"),exact:!0},{path:"/tecochat-retrospective-3",component:d("/tecochat-retrospective-3","6f4"),exact:!0},{path:"/test-double",component:d("/test-double","8ea"),exact:!0},{path:"/the-essence-of-object-orientation",component:d("/the-essence-of-object-orientation","9a2"),exact:!0},{path:"/tomcat-retrospective",component:d("/tomcat-retrospective","5a3"),exact:!0},{path:"/transaction-and-isolation",component:d("/transaction-and-isolation","d60"),exact:!0},{path:"/web-application-evolution",component:d("/web-application-evolution","c55"),exact:!0},{path:"/web-racing-car-retrospective",component:d("/web-racing-car-retrospective","ccb"),exact:!0},{path:"/websocket",component:d("/websocket","5c1"),exact:!0},{path:"/woowacourse-level1-retrospective",component:d("/woowacourse-level1-retrospective","a6a"),exact:!0},{path:"/woowacourse-level2-retrospective",component:d("/woowacourse-level2-retrospective","758"),exact:!0},{path:"/woowacourse-level3-retrospective",component:d("/woowacourse-level3-retrospective","4e5"),exact:!0},{path:"/docs",component:d("/docs","cf0"),routes:[{path:"/docs",component:d("/docs","d75"),routes:[{path:"/docs/tags",component:d("/docs/tags","0cc"),exact:!0},{path:"/docs/tags/architecture",component:d("/docs/tags/architecture","44b"),exact:!0},{path:"/docs/tags/book",component:d("/docs/tags/book","977"),exact:!0},{path:"/docs/tags/collection",component:d("/docs/tags/collection","0f6"),exact:!0},{path:"/docs/tags/deploy",component:d("/docs/tags/deploy","001"),exact:!0},{path:"/docs/tags/etc",component:d("/docs/tags/etc","dd7"),exact:!0},{path:"/docs/tags/java",component:d("/docs/tags/java","bac"),exact:!0},{path:"/docs/tags/jpa",component:d("/docs/tags/jpa","831"),exact:!0},{path:"/docs/tags/latency",component:d("/docs/tags/latency","a14"),exact:!0},{path:"/docs/tags/load-balancing",component:d("/docs/tags/load-balancing","5bb"),exact:!0},{path:"/docs/tags/monitoring",component:d("/docs/tags/monitoring","652"),exact:!0},{path:"/docs/tags/network",component:d("/docs/tags/network","5ba"),exact:!0},{path:"/docs/tags/nginx",component:d("/docs/tags/nginx","379"),exact:!0},{path:"/docs/tags/package",component:d("/docs/tags/package","dec"),exact:!0},{path:"/docs/tags/performance",component:d("/docs/tags/performance","364"),exact:!0},{path:"/docs/tags/postmortem",component:d("/docs/tags/postmortem","cb8"),exact:!0},{path:"/docs/tags/sequenced",component:d("/docs/tags/sequenced","fc4"),exact:!0},{path:"/docs/tags/spring",component:d("/docs/tags/spring","219"),exact:!0},{path:"/docs/tags/test",component:d("/docs/tags/test","df6"),exact:!0},{path:"/docs/tags/throughput",component:d("/docs/tags/throughput","760"),exact:!0},{path:"/docs/tags/zero-downtime",component:d("/docs/tags/zero-downtime","9c1"),exact:!0},{path:"/docs",component:d("/docs","02e"),routes:[{path:"/docs",component:d("/docs","818"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/architecture/virtical-slice-architecture",component:d("/docs/architecture/virtical-slice-architecture","825"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/book/getting-out-of-the-box",component:d("/docs/book/getting-out-of-the-box","8e1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/culture/postmortem",component:d("/docs/culture/postmortem","420"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/database/maximumPoolSize",component:d("/docs/database/maximumPoolSize","9ab"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/database/query-execution",component:d("/docs/database/query-execution","7b8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/deploy/zero-downtime",component:d("/docs/deploy/zero-downtime","20f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/design/package",component:d("/docs/design/package","274"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/etc/communication",component:d("/docs/etc/communication","9c1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/etc/develop-with-spring",component:d("/docs/etc/develop-with-spring","9ab"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/etc/experience-and-self-question",component:d("/docs/etc/experience-and-self-question","d25"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/etc/healthful-growth",component:d("/docs/etc/healthful-growth","fcf"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/java/sequenced-collection",component:d("/docs/java/sequenced-collection","bda"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/jpa/key",component:d("/docs/jpa/key","68b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/linux/shell",component:d("/docs/linux/shell","c5b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/linux/swap",component:d("/docs/linux/swap","9d5"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/mac/java",component:d("/docs/mac/java","5a9"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/monitoring/intro",component:d("/docs/monitoring/intro","5db"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/network/load-balancing",component:d("/docs/network/load-balancing","caa"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/network/load-balancing-algorithm",component:d("/docs/network/load-balancing-algorithm","a4d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nginx/command",component:d("/docs/nginx/command","0e3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nginx/static-file",component:d("/docs/nginx/static-file","629"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/performance/throughput",component:d("/docs/performance/throughput","56a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/performance/throughput-latency",component:d("/docs/performance/throughput-latency","12a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/performance/types",component:d("/docs/performance/types","c08"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/spring/essence",component:d("/docs/spring/essence","4c6"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/test/benefit",component:d("/docs/test/benefit","6c8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/test/first",component:d("/docs/test/first","566"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/test/heuristics",component:d("/docs/test/heuristics","b35"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/test/stairstep",component:d("/docs/test/stairstep","a57"),exact:!0,sidebar:"tutorialSidebar"}]}]}]},{path:"/",component:d("/","3ce"),exact:!0},{path:"/",component:d("/","956"),exact:!0},{path:"*",component:d("*")}]},98934:(e,t,n)=>{"use strict";n.d(t,{_:()=>o,t:()=>i});var a=n(67294),r=n(85893);const o=a.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,a.useState)(!1);return(0,a.useEffect)((()=>{i(!0)}),[]),(0,r.jsx)(o.Provider,{value:n,children:t})}},97221:(e,t,n)=>{"use strict";var a=n(67294),r=n(20745),o=n(73727),i=n(70405),s=n(10412);const l=[n(56657),n(32497),n(3310),n(18320),n(52295)];var c=n(723),u=n(16550),d=n(18790),p=n(85893);function f(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var g=n(35742),h=n(52263),m=n(44996),b=n(86668),y=n(10833),v=n(94711),x=n(19727),w=n(43320),_=n(18780),k=n(90197);function S(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.Z)(),a=(0,v.l)(),r=n[e].htmlLang,o=e=>e.replace("-","_");return(0,p.jsxs)(g.Z,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:a.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:a.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:o(r)}),Object.values(n).filter((e=>r!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:o(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.Z)(),a=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.Z)(),{pathname:a}=(0,u.TH)();return e+(0,_.applyTrailingSlash)((0,m.Z)(a),{trailingSlash:n,baseUrl:t})}(),r=t?`${n}${t}`:a;return(0,p.jsxs)(g.Z,{children:[(0,p.jsx)("meta",{property:"og:url",content:r}),(0,p.jsx)("link",{rel:"canonical",href:r})]})}function j(){const{i18n:{currentLocale:e}}=(0,h.Z)(),{metadata:t,image:n}=(0,b.L)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(g.Z,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:x.h})]}),n&&(0,p.jsx)(y.d,{image:n}),(0,p.jsx)(E,{}),(0,p.jsx)(S,{}),(0,p.jsx)(k.Z,{tag:w.HX,locale:e}),(0,p.jsx)(g.Z,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const C=new Map;function T(e){if(C.has(e.pathname))return{...e,pathname:C.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return C.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return C.set(e.pathname,t),{...e,pathname:t}}var A=n(98934),L=n(58940),P=n(20469);function N(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),a=1;a{const a=t.default?.[e]??t[e];return a?.(...n)}));return()=>r.forEach((e=>e?.()))}const M=function(e){let{children:t,location:n,previousLocation:a}=e;return(0,P.Z)((()=>{a!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const a=t.pathname===n.pathname,r=t.hash===n.hash,o=t.search===n.search;if(a&&r&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:a}),N("onRouteDidUpdate",{previousLocation:a,location:n}))}),[a,n]),t};function R(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class O extends a.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=s.Z.canUseDOM?N("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=N("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),R(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,p.jsx)(M,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(u.AW,{location:t,render:()=>e})})}}const I=O,F="__docusaurus-base-url-issue-banner-container",D="__docusaurus-base-url-issue-banner",B="__docusaurus-base-url-issue-banner-suggestion-container";function z(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${F}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{if("undefined"==typeof document)return void n();const a=document.createElement("link");a.setAttribute("rel","prefetch"),a.setAttribute("href",e),a.onload=()=>t(),a.onerror=()=>n();const r=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;r?.appendChild(a)}))}:function(e){return new Promise(((t,n)=>{const a=new XMLHttpRequest;a.open("GET",e,!0),a.withCredentials=!0,a.onload=()=>{200===a.status?t():n()},a.send(null)}))};var Y=n(99670);const Q=new Set,X=new Set,J=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch(e){if(!(e=>!J()&&!X.has(e)&&!Q.has(e))(e))return!1;Q.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(G).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,Y.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?K(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!J()&&!X.has(e))(e)&&(X.add(e),R(e))},te=Object.freeze(ee),ne=Boolean(!0);if(s.Z.canUseDOM){window.docusaurus=te;const e=document.getElementById("__docusaurus"),t=(0,p.jsx)(i.B6,{children:(0,p.jsx)(o.VK,{children:(0,p.jsx)(q,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},s=()=>{if(ne)a.startTransition((()=>{r.hydrateRoot(e,t,{onRecoverableError:n})}));else{const o=r.createRoot(e,{onRecoverableError:n});a.startTransition((()=>{o.render(t)}))}};R(window.location.pathname).then(s)}},58940:(e,t,n)=>{"use strict";n.d(t,{_:()=>d,M:()=>p});var a=n(67294),r=n(36809);const o=JSON.parse('{"docusaurus-plugin-google-gtag":{"default":{"trackingID":["G-17TREGCW4H"],"anonymizeIP":true,"id":"default"}},"docusaurus-plugin-content-docs":{"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"intro","docs":[{"id":"intro","path":"/docs/","sidebar":"tutorialSidebar"},{"id":"Java/SequencedCollection","path":"/docs/java/sequenced-collection","sidebar":"tutorialSidebar"},{"id":"JPA/\uae30\ubcf8 \ud0a4 \ub9e4\ud551","path":"/docs/jpa/key","sidebar":"tutorialSidebar"},{"id":"MAC/\uc790\ubc14 \ubc84\uc804 \ubcc0\uacbd","path":"/docs/mac/java","sidebar":"tutorialSidebar"},{"id":"Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4","path":"/docs/nginx/command","sidebar":"tutorialSidebar"},{"id":"Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5","path":"/docs/nginx/static-file","sidebar":"tutorialSidebar"},{"id":"\uae30\ud0c0/\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30","path":"/docs/etc/healthful-growth","sidebar":"tutorialSidebar"},{"id":"\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30","path":"/docs/etc/develop-with-spring","sidebar":"tutorialSidebar"},{"id":"\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8","path":"/docs/etc/experience-and-self-question","sidebar":"tutorialSidebar"},{"id":"\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00","path":"/docs/etc/communication","sidebar":"tutorialSidebar"},{"id":"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1","path":"/docs/network/load-balancing","sidebar":"tutorialSidebar"},{"id":"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998","path":"/docs/network/load-balancing-algorithm","sidebar":"tutorialSidebar"},{"id":"\ub370\uc774\ud130\ubca0\uc774\uc2a4/Connection Pool","path":"/docs/database/maximumPoolSize","sidebar":"tutorialSidebar"},{"id":"\ub370\uc774\ud130\ubca0\uc774\uc2a4/\ucffc\ub9ac \uc2e4\ud589 \uad6c\uc870","path":"/docs/database/query-execution","sidebar":"tutorialSidebar"},{"id":"\ub3c4\uc11c/\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30","path":"/docs/book/getting-out-of-the-box","sidebar":"tutorialSidebar"},{"id":"\ub9ac\ub205\uc2a4/Swap \uba54\ubaa8\ub9ac \uc124\uc815","path":"/docs/linux/swap","sidebar":"tutorialSidebar"},{"id":"\ub9ac\ub205\uc2a4/\ud130\ubbf8\ub110 \uc258 \ud504\ub86c\ud504\ud2b8 \uc124\uc815","path":"/docs/linux/shell","sidebar":"tutorialSidebar"},{"id":"\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","path":"/docs/monitoring/intro","sidebar":"tutorialSidebar"},{"id":"\ubb38\ud654/\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c","path":"/docs/culture/postmortem","sidebar":"tutorialSidebar"},{"id":"\ubc30\ud3ec/\ubb34\uc911\ub2e8 \ubc30\ud3ec","path":"/docs/deploy/zero-downtime","sidebar":"tutorialSidebar"},{"id":"\uc124\uacc4/\ud328\ud0a4\uc9c0","path":"/docs/design/package","sidebar":"tutorialSidebar"},{"id":"\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12","path":"/docs/performance/throughput","sidebar":"tutorialSidebar"},{"id":"\uc131\ub2a5/Throughput\uacfc Latency","path":"/docs/performance/throughput-latency","sidebar":"tutorialSidebar"},{"id":"\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8","path":"/docs/performance/types","sidebar":"tutorialSidebar"},{"id":"\uc2a4\ud504\ub9c1/\uc2a4\ud504\ub9c1\uc758 \ud2b9\uc9d5","path":"/docs/spring/essence","sidebar":"tutorialSidebar"},{"id":"\uc544\ud0a4\ud14d\ucc98/\ubc84\ud2f0\uceec \uc2ac\ub77c\uc774\uc2a4 \uc544\ud0a4\ud14d\ucc98","path":"/docs/architecture/virtical-slice-architecture","sidebar":"tutorialSidebar"},{"id":"\ud14c\uc2a4\ud2b8/FIRST","path":"/docs/test/first","sidebar":"tutorialSidebar"},{"id":"\ud14c\uc2a4\ud2b8/\uacc4\ub2e8 \ud14c\uc2a4\ud2b8","path":"/docs/test/stairstep","sidebar":"tutorialSidebar"},{"id":"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uaddc\uce59","path":"/docs/test/heuristics","sidebar":"tutorialSidebar"},{"id":"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd","path":"/docs/test/benefit","sidebar":"tutorialSidebar"}],"draftIds":[],"sidebars":{"tutorialSidebar":{"link":{"path":"/docs/jpa/key","label":"JPA/\uae30\ubcf8 \ud0a4 \ub9e4\ud551"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"ko","locales":["ko"],"path":"i18n","currentLocale":"ko","localeConfigs":{"ko":{"label":"\ud55c\uad6d\uc5b4","direction":"ltr","htmlLang":"ko","calendar":"gregory","path":"ko"}}}');var s=n(57529);const l=JSON.parse('{"docusaurusVersion":"3.0.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.0.0"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.0.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.0.0"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"3.0.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.0.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.0.0"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"3.0.0"},"docusaurus-theme-mermaid":{"type":"package","name":"@docusaurus/theme-mermaid","version":"3.0.0"}}}');var c=n(85893);const u={siteConfig:r.default,siteMetadata:l,globalData:o,i18n:i,codeTranslations:s},d=a.createContext(u);function p(e){let{children:t}=e;return(0,c.jsx)(d.Provider,{value:u,children:t})}},44763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var a=n(67294),r=n(10412),o=n(35742),i=n(18780),s=n(58207),l=n(85893);function c(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,l.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,l.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,l.jsx)(u,{error:t})]})}function u(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,l.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function d(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)(f,{fallback:()=>(0,l.jsx)(c,{error:t,tryAgain:n}),children:[(0,l.jsx)(o.Z,{children:(0,l.jsx)("title",{children:"Page Error"})}),(0,l.jsx)(s.Z,{children:(0,l.jsx)(c,{error:t,tryAgain:n})})]})}const p=e=>(0,l.jsx)(d,{...e});class f extends a.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){r.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??p)(e)}return e??null}}},10412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const a="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,r={canUseDOM:a,canUseEventListeners:a&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:a&&"IntersectionObserver"in window,canUseViewport:a&&"screen"in window}},35742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(67294);var a=n(70405),r=n(85893);function o(e){return(0,r.jsx)(a.ql,{...e})}},39960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var a=n(67294),r=n(73727),o=n(18780),i=n(52263),s=n(13919),l=n(10412),c=n(85893);const u=a.createContext({collectLink:()=>{}});var d=n(44996);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:g,isActive:h,"data-noBrokenLinkCheck":m,autoAddBaseUrl:b=!0,...y}=e;const{siteConfig:{trailingSlash:v,baseUrl:x}}=(0,i.Z)(),{withBaseUrl:w}=(0,d.C)(),_=(0,a.useContext)(u),k=(0,a.useRef)(null);(0,a.useImperativeHandle)(t,(()=>k.current));const S=p||f;const E=(0,s.Z)(S),j=S?.replace("pathname://","");let C=void 0!==j?(T=j,b&&(e=>e.startsWith("/"))(T)?w(T):T):void 0;var T;C&&E&&(C=(0,o.applyTrailingSlash)(C,{trailingSlash:v,baseUrl:x}));const A=(0,a.useRef)(!1),L=n?r.OL:r.rU,P=l.Z.canUseIntersectionObserver,N=(0,a.useRef)(),M=()=>{A.current||null==C||(window.docusaurus.preload(C),A.current=!0)};(0,a.useEffect)((()=>(!P&&E&&null!=C&&window.docusaurus.prefetch(C),()=>{P&&N.current&&N.current.disconnect()})),[N,C,P,E]);const R=C?.startsWith("#")??!1,O=!C||!E||R;return O||m||_.collectLink(C),O?(0,c.jsx)("a",{ref:k,href:C,...S&&!E&&{target:"_blank",rel:"noopener noreferrer"},...y}):(0,c.jsx)(L,{...y,onMouseEnter:M,onTouchStart:M,innerRef:e=>{k.current=e,P&&e&&E&&(N.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(N.current.unobserve(e),N.current.disconnect(),null!=C&&window.docusaurus.prefetch(C))}))})),N.current.observe(e))},to:C,...n&&{isActive:h,activeClassName:g}})}const f=a.forwardRef(p)},95999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c,I:()=>l});var a=n(67294),r=n(85893);function o(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,a.isValidElement)(e)))?n.map(((e,t)=>(0,a.isValidElement)(e)?a.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=n(57529);function s(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return i[t??n]??n??t}function l(e,t){let{message:n,id:a}=e;return o(s({message:n,id:a}),t)}function c(e){let{children:t,id:n,values:a}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const i=s({message:t,id:n});return(0,r.jsx)(r.Fragment,{children:o(i,a)})}},29935:(e,t,n)=>{"use strict";n.d(t,{m:()=>a});const a="default"},13919:(e,t,n)=>{"use strict";function a(e){return/^(?:\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!a(e)}n.d(t,{Z:()=>r,b:()=>a})},44996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>s});var a=n(67294),r=n(52263),o=n(13919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,r.Z)(),n=(0,a.useCallback)(((n,a)=>function(e,t,n,a){let{forcePrependBaseUrl:r=!1,absolute:i=!1}=void 0===a?{}:a;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(r)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,a)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},52263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(67294),r=n(58940);function o(){return(0,a.useContext)(r._)}},72389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(67294),r=n(98934);function o(){return(0,a.useContext)(r._)}},20469:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var a=n(67294);const r=n(10412).Z.canUseDOM?a.useLayoutEffect:a.useEffect},99670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const a=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function r(e){const t={};return function e(n,r){Object.entries(n).forEach((n=>{let[o,i]=n;const s=r?`${r}.${o}`:o;a(i)?e(i,s):t[s]=i}))}(e),t}},30226:(e,t,n)=>{"use strict";n.d(t,{_:()=>o,z:()=>i});var a=n(67294),r=n(85893);const o=a.createContext(null);function i(e){let{children:t,value:n}=e;const i=a.useContext(o),s=(0,a.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const a={...t.data,...n?.data};return{plugin:t.plugin,data:a}}({parent:i,value:n})),[i,n]);return(0,r.jsx)(o.Provider,{value:s,children:t})}},80143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>b,gA:()=>f,WS:()=>g,_r:()=>d,Jo:()=>y,zh:()=>p,yW:()=>m,gB:()=>h});var a=n(16550),r=n(52263),o=n(29935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,r.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const s=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=s(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,a.LX)(t,{path:e.path,exact:!1,strict:!1})))}function c(e,t){const n=l(e,t),r=n?.docs.find((e=>!!(0,a.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:r,alternateDocVersions:r?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((a=>{a.id===t&&(n[e.name]=a)}))})),n}(r.id):{}}}const u={},d=()=>i("docusaurus-plugin-content-docs")??u,p=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const a=i(e),r=a?.[t];if(!r&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return r}("docusaurus-plugin-content-docs",e,{failfast:!0});function f(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,a.TH)();return function(e,t,n){void 0===n&&(n={});const r=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,a.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=r?{pluginId:r[0],pluginData:r[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function g(e){void 0===e&&(e={});const t=f(e),{pathname:n}=(0,a.TH)();if(!t)return;return{activePlugin:t,activeVersion:l(t.pluginData,n)}}function h(e){return p(e).versions}function m(e){const t=p(e);return s(t)}function b(e){const t=p(e),{pathname:n}=(0,a.TH)();return c(t,n)}function y(e){const t=p(e),{pathname:n}=(0,a.TH)();return function(e,t){const n=s(e);return{latestDocSuggestion:c(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},56657:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});const a={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("set","page_path",t.pathname+t.search+t.hash),window.gtag("event","page_view")}))}}},18320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var a=n(74865),r=n.n(a);r().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{r().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){r().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var a=n(34798),r=n(36809);!function(e){const{themeConfig:{prism:t}}=r.default,{additionalLanguages:a}=t;globalThis.Prism=e,a.forEach((e=>{"php"===e&&n(96854),n(52811)(`./prism-${e}`)})),delete globalThis.Prism}(a.p1)},92503:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});n(67294);var a=n(86010),r=n(95999),o=n(86668),i=n(39960);const s={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var l=n(85893);function c(e){let{as:t,id:n,...c}=e;const{navbar:{hideOnScroll:u}}=(0,o.L)();if("h1"===t||!n)return(0,l.jsx)(t,{...c,id:void 0});const d=(0,r.I)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof c.children?c.children:n});return(0,l.jsxs)(t,{...c,className:(0,a.Z)("anchor",u?s.anchorWithHideOnScrollNavbar:s.anchorWithStickyNavbar,c.className),id:n,children:[c.children,(0,l.jsx)(i.Z,{className:"hash-link",to:`#${n}`,"aria-label":d,title:d,children:"\u200b"})]})}},39471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(67294);const a={iconExternalLink:"iconExternalLink_nPIU"};var r=n(85893);function o(e){let{width:t=13.5,height:n=13.5}=e;return(0,r.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:a.iconExternalLink,children:(0,r.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},58207:(e,t,n)=>{"use strict";n.d(t,{Z:()=>Ct});var a=n(67294),r=n(86010),o=n(44763),i=n(10833),s=n(16550),l=n(95999),c=n(85936),u=n(85893);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,a.useRef)(null),{action:t}=(0,s.k6)(),n=(0,a.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,c.S)((n=>{let{location:a}=n;e.current&&!a.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const g=(0,l.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function h(e){const t=e.children??g,{containerRef:n,onClick:a}=f();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":g,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:a,children:t})})}var m=n(35281),b=n(19727);const y={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(h,{className:y.skipToContent})}var x=n(86668),w=n(59689);function _(e){let{width:t=21,height:n=21,color:a="currentColor",strokeWidth:r=1.2,className:o,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:a,strokeWidth:r,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const k={closeButton:"closeButton_CVFx"};function S(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,l.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,r.Z)("clean-btn close",k.closeButton,e.className),children:(0,u.jsx)(_,{width:14,height:14,strokeWidth:3.1})})}const E={content:"content_knG7"};function j(e){const{announcementBar:t}=(0,x.L)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,r.Z)(E.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const C={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function T(){const{announcementBar:e}=(0,x.L)(),{isActive:t,close:n}=(0,w.nT)();if(!t)return null;const{backgroundColor:a,textColor:r,isCloseable:o}=e;return(0,u.jsxs)("div",{className:C.announcementBar,style:{backgroundColor:a,color:r},role:"banner",children:[o&&(0,u.jsx)("div",{className:C.announcementBarPlaceholder}),(0,u.jsx)(j,{className:C.announcementBarContent}),o&&(0,u.jsx)(S,{onClick:n,className:C.announcementBarClose})]})}var A=n(93163),L=n(12466);var P=n(902),N=n(13102);const M=a.createContext(null);function R(e){let{children:t}=e;const n=function(){const e=(0,A.e)(),t=(0,N.HY)(),[n,r]=(0,a.useState)(!1),o=null!==t.component,i=(0,P.D9)(o);return(0,a.useEffect)((()=>{o&&!i&&r(!0)}),[o,i]),(0,a.useEffect)((()=>{o?e.shown||r(!0):r(!1)}),[e.shown,o]),(0,a.useMemo)((()=>[n,r]),[n])}();return(0,u.jsx)(M.Provider,{value:n,children:t})}function O(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function I(){const e=(0,a.useContext)(M);if(!e)throw new P.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,r=(0,a.useCallback)((()=>n(!1)),[n]),o=(0,N.HY)();return(0,a.useMemo)((()=>({shown:t,hide:r,content:O(o)})),[r,o,t])}function F(e){let{header:t,primaryMenu:n,secondaryMenu:a}=e;const{shown:o}=I();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,r.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":o}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:a})]})]})}var D=n(92949),B=n(72389);function z(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function $(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const U={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function Z(e){let{className:t,buttonClassName:n,value:a,onChange:o}=e;const i=(0,B.Z)(),s=(0,l.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===a?(0,l.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,l.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,r.Z)(U.toggle,t),children:(0,u.jsxs)("button",{className:(0,r.Z)("clean-btn",U.toggleButton,!i&&U.toggleButtonDisabled,n),type:"button",onClick:()=>o("dark"===a?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite",children:[(0,u.jsx)(z,{className:(0,r.Z)(U.toggleIcon,U.lightToggleIcon)}),(0,u.jsx)($,{className:(0,r.Z)(U.toggleIcon,U.darkToggleIcon)})]})})}const H=a.memo(Z),V={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function W(e){let{className:t}=e;const n=(0,x.L)().navbar.style,a=(0,x.L)().colorMode.disableSwitch,{colorMode:r,setColorMode:o}=(0,D.I)();return a?null:(0,u.jsx)(H,{className:t,buttonClassName:"dark"===n?V.darkNavbarColorModeToggle:void 0,value:r,onChange:o})}var q=n(21327);function G(){return(0,u.jsx)(q.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function K(){const e=(0,A.e)();return(0,u.jsx)("button",{type:"button","aria-label":(0,l.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(_,{color:"var(--ifm-color-emphasis-600)"})})}function Y(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(G,{}),(0,u.jsx)(W,{className:"margin-right--md"}),(0,u.jsx)(K,{})]})}var Q=n(39960),X=n(44996),J=n(13919),ee=n(98022),te=n(39471);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:a,href:r,label:o,html:i,isDropdownLink:s,prependBaseUrlToHref:l,...c}=e;const d=(0,X.Z)(a),p=(0,X.Z)(t),f=(0,X.Z)(r,{forcePrependBaseUrl:!0}),g=o&&r&&!(0,J.Z)(r),h=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[o,g&&(0,u.jsx)(te.Z,{...s&&{width:12,height:12}})]})};return r?(0,u.jsx)(Q.Z,{href:l?f:r,...c,...h}):(0,u.jsx)(Q.Z,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?(0,ee.F)(n,t.pathname):t.pathname.startsWith(p)},...c,...h})}function ae(e){let{className:t,isDropdownItem:n=!1,...a}=e;const o=(0,u.jsx)(ne,{className:(0,r.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...a});return n?(0,u.jsx)("li",{children:o}):o}function re(e){let{className:t,isDropdownItem:n,...a}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,r.Z)("menu__link",t),...a})})}function oe(e){let{mobile:t=!1,position:n,...a}=e;const r=t?re:ae;return(0,u.jsx)(r,{...a,activeClassName:a.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(86043),se=n(48596),le=n(52263);function ce(e,t){return e.some((e=>function(e,t){return!!(0,se.Mg)(e.to,t)||!!(0,ee.F)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function ue(e){let{items:t,position:n,className:o,onClick:i,...s}=e;const l=(0,a.useRef)(null),[c,d]=(0,a.useState)(!1);return(0,a.useEffect)((()=>{const e=e=>{l.current&&!l.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[l]),(0,u.jsxs)("div",{ref:l,className:(0,r.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,r.Z)("navbar__link",o),...s,onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))},children:s.children??s.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,a.createElement)(Ze,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function de(e){let{items:t,className:n,position:o,onClick:i,...l}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,le.Z)(),{pathname:t}=(0,s.TH)();return t.replace(e,"/")}(),d=ce(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:g}=(0,ie.u)({initialState:()=>!d});return(0,a.useEffect)((()=>{d&&g(!d)}),[c,d,g]),(0,u.jsxs)("li",{className:(0,r.Z)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,u.jsx)(ne,{role:"button",className:(0,r.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n),...l,onClick:e=>{e.preventDefault(),f()},children:l.children??l.label}),(0,u.jsx)(ie.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,a.createElement)(Ze,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function pe(e){let{mobile:t=!1,...n}=e;const a=t?de:ue;return(0,u.jsx)(a,{...n})}var fe=n(94711);function ge(e){let{width:t=20,height:n=20,...a}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...a,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const he="iconLanguage_nlXk";function me(){return a.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},a.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}var be=n(20830),ye=["translations"];function ve(){return ve=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,a=new Array(t);n=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var ke="Ctrl";var Se=a.forwardRef((function(e,t){var n=e.translations,r=void 0===n?{}:n,o=_e(e,ye),i=r.buttonText,s=void 0===i?"Search":i,l=r.buttonAriaLabel,c=void 0===l?"Search":l,u=xe((0,a.useState)(null),2),d=u[0],p=u[1];return(0,a.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?p("\u2318"):p(ke))}),[]),a.createElement("button",ve({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},o,{ref:t}),a.createElement("span",{className:"DocSearch-Button-Container"},a.createElement(be.W,null),a.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),a.createElement("span",{className:"DocSearch-Button-Keys"},null!==d&&a.createElement(a.Fragment,null,a.createElement("kbd",{className:"DocSearch-Button-Key"},d===ke?a.createElement(me,null):d),a.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))})),Ee=n(35742),je=n(66177),Ce=n(239),Te=n(43320);var Ae=n(73935);const Le={button:{buttonText:(0,l.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,l.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,l.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,l.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,l.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,l.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,l.I)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,l.I)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,l.I)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,l.I)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,l.I)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,l.I)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,l.I)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,l.I)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,l.I)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,l.I)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,l.I)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,l.I)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,l.I)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,l.I)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,l.I)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,l.I)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,l.I)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,l.I)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,l.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,l.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,l.I)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Pe=null;function Ne(e){let{hit:t,children:n}=e;return(0,u.jsx)(Q.Z,{to:t.url,children:n})}function Me(e){let{state:t,onClose:n}=e;const a=(0,je.M)();return(0,u.jsx)(Q.Z,{to:a(t.query),onClick:n,children:(0,u.jsx)(l.Z,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits},children:"See all {count} results"})})}function Re(e){let{contextualSearch:t,externalUrlRegex:r,...o}=e;const{siteMetadata:i}=(0,le.Z)(),l=(0,Ce.l)(),c=function(){const{locale:e,tags:t}=(0,Te._q)();return[`language:${e}`,t.map((e=>`docusaurus_tag:${e}`))]}(),d=o.searchParameters?.facetFilters??[],p=t?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(c,d):d,f={...o.searchParameters,facetFilters:p},g=(0,s.k6)(),h=(0,a.useRef)(null),m=(0,a.useRef)(null),[b,y]=(0,a.useState)(!1),[v,x]=(0,a.useState)(void 0),w=(0,a.useCallback)((()=>Pe?Promise.resolve():Promise.all([n.e(1426).then(n.bind(n,61426)),Promise.all([n.e(532),n.e(6945)]).then(n.bind(n,46945)),Promise.all([n.e(532),n.e(2090)]).then(n.bind(n,18894))]).then((e=>{let[{DocSearchModal:t}]=e;Pe=t}))),[]),_=(0,a.useCallback)((()=>{w().then((()=>{h.current=document.createElement("div"),document.body.insertBefore(h.current,document.body.firstChild),y(!0)}))}),[w,y]),k=(0,a.useCallback)((()=>{y(!1),h.current?.remove()}),[y]),S=(0,a.useCallback)((e=>{w().then((()=>{y(!0),x(e.key)}))}),[w,y,x]),E=(0,a.useRef)({navigate(e){let{itemUrl:t}=e;(0,ee.F)(r,t)?window.location.href=t:g.push(t)}}).current,j=(0,a.useRef)((e=>o.transformItems?o.transformItems(e):e.map((e=>({...e,url:l(e.url)}))))).current,C=(0,a.useMemo)((()=>e=>(0,u.jsx)(Me,{...e,onClose:k})),[k]),T=(0,a.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",i.docusaurusVersion),e)),[i.docusaurusVersion]);return function(e){var t=e.isOpen,n=e.onOpen,r=e.onClose,o=e.onInput,i=e.searchButtonRef;a.useEffect((function(){function e(e){var a;(27===e.keyCode&&t||"k"===(null===(a=e.key)||void 0===a?void 0:a.toLowerCase())&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?r():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),i&&i.current===document.activeElement&&o&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&o(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,r,o,i])}({isOpen:b,onOpen:_,onClose:k,onInput:S,searchButtonRef:m}),(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(Ee.Z,{children:(0,u.jsx)("link",{rel:"preconnect",href:`https://${o.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})}),(0,u.jsx)(Se,{onTouchStart:w,onFocus:w,onMouseOver:w,onClick:_,ref:m,translations:Le.button}),b&&Pe&&h.current&&(0,Ae.createPortal)((0,u.jsx)(Pe,{onClose:k,initialScrollY:window.scrollY,initialQuery:v,navigator:E,transformItems:j,hitComponent:Ne,transformSearchClient:T,...o.searchPagePath&&{resultsFooterComponent:C},...o,searchParameters:f,placeholder:Le.placeholder,translations:Le.modal}),h.current)]})}function Oe(){const{siteConfig:e}=(0,le.Z)();return(0,u.jsx)(Re,{...e.themeConfig.algolia})}const Ie={navbarSearchContainer:"navbarSearchContainer_Bca1"};function Fe(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,r.Z)(n,Ie.navbarSearchContainer),children:t})}var De=n(80143),Be=n(53438);var ze=n(60373);const $e=e=>e.docs.find((t=>t.id===e.mainDocId));const Ue={default:oe,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:a,queryString:r="",...o}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,le.Z)(),p=(0,fe.l)(),{search:f,hash:g}=(0,s.TH)(),h=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${g}${r}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...a],m=t?(0,l.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(pe,{...o,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ge,{className:he}),m]}),items:h})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(Fe,{className:n,children:(0,u.jsx)(Oe,{})})},dropdown:pe,html:function(e){let{value:t,className:n,mobile:a=!1,isDropdownItem:o=!1}=e;const i=o?"li":"div";return(0,u.jsx)(i,{className:(0,r.Z)({navbar__item:!a&&!o,"menu__list-item":a},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:a,...r}=e;const{activeDoc:o}=(0,De.Iw)(a),i=(0,Be.vY)(t,a),s=o?.path===i?.path;return null===i||i.unlisted&&!s?null:(0,u.jsx)(oe,{exact:!0,...r,isActive:()=>s||!!o?.sidebar&&o.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:a,...r}=e;const{activeDoc:o}=(0,De.Iw)(a),i=(0,Be.oz)(t,a).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(oe,{exact:!0,...r,isActive:()=>o?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:a,...r}=e;const o=(0,Be.lO)(a)[0],i=t??o.label,s=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(o).path;return(0,u.jsx)(oe,{...r,label:i,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:a,dropdownItemsBefore:r,dropdownItemsAfter:o,...i}=e;const{search:c,hash:d}=(0,s.TH)(),p=(0,De.Iw)(n),f=(0,De.gB)(n),{savePreferredVersionName:g}=(0,ze.J)(n),h=[...r,...f.map((e=>{const t=p.alternateDocVersions[e.name]??$e(e);return{label:e.label,to:`${t.path}${c}${d}`,isActive:()=>e===p.activeVersion,onClick:()=>g(e.name)}})),...o],m=(0,Be.lO)(n)[0],b=t&&h.length>1?(0,l.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):m.label,y=t&&h.length>1?void 0:$e(m).path;return h.length<=1?(0,u.jsx)(oe,{...i,mobile:t,label:b,to:y,isActive:a?()=>!1:void 0}):(0,u.jsx)(pe,{...i,mobile:t,label:b,to:y,items:h,isActive:a?()=>!1:void 0})}};function Ze(e){let{type:t,...n}=e;const a=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),r=Ue[a];if(!r)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(r,{...n})}function He(){const e=(0,A.e)(),t=(0,x.L)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,a.createElement)(Ze,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function Ve(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(l.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function We(){const e=0===(0,x.L)().navbar.items.length,t=I();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(Ve,{onClick:()=>t.hide()}),t.content]})}function qe(){const e=(0,A.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,a.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(F,{header:(0,u.jsx)(Y,{}),primaryMenu:(0,u.jsx)(He,{}),secondaryMenu:(0,u.jsx)(We,{})}):null}const Ge={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Ke(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,r.Z)("navbar-sidebar__backdrop",e.className)})}function Ye(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,x.L)(),i=(0,A.e)(),{navbarRef:s,isNavbarVisible:d}=function(e){const[t,n]=(0,a.useState)(e),r=(0,a.useRef)(!1),o=(0,a.useRef)(0),i=(0,a.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,L.RF)(((t,a)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+c{if(!e)return;const a=t.location.hash;if(a?document.getElementById(a.substring(1)):void 0)return r.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:s,"aria-label":(0,l.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,r.Z)("navbar","navbar--fixed-top",n&&[Ge.navbarHideable,!d&&Ge.navbarHidden],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(Ke,{onClick:i.toggle}),(0,u.jsx)(qe,{})]})}var Qe=n(69690);const Xe="right";function Je(e){let{width:t=30,height:n=30,className:a,...r}=e;return(0,u.jsx)("svg",{className:a,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...r,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function et(){const{toggle:e,shown:t}=(0,A.e)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,l.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(Je,{})})}const tt={colorModeToggle:"colorModeToggle_DEke"};function nt(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(Qe.QW,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,u.jsx)(Ze,{...e})},t)))})}function at(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function rt(){const e=(0,A.e)(),t=(0,x.L)().navbar.items,[n,a]=function(e){function t(e){return"left"===(e.position??Xe)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),r=t.find((e=>"search"===e.type));return(0,u.jsx)(at,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(et,{}),(0,u.jsx)(G,{}),(0,u.jsx)(nt,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(nt,{items:a}),(0,u.jsx)(W,{className:tt.colorModeToggle}),!r&&(0,u.jsx)(Fe,{children:(0,u.jsx)(Oe,{})})]})})}function ot(){return(0,u.jsx)(Ye,{children:(0,u.jsx)(rt,{})})}function it(e){let{item:t}=e;const{to:n,href:a,label:r,prependBaseUrlToHref:o,...i}=t,s=(0,X.Z)(n),l=(0,X.Z)(a,{forcePrependBaseUrl:!0});return(0,u.jsxs)(Q.Z,{className:"footer__link-item",...a?{href:o?l:a}:{to:s},...i,children:[r,a&&!(0,J.Z)(a)&&(0,u.jsx)(te.Z,{})]})}function st(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(it,{item:t})},t.href??t.to)}function lt(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(st,{item:e},t)))})]})}function ct(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(lt,{column:e},t)))})}function ut(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function dt(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(it,{item:t})}function pt(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(a.Fragment,{children:[(0,u.jsx)(dt,{item:e}),t.length!==n+1&&(0,u.jsx)(ut,{})]},n)))})})}function ft(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(ct,{columns:t}):(0,u.jsx)(pt,{links:t})}var gt=n(19965);const ht={footerLogoLink:"footerLogoLink_BH7S"};function mt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.C)(),a={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(gt.Z,{className:(0,r.Z)("footer__logo",t.className),alt:t.alt,sources:a,width:t.width,height:t.height,style:t.style})}function bt(e){let{logo:t}=e;return t.href?(0,u.jsx)(Q.Z,{href:t.href,className:ht.footerLogoLink,target:t.target,children:(0,u.jsx)(mt,{logo:t})}):(0,u.jsx)(mt,{logo:t})}function yt(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function vt(e){let{style:t,links:n,logo:a,copyright:o}=e;return(0,u.jsx)("footer",{className:(0,r.Z)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(a||o)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[a&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:a}),o]})]})})}function xt(){const{footer:e}=(0,x.L)();if(!e)return null;const{copyright:t,links:n,logo:a,style:r}=e;return(0,u.jsx)(vt,{style:r,links:n&&n.length>0&&(0,u.jsx)(ft,{links:n}),logo:a&&(0,u.jsx)(bt,{logo:a}),copyright:t&&(0,u.jsx)(yt,{copyright:t})})}const wt=a.memo(xt),_t=(0,P.Qc)([D.S,w.pl,L.OC,ze.L5,i.VC,function(e){let{children:t}=e;return(0,u.jsx)(N.n2,{children:(0,u.jsx)(A.M,{children:(0,u.jsx)(R,{children:t})})})}]);function kt(e){let{children:t}=e;return(0,u.jsx)(_t,{children:t})}var St=n(92503);function Et(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(St.Z,{as:"h1",className:"hero__title",children:(0,u.jsx)(l.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(Qe.Cw,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(Qe.aG,{error:t})})]})})})}const jt={mainWrapper:"mainWrapper_z2l0"};function Ct(e){const{children:t,noFooter:n,wrapperClassName:a,title:s,description:l}=e;return(0,b.t)(),(0,u.jsxs)(kt,{children:[(0,u.jsx)(i.d,{title:s,description:l}),(0,u.jsx)(v,{}),(0,u.jsx)(T,{}),(0,u.jsx)(ot,{}),(0,u.jsx)("div",{id:d,className:(0,r.Z)(m.k.wrapper.main,jt.mainWrapper,a),children:(0,u.jsx)(o.Z,{fallback:e=>(0,u.jsx)(Et,{...e}),children:t})}),!n&&(0,u.jsx)(wt,{})]})}},21327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});n(67294);var a=n(39960),r=n(44996),o=n(52263),i=n(86668),s=n(19965),l=n(85893);function c(e){let{logo:t,alt:n,imageClassName:a}=e;const o={light:(0,r.Z)(t.src),dark:(0,r.Z)(t.srcDark||t.src)},i=(0,l.jsx)(s.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return a?(0,l.jsx)("div",{className:a,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,o.Z)(),{navbar:{title:n,logo:s}}=(0,i.L)(),{imageClassName:u,titleClassName:d,...p}=e,f=(0,r.Z)(s?.href||"/"),g=n?"":t,h=s?.alt??g;return(0,l.jsxs)(a.Z,{to:f,...p,...s?.target&&{target:s.target},children:[s&&(0,l.jsx)(c,{logo:s,alt:h,imageClassName:u}),null!=n&&(0,l.jsx)("b",{className:d,children:n})]})}},90197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(67294);var a=n(35742),r=n(85893);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return(0,r.jsxs)(a.Z,{children:[t&&(0,r.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,r.jsx)("meta",{name:"docusaurus_version",content:n}),o&&(0,r.jsx)("meta",{name:"docusaurus_tag",content:o}),i&&(0,r.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,r.jsx)("meta",{name:"docsearch:version",content:n}),o&&(0,r.jsx)("meta",{name:"docsearch:docusaurus_tag",content:o})]})}},19965:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var a=n(67294),r=n(86010),o=n(72389),i=n(92949);const s={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var l=n(85893);function c(e){let{className:t,children:n}=e;const c=(0,o.Z)(),{colorMode:u}=(0,i.I)();return(0,l.jsx)(l.Fragment,{children:(c?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const o=n({theme:e,className:(0,r.Z)(t,s.themedComponent,s[`themedComponent--${e}`])});return(0,l.jsx)(a.Fragment,{children:o},e)}))})}function u(e){const{sources:t,className:n,alt:a,...r}=e;return(0,l.jsx)(c,{className:n,children:e=>{let{theme:n,className:o}=e;return(0,l.jsx)("img",{src:t[n],alt:a,className:o,...r})}})}},86043:(e,t,n)=>{"use strict";n.d(t,{u:()=>c,z:()=>b});var a=n(67294),r=n(10412),o=n(20469),i=n(91442),s=n(85893);const l="ease-in-out";function c(e){let{initialState:t}=e;const[n,r]=(0,a.useState)(t??!1),o=(0,a.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:o}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const o=(0,a.useRef)(!1);(0,a.useEffect)((()=>{const e=t.current;function a(){const t=e.scrollHeight,n=r?.duration??function(e){if((0,i.n)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${r?.easing??l}`,height:`${t}px`}}function s(){const t=a();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return p(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function g(e){if(!r.Z.canUseDOM)return e?u:d}function h(e){let{as:t="div",collapsed:n,children:r,animation:o,onCollapseTransitionEnd:i,className:l,disableSSRStyle:c}=e;const u=(0,a.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:o}),(0,s.jsx)(t,{ref:u,style:c?void 0:g(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),i?.(n))},className:l,children:r})}function m(e){let{collapsed:t,...n}=e;const[r,i]=(0,a.useState)(!t),[l,c]=(0,a.useState)(t);return(0,o.Z)((()=>{t||i(!0)}),[t]),(0,o.Z)((()=>{r&&c(t)}),[r,t]),r?(0,s.jsx)(h,{...n,collapsed:l}):null}function b(e){let{lazy:t,...n}=e;const a=t?m:h;return(0,s.jsx)(a,{...n})}},59689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>h,pl:()=>g});var a=n(67294),r=n(72389),o=n(50012),i=n(902),s=n(86668),l=n(85893);const c=(0,o.WA)("docusaurus.announcement.dismiss"),u=(0,o.WA)("docusaurus.announcement.id"),d=()=>"true"===c.get(),p=e=>c.set(String(e)),f=a.createContext(null);function g(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.L)(),t=(0,r.Z)(),[n,o]=(0,a.useState)((()=>!!t&&d()));(0,a.useEffect)((()=>{o(d())}),[]);const i=(0,a.useCallback)((()=>{p(!0),o(!0)}),[]);return(0,a.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const a=t!==n;u.set(t),a&&p(!1),!a&&d()||o(!1)}),[e]),(0,a.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,l.jsx)(f.Provider,{value:n,children:t})}function h(){const e=(0,a.useContext)(f);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},92949:(e,t,n)=>{"use strict";n.d(t,{I:()=>b,S:()=>m});var a=n(67294),r=n(10412),o=n(902),i=n(50012),s=n(86668),l=n(85893);const c=a.createContext(void 0),u="theme",d=(0,i.WA)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,g=e=>r.Z.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),h=e=>{d.set(f(e))};function m(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[r,o]=(0,a.useState)(g(e));(0,a.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,a.useCallback)((function(t,a){void 0===a&&(a={});const{persist:r=!0}=a;t?(o(t),r&&h(t)):(o(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,a.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(r))}),[r]),(0,a.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const l=(0,a.useRef)(!1);return(0,a.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),a=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:i(null)};return e.addListener(a),()=>e.removeListener(a)}),[i,t,n]),(0,a.useMemo)((()=>({colorMode:r,setColorMode:i,get isDarkTheme(){return r===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[r,i])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function b(){const e=(0,a.useContext)(c);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},60373:(e,t,n)=>{"use strict";n.d(t,{J:()=>v,L5:()=>b,Oh:()=>x});var a=n(67294),r=n(80143),o=n(29935),i=n(86668),s=n(53438),l=n(902),c=n(50012),u=n(85893);const d=e=>`docs-preferred-version-${e}`,p={save:(e,t,n)=>{(0,c.WA)(d(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.WA)(d(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.WA)(d(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const g=a.createContext(null);function h(){const e=(0,r._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,a.useMemo)((()=>Object.keys(e)),[e]),[o,s]=(0,a.useState)((()=>f(n)));(0,a.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:a}=e;function r(e){const t=p.read(e,n);return a[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,r(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,a.useMemo)((()=>({savePreferredVersion:function(e,n){p.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function m(e){let{children:t}=e;const n=h();return(0,u.jsx)(g.Provider,{value:n,children:t})}function b(e){let{children:t}=e;return s.cE?(0,u.jsx)(m,{children:t}):(0,u.jsx)(u.Fragment,{children:t})}function y(){const e=(0,a.useContext)(g);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=o.m);const t=(0,r.zh)(e),[n,i]=y(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,a.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}function x(){const e=(0,r._r)(),[t]=y();function n(n){const a=e[n],{preferredVersionName:r}=t[n];return a.versions.find((e=>e.name===r))??null}const a=Object.keys(e);return Object.fromEntries(a.map((e=>[e,n(e)])))}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>c,b:()=>l});var a=n(67294),r=n(902),o=n(85893);const i=Symbol("EmptyContext"),s=a.createContext(i);function l(e){let{children:t,name:n,items:r}=e;const i=(0,a.useMemo)((()=>n&&r?{name:n,items:r}:null),[n,r]);return(0,o.jsx)(s.Provider,{value:i,children:t})}function c(){const e=(0,a.useContext)(s);if(e===i)throw new r.i6("DocsSidebarProvider");return e}},74477:(e,t,n)=>{"use strict";n.d(t,{E:()=>l,q:()=>s});var a=n(67294),r=n(902),o=n(85893);const i=a.createContext(null);function s(e){let{children:t,version:n}=e;return(0,o.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,a.useContext)(i);if(null===e)throw new r.i6("DocsVersionProvider");return e}},93163:(e,t,n)=>{"use strict";n.d(t,{M:()=>p,e:()=>f});var a=n(67294),r=n(13102),o=n(87524),i=n(91980),s=n(86668),l=n(902),c=n(85893);const u=a.createContext(void 0);function d(){const e=function(){const e=(0,r.HY)(),{items:t}=(0,s.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[l,c]=(0,a.useState)(!1);(0,i.Rb)((()=>{if(l)return c(!1),!1}));const u=(0,a.useCallback)((()=>{c((e=>!e))}),[]);return(0,a.useEffect)((()=>{"desktop"===t&&c(!1)}),[t]),(0,a.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:l})),[e,n,u,l])}function p(e){let{children:t}=e;const n=d();return(0,c.jsx)(u.Provider,{value:n,children:t})}function f(){const e=a.useContext(u);if(void 0===e)throw new l.i6("NavbarMobileSidebarProvider");return e}},13102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>l,Zo:()=>c,n2:()=>s});var a=n(67294),r=n(902),o=n(85893);const i=a.createContext(null);function s(e){let{children:t}=e;const n=(0,a.useState)({component:null,props:null});return(0,o.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,a.useContext)(i);if(!e)throw new r.i6("NavbarSecondaryMenuContentProvider");return e[0]}function c(e){let{component:t,props:n}=e;const o=(0,a.useContext)(i);if(!o)throw new r.i6("NavbarSecondaryMenuContentProvider");const[,s]=o,l=(0,r.Ql)(n);return(0,a.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,a.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},19727:(e,t,n)=>{"use strict";n.d(t,{h:()=>r,t:()=>o});var a=n(67294);const r="navigation-with-keyboard";function o(){(0,a.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(r),"mousedown"===e.type&&document.body.classList.remove(r)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(r),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},66177:(e,t,n)=>{"use strict";n.d(t,{K:()=>s,M:()=>l});var a=n(67294),r=n(52263),o=n(91980);const i="q";function s(){return(0,o.Nc)(i)}function l(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,r.Z)(),{algolia:{searchPagePath:n}}=t;return(0,a.useCallback)((t=>`${e}${n}?${i}=${encodeURIComponent(t)}`),[e,n])}},87524:(e,t,n)=>{"use strict";n.d(t,{i:()=>s});var a=n(67294),r=n(10412);const o={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(){const[e,t]=(0,a.useState)((()=>"ssr"));return(0,a.useEffect)((()=>{function e(){t(function(){if(!r.Z.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>i?o.desktop:o.mobile}())}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[]),e}},35281:(e,t,n)=>{"use strict";n.d(t,{k:()=>a});const a={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},91442:(e,t,n)=>{"use strict";function a(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>a})},53438:(e,t,n)=>{"use strict";n.d(t,{LM:()=>f,SN:()=>S,_F:()=>m,cE:()=>p,f:()=>y,lO:()=>w,oz:()=>_,s1:()=>x,vY:()=>k});var a=n(67294),r=n(16550),o=n(18790),i=n(80143),s=n(60373),l=n(74477),c=n(1116),u=n(67392),d=n(48596);const p=!!i._r;function f(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=f(t);if(e)return e}}(e):void 0:e.href}const g=(e,t)=>void 0!==e&&(0,d.Mg)(e,t),h=(e,t)=>e.some((e=>m(e,t)));function m(e,t){return"link"===e.type?g(e.href,t):"category"===e.type&&(g(e.href,t)||h(e.items,t))}function b(e,t){switch(e.type){case"category":return m(e,t)||e.items.some((e=>b(e,t)));case"link":return!e.unlisted||m(e,t);default:return!1}}function y(e,t){return(0,a.useMemo)((()=>e.filter((e=>b(e,t)))),[e,t])}function v(e){let{sidebarItems:t,pathname:n,onlyCategories:a=!1}=e;const r=[];return function e(t){for(const o of t)if("category"===o.type&&((0,d.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,d.Mg)(o.href,n)){return a&&"category"!==o.type||r.unshift(o),!0}return!1}(t),r}function x(){const e=(0,c.V)(),{pathname:t}=(0,r.TH)(),n=(0,i.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?v({sidebarItems:e.items,pathname:t}):null}function w(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,s.J)(e),r=(0,i.yW)(e);return(0,a.useMemo)((()=>(0,u.j)([t,n,r].filter(Boolean))),[t,n,r])}function _(e,t){const n=w(t);return(0,a.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),a=t.find((t=>t[0]===e));if(!a)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return a[1]}),[e,n])}function k(e,t){const n=w(t);return(0,a.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),a=t.find((t=>t.id===e));if(!a){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,u.j)(t.map((e=>e.id))).join("\n- ")}`)}return a}),[e,n])}function S(e){let{route:t}=e;const n=(0,r.TH)(),a=(0,l.E)(),i=t.routes,s=i.find((e=>(0,r.LX)(n.pathname,e)));if(!s)return null;const c=s.sidebar,u=c?a.docsSidebars[c]:void 0;return{docElement:(0,o.H)(i),sidebarName:c,sidebarItems:u}}},69690:(e,t,n)=>{"use strict";n.d(t,{aG:()=>u,Ac:()=>c,Cw:()=>l,QW:()=>d});var a=n(67294),r=n(95999),o=n(18780);const i={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};var s=n(85893);function l(e){return(0,s.jsx)("button",{type:"button",...e,children:(0,s.jsx)(r.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function c(e){let{error:t,tryAgain:n}=e;return(0,s.jsxs)("div",{className:i.errorBoundaryFallback,children:[(0,s.jsx)("p",{children:t.message}),(0,s.jsx)(l,{onClick:n})]})}function u(e){let{error:t}=e;const n=(0,o.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,s.jsx)("p",{className:i.errorBoundaryError,children:n})}class d extends a.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}},82128:(e,t,n)=>{"use strict";n.d(t,{p:()=>r});var a=n(52263);function r(e){const{siteConfig:t}=(0,a.Z)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}},91980:(e,t,n)=>{"use strict";n.d(t,{Nc:()=>l,Rb:()=>i,_X:()=>s});var a=n(67294),r=n(16550),o=n(902);function i(e){!function(e){const t=(0,r.k6)(),n=(0,o.zX)(e);(0,a.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function s(e){return function(e){const t=(0,r.k6)();return(0,a.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}function l(e){const t=s(e)??"",n=function(){const e=(0,r.k6)();return(0,a.useCallback)(((t,n,a)=>{const r=new URLSearchParams(e.location.search);n?r.set(t,n):r.delete(t),(a?.push?e.push:e.replace)({search:r.toString()})}),[e])}();return[t,(0,a.useCallback)(((t,a)=>{n(e,t,a)}),[n,e])]}},67392:(e,t,n)=>{"use strict";function a(e,t){return void 0===t&&(t=(e,t)=>e===t),e.filter(((n,a)=>e.findIndex((e=>t(e,n)))!==a))}function r(e){return Array.from(new Set(e))}n.d(t,{j:()=>r,l:()=>a})},10833:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>d,VC:()=>g});var a=n(67294),r=n(86010),o=n(35742),i=n(30226);function s(){const e=a.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(44996),c=n(82128),u=n(85893);function d(e){let{title:t,description:n,keywords:a,image:r,children:i}=e;const s=(0,c.p)(t),{withBaseUrl:d}=(0,l.C)(),p=r?d(r,{absolute:!0}):void 0;return(0,u.jsxs)(o.Z,{children:[t&&(0,u.jsx)("title",{children:s}),t&&(0,u.jsx)("meta",{property:"og:title",content:s}),n&&(0,u.jsx)("meta",{name:"description",content:n}),n&&(0,u.jsx)("meta",{property:"og:description",content:n}),a&&(0,u.jsx)("meta",{name:"keywords",content:Array.isArray(a)?a.join(","):a}),p&&(0,u.jsx)("meta",{property:"og:image",content:p}),p&&(0,u.jsx)("meta",{name:"twitter:image",content:p}),i]})}const p=a.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=a.useContext(p),s=(0,r.Z)(i,t);return(0,u.jsxs)(p.Provider,{value:s,children:[(0,u.jsx)(o.Z,{children:(0,u.jsx)("html",{className:s})}),n]})}function g(e){let{children:t}=e;const n=s(),a=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const o=`plugin-id-${n.plugin.id}`;return(0,u.jsx)(f,{className:(0,r.Z)(a,o),children:t})}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>s,Qc:()=>u,Ql:()=>c,i6:()=>l,zX:()=>i});var a=n(67294),r=n(20469),o=n(85893);function i(e){const t=(0,a.useRef)(e);return(0,r.Z)((()=>{t.current=e}),[e]),(0,a.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,a.useRef)();return(0,r.Z)((()=>{t.current=e})),t.current}class l extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function c(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,a.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,o.jsx)(o.Fragment,{children:e.reduceRight(((e,t)=>(0,o.jsx)(t,{children:e})),n)})}}},98022:(e,t,n)=>{"use strict";function a(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{F:()=>a})},48596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>s});var a=n(67294),r=n(723),o=n(52263);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,a.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function a(e){return e.path===t&&!0===e.exact}function r(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(a)||e(t.filter(r).flatMap((e=>e.routes??[])))}(n)}({routes:r.Z,baseUrl:e})),[e])}},12466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>h,OC:()=>u,RF:()=>f,o5:()=>g});var a=n(67294),r=n(10412),o=n(72389),i=n(20469),s=n(902),l=n(85893);const c=a.createContext(void 0);function u(e){let{children:t}=e;const n=function(){const e=(0,a.useRef)(!0);return(0,a.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function d(){const e=(0,a.useContext)(c);if(null==e)throw new s.i6("ScrollControllerProvider");return e}const p=()=>r.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function f(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=d(),r=(0,a.useRef)(p()),o=(0,s.zX)(e);(0,a.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=p();o(e,r.current),r.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function g(){const e=d(),t=function(){const e=(0,a.useRef)({elem:null,top:0}),t=(0,a.useCallback)((t=>{e.current={elem:t,top:t.getBoundingClientRect().top}}),[]),n=(0,a.useCallback)((()=>{const{current:{elem:t,top:n}}=e;if(!t)return{restored:!1};const a=t.getBoundingClientRect().top-n;return a&&window.scrollBy({left:0,top:a}),e.current={elem:null,top:0},{restored:0!==a}}),[]);return(0,a.useMemo)((()=>({save:t,restore:n})),[n,t])}(),n=(0,a.useRef)(void 0),r=(0,a.useCallback)((a=>{t.save(a),e.disableScrollEvents(),n.current=()=>{const{restored:a}=t.restore();if(n.current=void 0,a){const t=()=>{e.enableScrollEvents(),window.removeEventListener("scroll",t)};window.addEventListener("scroll",t)}else e.enableScrollEvents()}}),[e,t]);return(0,i.Z)((()=>{queueMicrotask((()=>n.current?.()))})),{blockElementScrollPositionUntilNextRender:r}}function h(){const e=(0,a.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function a(){const r=document.documentElement.scrollTop;(n&&r>e||!n&&rt&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},43320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>i,_q:()=>l,os:()=>s});var a=n(80143),r=n(52263),o=n(60373);const i="default";function s(e,t){return`docs-${e}-${t}`}function l(){const{i18n:e}=(0,r.Z)(),t=(0,a._r)(),n=(0,a.WS)(),l=(0,o.Oh)();const c=[i,...Object.keys(t).map((function(e){const a=n?.activePlugin.pluginId===e?n.activeVersion:void 0,r=l[e],o=t[e].versions.find((e=>e.isLast));return s(e,(a??r??o).name)}))];return{locale:e.currentLocale,tags:c}}},50012:(e,t,n)=>{"use strict";n.d(t,{Nk:()=>u,WA:()=>c});var a=n(67294);const r="localStorage";function o(e){let{key:t,oldValue:n,newValue:a,storage:r}=e;if(n===a)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,a,window.location.href,r),window.dispatchEvent(o)}function i(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,s||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),s=!0),null}var t}let s=!1;const l={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function c(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=i(t?.persistence);return null===n?l:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const a=n.getItem(e);n.setItem(e,t),o({key:e,oldValue:a,newValue:t,storage:n})}catch(a){console.error(`Docusaurus storage error, can't set ${e}=${t}`,a)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),o({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const a=a=>{a.storageArea===n&&a.key===e&&t(a)};return window.addEventListener("storage",a),()=>window.removeEventListener("storage",a)}catch(a){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,a),()=>{}}}}}function u(e,t){const n=(0,a.useRef)((()=>null===e?l:c(e,t))).current(),r=(0,a.useCallback)((e=>"undefined"==typeof window?()=>{}:n.listen(e)),[n]);return[(0,a.useSyncExternalStore)(r,(()=>"undefined"==typeof window?null:n.get()),(()=>null)),n]}},94711:(e,t,n)=>{"use strict";n.d(t,{l:()=>i});var a=n(52263),r=n(16550),o=n(18780);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,a.Z)(),{pathname:l}=(0,r.TH)(),c=(0,o.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace(`/${s}/`,"/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:a}=e;return`${a?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},85936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var a=n(67294),r=n(16550),o=n(902);function i(e){const t=(0,r.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,a.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},86668:(e,t,n)=>{"use strict";n.d(t,{L:()=>r});var a=n(52263);function r(){return(0,a.Z)().siteConfig.themeConfig}},6278:(e,t,n)=>{"use strict";n.d(t,{L:()=>r});var a=n(52263);function r(){const{siteConfig:{themeConfig:e}}=(0,a.Z)();return e}},239:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var a=n(67294),r=n(98022),o=n(44996),i=n(6278);function s(){const{withBaseUrl:e}=(0,o.C)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.L)();return(0,a.useCallback)((a=>{const o=new URL(a);if((0,r.F)(t,o.href))return a;const i=`${o.pathname+o.hash}`;return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:a}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[r]=e.split(/[#?]/),o="/"===r||r===a?r:(i=r,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(r,o)}},54143:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},18780:function(e,t,n){"use strict";var a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var r=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return a(r).default}});var o=n(54143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return o.getErrorCausalChain}})},86010:(e,t,n)=>{"use strict";function a(e){var t,n,r="";if("string"==typeof e||"number"==typeof e)r+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;tr});const r=function(){for(var e,t,n=0,r="";n{"use strict";n.d(t,{lX:()=>k,q_:()=>A,ob:()=>h,PP:()=>P,Ep:()=>g,Hp:()=>m});var a=n(83117);function r(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,a=n+1,r=e.length;a=0;p--){var f=i[p];"."===f?o(i,p):".."===f?(o(i,p),d++):d&&(o(i,p),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&r(i[0])||i.unshift("");var g=i.join("/");return n&&"/"!==g.substr(-1)&&(g+="/"),g};function s(e){return e.valueOf?e.valueOf():Object.prototype.valueOf.call(e)}const l=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every((function(t,a){return e(t,n[a])}));if("object"==typeof t||"object"==typeof n){var a=s(t),r=s(n);return a!==t||r!==n?e(a,r):Object.keys(Object.assign({},t,n)).every((function(a){return e(t[a],n[a])}))}return!1};var c=n(38776);function u(e){return"/"===e.charAt(0)?e:"/"+e}function d(e){return"/"===e.charAt(0)?e.substr(1):e}function p(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function f(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function g(e){var t=e.pathname,n=e.search,a=e.hash,r=t||"/";return n&&"?"!==n&&(r+="?"===n.charAt(0)?n:"?"+n),a&&"#"!==a&&(r+="#"===a.charAt(0)?a:"#"+a),r}function h(e,t,n,r){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",a="",r=t.indexOf("#");-1!==r&&(a=t.substr(r),t=t.substr(0,r));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===a?"":a}}(e),o.state=t):(void 0===(o=(0,a.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(o.key=n),r?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,r.pathname)):o.pathname=r.pathname:o.pathname||(o.pathname="/"),o}function m(e,t){return e.pathname===t.pathname&&e.search===t.search&&e.hash===t.hash&&e.key===t.key&&l(e.state,t.state)}function b(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,a,r){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof a?a(o,r):r(!0):r(!1!==o)}else r(!0)},appendListener:function(e){var n=!0;function a(){n&&e.apply(void 0,arguments)}return t.push(a),function(){n=!1,t=t.filter((function(e){return e!==a}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),a=0;at?n.splice(t,n.length-t,r):n.push(r),d({action:a,location:r,index:t,entries:n})}}))},replace:function(e,t){var a="REPLACE",r=h(e,t,p(),x.location);u.confirmTransitionTo(r,a,n,(function(e){e&&(x.entries[x.index]=r,d({action:a,location:r}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=x.index+e;return t>=0&&t{"use strict";var a=n(59864),r={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return a.isMemo(e)?i:s[e.$$typeof]||r}s[a.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[a.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,g=Object.prototype;e.exports=function e(t,n,a){if("string"!=typeof n){if(g){var r=f(n);r&&r!==g&&e(t,r,a)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),h=l(n),m=0;m{"use strict";e.exports=function(e,t,n,a,r,o,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,a,r,o,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},32497:(e,t,n)=>{"use strict";n.r(t)},52295:(e,t,n)=>{"use strict";n.r(t)},74865:function(e,t,n){var a,r;a=function(){var e,t,n={version:"0.2.0"},a=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function r(e,t,n){return en?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var r;return(r="translate3d"===a.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===a.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,r}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(a[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=r(e,a.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(a.barSelector),u=a.speed,d=a.easing;return o.offsetWidth,s((function(t){""===a.positionUsing&&(a.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),a.trickleSpeed)};return a.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*r(Math.random()*t,.1,.95)),t=r(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*a.trickleRate)},e=0,t=0,n.promise=function(a){return a&&"resolved"!==a.state()?(0===t&&n.start(),e++,t++,a.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=a.template;var r,i=t.querySelector(a.barSelector),s=e?"-100":o(n.status||0),c=document.querySelector(a.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),a.showSpinner||(r=t.querySelector(a.spinnerSelector))&&f(r),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(a.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function a(t){var n=document.body.style;if(t in n)return t;for(var a,r=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);r--;)if((a=e[r]+o)in n)return a;return t}function r(e){return e=n(e),t[e]||(t[e]=a(e))}function o(e,t,n){t=r(t),e.style[t]=n}return function(e,t){var n,a,r=arguments;if(2==r.length)for(n in t)void 0!==(a=t[n])&&t.hasOwnProperty(n)&&o(e,n,a);else o(e,r[1],r[2])}}();function c(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),a=n+t;c(n,t)||(e.className=a.substring(1))}function d(e,t){var n,a=p(e);c(e,t)&&(n=a.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(r="function"==typeof a?a.call(t,n,t,e):a)||(e.exports=r)},40485:()=>{!function(e){var t={pattern:/((?:^|[^\\$])(?:\\{2})*)\$(?:\w+|\{[^{}]*\})/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:null}}};e.languages.groovy=e.languages.extend("clike",{string:{pattern:/'''(?:[^\\]|\\[\s\S])*?'''|'(?:\\.|[^\\'\r\n])*'/,greedy:!0},keyword:/\b(?:abstract|as|assert|boolean|break|byte|case|catch|char|class|const|continue|def|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|in|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\b/,number:/\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?\d+)?)[glidf]?\b/i,operator:{pattern:/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.\.(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),e.languages.insertBefore("groovy","string",{shebang:{pattern:/#!.+/,alias:"comment",greedy:!0},"interpolation-string":{pattern:/"""(?:[^\\]|\\[\s\S])*?"""|(["/])(?:\\.|(?!\1)[^\\\r\n])*\1|\$\/(?:[^/$]|\$(?:[/$]|(?![/$]))|\/(?!\$))*\/\$/,greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}}}),e.languages.insertBefore("groovy","punctuation",{"spock-block":/\b(?:and|cleanup|expect|given|setup|then|when|where):/}),e.languages.insertBefore("groovy","function",{annotation:{pattern:/(^|[^.])@\w+/,lookbehind:!0,alias:"punctuation"}}),t.inside.expression.inside=e.languages.groovy}(Prism)},52503:()=>{!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,a={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[a,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:a.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:a.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:a.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,(function(){return t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism)},32334:()=>{!function(e){e.languages.kotlin=e.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete e.languages.kotlin["class-name"];var t={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:e.languages.kotlin}};e.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:t},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:t},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete e.languages.kotlin.string,e.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),e.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),e.languages.kt=e.languages.kotlin,e.languages.kts=e.languages.kotlin}(Prism)},96854:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,a,r,o){if(n.language===a){var i=n.tokenStack=[];n.code=n.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,s=i.length;-1!==n.code.indexOf(r=t(a,s));)++s;return i[s]=e,r})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,a){if(n.language===a&&n.tokenStack){n.grammar=e.languages[a];var r=0,o=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=o.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[r],d=n.tokenStack[u],p="string"==typeof c?c:c.content,f=t(a,u),g=p.indexOf(f);if(g>-1){++r;var h=p.substring(0,g),m=new e.Token(a,e.tokenize(d,n.grammar),"language-"+a,d),b=p.substring(g+f.length),y=[];h&&y.push.apply(y,i([h])),y.push(m),b&&y.push.apply(y,i([b])),"string"==typeof c?s.splice.apply(s,[l,1].concat(y)):c.content=y}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(Prism)},52811:(e,t,n)=>{var a={"./prism-groovy":40485,"./prism-java":52503,"./prism-kotlin":32334};function r(e){var t=o(e);return n(t)}function o(e){if(!n.o(a,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return a[e]}r.keys=function(){return Object.keys(a)},r.resolve=o,e.exports=r,r.id=52811},92703:(e,t,n)=>{"use strict";var a=n(50414);function r(){}function o(){}o.resetWarningCache=r,e.exports=function(){function e(e,t,n,r,o,i){if(i!==a){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:r};return n.PropTypes=n,n}},45697:(e,t,n)=>{e.exports=n(92703)()},50414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},64448:(e,t,n)=>{"use strict";var a=n(67294),r=n(63840);function o(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n
]]> + + - <![CDATA[경로 이미지 생성하기 - 구현]]> - https://greeng00se.github.io/route-image-implementation - - 2023-08-02T00:00:00.000Z - - 개요 -

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
-경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

-

구현 결과

-

./result.png

-

예시 데이터는 다음과 같다.
-서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

-
List<Double> x = List.of(
-        126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
-        126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
-);
-List<Double> y = List.of(
-        37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
-        37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
-);
-List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
-List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);
-
-

IMAGE_SIZE & ROUTE_SIZE

-
private static final int IMAGE_SIZE = 800;
-private static final int ROUTE_SIZE = 600;
-
-

코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
-IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
-ROUTE_SIZE의 경우 상하좌우 100px 만큼의 간격을 위해 존재한다.
-따라서 실제 경로 이미지의 크기는 600 * 600 사이즈로 생성된다.

-

./600.png

-

사이즈 변경의 이유

-

255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

-

주요 클래스

-

요약

-
클래스명설명특이사항
Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
CoordinatesCoordinate의 일급 컬렉션-
Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
PositionsPositions의 일급 컬렉션-
RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
-

의존관계

- -

Coordinates(위도, 경도의 일급 컬렉션)

-

List<Double> 2개(위도, 경도)인 형태로 관리하는 방법이 있었지만, 위치 점을 여러개 찍는 부분에서 로직이 복잡해 질 것 같아서 Coordinate(x, y)와 일급 컬렉션인 Coordinates로 관리하기로 했다.
-Coordinates 클래스에는 다음 두 개의 인터페이스가 존재한다.

-
    -
  • calculatePositions: 경로 이미지의 크기를 받아 실제 이미지 생성시 사용될 Positions를 반환
  • -
  • indexOf: 다른 Coordinates를 받아 동일한 위치점에 해당하는 인덱스를 반환하는
  • -
-

Positions 계산 로직은 다음과 같다.
-위도, 경도 각각에 대한 부분을 이미지 생성시 필요한 값으로 변환한다.

-
// 호출
-// List<Integer> xPositions = toPositions(xValues, maxDifference, routeImageSize);
-// List<Integer> yPositions = toPositions(yValues, maxDifference, routeImageSize);
-
-private List<Integer> toPositions(List<Double> values, Double maxDifference, Integer routeImageSize) {
-    Double minValue = Collections.min(values);
-    return values.stream()
-            .map(value -> normalizeCoordinate(value, maxDifference, minValue))
-            .map(value -> mapToPosition(value, routeImageSize))
-            .toList();
-}
-
-private double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {
-    return (coordinate - minValue) / maxDifference;
-}
-
-private int mapToPosition(Double coordinate, Integer routeImageSize) {
-    return (int) (coordinate * routeImageSize);
+        <![CDATA[자바 클래스 파일 구조]]>
+        https://greeng00se.github.io/java-class-file
+        
+        2023-04-03T00:00:00.000Z
+        
+        클래스 파일
+

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
+컴파일된 클래스파일은 어떤 구조로 되어있을까?

+

클래스 파일의 데이터 형식

+

8비트 바이트의 스트림으로 구성된다.
+16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
+멀티바이트의 경우 항상 big endian 순서로 저장된다.

+

u1 → unsigned 1byte
+u2 → unsigned 2byte
+u4 → unsigned 4byte

+

클래스 파일 구조

+
ClassFile {
+    u4             magic;
+    u2             minor_version;
+    u2             major_version;
+    u2             constant_pool_count;
+    cp_info        constant_pool[constant_pool_count-1];
+    u2             access_flags;
+    u2             this_class;
+    u2             super_class;
+    u2             interfaces_count;
+    u2             interfaces[interfaces_count];
+    u2             fields_count;
+    field_info     fields[fields_count];
+    u2             methods_count;
+    method_info    methods[methods_count];
+    u2             attributes_count;
+    attribute_info attributes[attributes_count];
 }
 
-

위도로 예시든 내용이다.

-
    -
  1. Collections.min(values) → 위도 리스트의 최소값을 구한다.
  2. -
  3. normalizeCoordinate → 각각의 위도 값에서 최소값을 빼고 0 ~ 1 사이 값으로 변환 후 위경도의 최대 차이로 나눈다.
  4. -
  5. mapToPosition → 그래프 크기를 받아 0 ~ 1 사이 값을 실제 이미지를 위한 위치값으로 변환한다.
  6. -
-

Positions(실제 이미지 생성에 사용할 위치)

-

Positions 클래스에는 다음 다섯 개의 인터페이스가 존재한다.

+

매직넘버

+

모든 클래스 파일은 0xCAFEBABE라는 매직넘버로 시작한다.
+보통 매직넘버는 파일 종류를 식별하는 용도로 사용된다.

+

클래스 파일 포맷 버전

+

클래스 파일 버전 값은 클래스로더의 호환성 보장을 위해 꼭 필요한 값이다.

    -
  • align: 이미지 사이즈와 경로 이미지 사이즈를 받아 Position 값들을 중앙 정렬한다.
  • -
  • getPositionsByIndexes: 인덱스 리스트를 받아 입력받은 인덱스에 해당하는 값들을 반환한다.
  • -
  • size: 크기를 반환한다.
  • -
  • xPositions: x 값들을 반환한다.
  • -
  • yPositions: y 값들을 반환한다.
  • +
  • Java 17 버전으로 빌드한다면 class version 61 ex) 00 00 00 3D
-

중앙 정렬 로직은 다음과 같다.

-
public Positions align(int imageSize, int routeSize) {
-    int xOffset = calculateOffset(Position::x, imageSize);
-    int yOffset = calculateOffset(Position::y, imageSize);
-
-    return items.stream()
-            .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))
-            .collect(collectingAndThen(toList(), Positions::new));
-}
-
-private int calculateOffset(ToIntFunction<Position> positionToInteger, int imageSize) {
-    List<Integer> positions = items.stream()
-            .mapToInt(positionToInteger)
-            .boxed()
-            .toList();
-
-    int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;
-    return imageSize / 2 - midValue;
-}
-
-

상하좌우 여백을 동일하게 주기 위해서 offset 값을 구해서 x, y 값에 각각 더하는 형태로 중앙 정렬을 수행했다.
-BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

-

./800.png

-

따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

-

x 값 → 계산한 offset 그대로 더한다.
-y 값 → imageSize(800)에서 y + offset 값을 뺀다.

-

RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

-

BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
-그림을 그리기 위해 설정한 상수들이 존재한다.

-
// RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
-// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
-// 이를 RGBA라고 부른다.
-private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
-// 배경 투명색
-private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
-// 경로를 위한 STROKE
-private static final int LINE_STROKE_WIDTH = 7;
-private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
-// 위치 점을 위한 STROKE
-private static final int POINT_STROKE_WIDTH = 20;
-private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
-// 안티앨리어싱 등 화질 개선을 위한 설정
-private static final Map<Object, Object> renderingHints = Map.of(
-        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
-        RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
-        RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
-);
-
-

RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

+

호환되지 않는 버전의 클래스 파일을 로딩하려고 하는 경우 런타임에 UnsupportedClassVersionError 예외가 발생한다.

+

class file format major versions

+
Java SEReleasedMajorSupported majors
8March 20145245 .. 52
9September 20175345 .. 53
10March 20185445 .. 54
11September 20185545 .. 55
12March 20195645 .. 56
13September 20195745 .. 57
14March 20205845 .. 58
15September 20205945 .. 59
16March 20216045 .. 60
17September 20216145 .. 61
+

상수 풀

+

2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
+클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
+JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

+

액세스 플래그

+

클래스, 인터페이스와 같은 파일의 속성을 표시한다.
+예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.

    -
  • drawLine: 선을 그린다.
  • -
  • drawPoint: 점을 찍는다.
  • -
  • dispose: 자원 할당을 해제한다.
  • +
  • 계산은 다음과 같이 이루어진다. ACC_PUBLIC xor ACC_INTERFACE xor ACC_ABSTRACT
-

dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

-

이미지 생성 Flow

-

1. 이미지 생성 준비

- -

2. 선 그리기 요청

- -

3. 위치 점 그리기 요청

- -

4. 업로드 요청

- -

전체 Flow

-]]>
- - - - - <![CDATA[경로 이미지 생성하기 - 파이썬]]> - https://greeng00se.github.io/route-image-python - - 2023-07-31T00:00:00.000Z - - 개요 -

이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

-

사용 기술

-

언어: Python 3.10
-이미지 생성: matplotlib
-서비스: AWS Lambda, AWS API Gateway
-이미지 저장 및 URL: AWS S3, AWS CloudFront

-

플로우는 다음과 같다.

- -

요구사항

-

./route.png

-

우측 상단의 경로 이미지를 생성하려고 한다.
-경로 이미지 생성에 대한 요구사항은 다음과 같다.

-
    -
  • 위도, 경도로 이루어진 배열을 입력받는다.
  • -
  • 이미지 생성
  • -
  • 선과 점 표현
  • -
  • 투명한 배경색
  • -
  • 위경도 차이가 크든 작든 제공하는 이미지 내에 경로가 다 포함되어 있어야 한다.
  • -
-

이미지 출력 방식

-
    -
  1. 위경도를 처리한 값으로 직접 경로를 그린 다음 이미지 형태로 저장
  2. -
  3. 플롯을 그려주는 라이브러리 사용하여 이미지 형태로 저장
  4. -
-

이미지 출력 방식의 경우 1번과 2번을 고민했었다.
-파이썬으로는 플롯을 그려주는 라이브러리인 matplotlib을 사용했다.

-

로컬에서 기능 구현

-
import time
-
-import matplotlib.pyplot as plt
-
-
-def draw(point):
-    start = time.time()
-    x, y = zip(*point)
-    pixel_x, pixel_y = convert_to_pixel_values(x, y)
-    draw_lines(pixel_x, pixel_y)
-    end = time.time()
-    print(end - start)
-    
-def convert_to_pixel_values(x, y):
-    max_diff = max(max(x) - min(x), max(y) - min(y))
-    return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)
-
-
-def scale_to_pixel_values(points, max_diff):
-    min_value = min(points)
-    scaled_coordinates = [(p - min_value) / max_diff for p in points]
-    return scaled_coordinates
-
-
-def draw_lines(x, y):
-    figure = plt.gcf()
-    figure.set_size_inches(5, 5)
-    plt.plot(x, y, c = 'w',linewidth=5)
-    plt.scatter(x[3],y[3], c = 'w', s = 125)
-    plt.axis('off')
-    plt.savefig('name.png', transparent=True, format='png')
-
-point = [
-    [126.96352960597338, 37.590841000217125],
-    [126.96987292787792, 37.58435564234159],
-    [126.98128481452298, 37.58594375113966],
-    [126.99360339342958, 37.58248524741927],
-    [126.99867565340067, 37.56778118088622],
-    [127.001935378366117, 37.55985240444085],
-    [126.9831048919687, 37.548030119488665],
-    [126.97189273528845, 37.5119879225856],
-    [127.02689859997221, 37.48488593333883]
-]
-
-draw(point)
-
-

생성 결과는 아래와 같다. (예시를 위해 검은색으로 출력)

-

./routeImage.png

-

AWS Lambda

-

썸네일 생성 서버를 따로 두기는 기능 대비 비용이 너무 클 것이라고 생각했다.
-따라서 서버리스로 파일을 처리했다.
-추가로 s3 접근은 boto3를 사용했다.

-

람다 S3 접근을 위한 IAM 생성

-

AmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy 두가지를 추가해서 Lambda 전용 역할을 만들어 사용했다.

-

람다 배포용 코드

-

기술 구현 가능 여부를 확인할 땐 위치 점을 찍는 기능을 람다에 배포하지 않았다.

-

-import io
-import uuid
-
-import boto3
-import matplotlib.pyplot as plt
-
-PIXEL = 255
-BUCKET_NAME = 'image-plot'
-S3 = 's3'
-
-def lambda_handler(event, context):
-    x = event['x']
-    y = event['y']
-    image_name = str(uuid.uuid4())
-
-    img_data = draw(x, y)
-    s3 = boto3.client(S3)
-    s3.put_object(Body=img_data.getvalue(), ContentType='image/png', Bucket=BUCKET_NAME, Key=image_name)
-    url = f'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}'
-
-    return {
-        'statusCode': 200,
-        'body': url
-    }
-
-def draw(x, y):
-    pixel_x, pixel_y = convert_to_pixel_values(x, y)
-    img_data = draw_lines(pixel_x, pixel_y)
-    plt.close()
-    return img_data
-
-def convert_to_pixel_values(x, y):
-    max_diff = max(max(x) - min(x), max(y) - min(y))
-    return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)
-
-def scale_to_pixel_values(points, max_diff):
-    min_value = min(points)
-    scaled_coordinates = [(p - min_value) / max_diff for p in points]
-    pixel_values = [int(p * PIXEL) for p in scaled_coordinates]
-    return pixel_values
-
-def draw_lines(x, y):
-    plt.plot(x, y, 'k-', linewidth=10)
-    plt.axis('off')
-    img_data = io.BytesIO()
-    plt.savefig(img_data, transparent=True, format='png')
-    img_data.seek(0)
-    return img_data
-
-
-

Layer 추가를 위한 zip 파일 생성

-

matplotlib의 경우 외부 라이브러리기 때문에 따로 Layer를 추가해야 한다.
-zip 파일을 만들어서 업로드해야한다.
-이때 python의 Lambda 런타임에 대한 계층 경로는 python이다.
-따라서 압축한 zip 파일은 다음과 같은 구조를 띄어야 한다.

-
pillow.zip
-│ python/PIL
-└ python/Pillow-5.3.0.dist-info
-
-

Ubuntu 기준 다음 명령어를 입력하여 생성을 진행했다.

-
sudo apt update
-sudo apt install zip
-sudo apt install python3-pip
-
-mkdir python
-pip3 install matplotlib -t python # pip3 install 설치할_패키지 -t 설치_경로
-zip -r my_layer.zip python # zip -r 압축_파일명 압축_파일이_존재하는_경로
-
-

No module named 'numpy.core._multiarray_umath' 에러

-

Layer 추가 후 람다 실행 시 발생한 에러였다.
-처음에 mac에서 zip 파일을 생성해서 업로드했는데 해당 문제가 발생했다.
-이는 lambda가 돌아가는 동일한 환경에서 layer를 위한 zip 파일을 만들지 않아서 발생하는 문제다.
-간단하게 ec2 인스턴스를 하나 만들어서 따로 Layer를 생성하면 문제가 발생하지 않는다.

-

적정기술에 대한 생각

-

프로젝트에 Lambda와 Python을 사용하려고 했지만 아쉽게도 반려당했다.
-AWS Lambda를 사용하는 것은 인스턴스에 해당 코드를 배포하는 것보다 더 효율적인 방법일 수 있다.
-하지만 현재 프로젝트에서 가용 가능한 자원, 기술의 난이도, 사용하는 팀원을 고려한다면 Lambda는 적정기술이 아닐 수 있다.
-따라서 해당 이미지 생성기를 어떻게 적용할지 조금 더 고려를 해야 될 것으로 보인다.

-

최종적으로 Java AWT를 사용하기로 결정했다.

-

참고 자료

-

AWS Lambda
-Lambda Layer
-Python Lambda 함수에 대한 .zip 파일 아카이브 작업
-No module named 'numpy.core._multiarray_umath'
-사례별로 알아본 안전한 S3 사용 가이드

]]>
- - +

공식문서에 들어가면 각 플래그에 대한 설명 + 플래그 설정시 동시에 설정되면 안되는 플래그와 같은 설명이 자세하게 나와있다.

+

Class access and property modifiers

+
Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_FINAL0x0010Declared final; no subclasses allowed.
ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
ACC_INTERFACE0x0200Is an interface, not a class.
ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ANNOTATION0x2000Declared as an annotation type.
ACC_ENUM0x4000Declared as an enum type.
ACC_MODULE0x8000Is a module, not a class or interface.
+

this_class

+

클래스명과 같은 이름을 표현하는 값으로, 상수 풀에서 클래스명과 일치하는 항목의 인덱스를 참조한다.
+해당 인덱스의 항목은 CONSTANT_Class_infoclass 형식의 값이어야 한다.

+

super_class

+

상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
+아무것도 상속하지 않는 클래스의 경우 java.lang.Object의 인덱스 값이 들어있다.

+

interface, field, method

+

각각의 개수와, 정보에 대한 값이 들어있다.
+interface, field, method를 표시하는 방법이 각각 다르고, 접근자에 대한 플래그도 각각 다르다.

+

attributes

+

해당 클래스 파일에서 사용하는 추가 정보의 모음이다. 예) 소스파일명
+정해진 클래스 파일의 구조를 확장하는 역할을 한다.

+

클래스 파일 확인하면서 사용한 툴

+

IntelliJ plugin - BinEd
+IntelliJ plugin - jclasslib Bytecode Viewer

+

참고 자료

+

2장 JVM 이야기, 자바 최적화
+Class file in Java, File Format
+java se11 Class 파일 형식, Oracle
+java se17 Class 파일 형식, Oracle

]]> + +
- <![CDATA[Mockito 이용해서 static 메서드 모킹하기]]> - https://greeng00se.github.io/mock-static-method - - 2023-07-30T00:00:00.000Z - - 개요 -

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
-하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

-

예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

-

프로젝트를 진행하며 ImageIo.write 메서드가 호출되는 지 검증이 필요했다.
-해당 static 메서드를 호출하는 부분을 따로 RouteImageUploader 클래스로 최대한 분리했다.
-이미지 저장 기능 자체가 외부로 나가는 상호작용이고, 호출 횟수를 검사하는데는 mock을 사용하는게 적절하다고 판단했다.

-
public void upload(BufferedImage bufferedImage) {
-    File file = new File(파일경로);
-    try {
-        ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);
-    } catch (IOException e) {
-        throw new DrawException(IMAGE_SAVE_FAIL);
-    }
-}
-
-

Mocking static methods

-

Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
-mockStatic을 사용하면 MockedStatic<T>이 반환되는데 사용 후 꼭 close를 해줘야 한다.

-

JUnit의 @BeforeAll로 설정하고 @AfterAll 메서드로 종료하는 방법도 있지만 MockedStatic<T>의 상위 인터페이스인 ScopedMock이 AutoCloseable을 구현하고 있기에 try-with-resources를 사용하는 방법이 더욱 좋은 것 같다.

-
// given
-BufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);
-RouteImageUploader routeImageUploader = new RouteImageUploader();
-
-// expect
-try (MockedStatic<ImageIO> imageIO = Mockito.mockStatic(ImageIO.class)) {
-    routeImageUploader.upload(bufferedImage);
-    imageIO.verify(
-            () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),
-            times(1)
-    );
-}
-
-

마치며

-

정적 메서드를 모킹하는 것은 안티패턴이으로 적절한 추상화를 이용해 테스트 하기 좋은 코드를 만드는 연습을 하자.
-하지만 추상화를 하면 할 수록 코드의 복잡도는 증가한다.
-항상 상황을 고려하고 간결함을 포기할 만큼 중요한 부분인지 적절한 트레이드오프를 고려하자.

+ <![CDATA[테스트 대역]]> + https://greeng00se.github.io/test-double + + 2023-04-04T00:00:00.000Z + + 테스트 대역이란? +

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
+Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

+

테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
+외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

+

테스트 대역의 타입 계층 구조

+ +

더미(Dummy)

+

가장 단순하고, 원시적인 유형의 테스트 대역이다.
+기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
+만약 메서드가 무언가 반환을 해야하는 경우 0, null과 같은 값을 반환한다.

+

스텁(Stub)

+

시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
+이를 통해 특정 조건에서 메서드가 예상한대로 동작하는지 확인할 수 있다.

+

스파이(Spy)

+

스텁과 유사하지만 호출 여부를 기록하거나 호출할 때 전달한 인자값을 기록할 수 있다.
+예) 메일 전송 기능을 가진 객체를 테스트 대역으로 구현했을 때 메일 전송 횟수를 기록한다.

+

목, 모의 객체(Mock)

+

목은 더미, 스텁, 스파이를 포함한다.
+호출 시 사전에 정의된 결과를 반환하고, 예상치 못한 호출이 있을 경우 예외를 던질 수 있다.
+또한 호출에 대한 검증을 할 수 있다.

+

가짜(Fake)

+

DOC와 동일한 기능을 제공하지만, 더욱 간단한 방법으로 구현된 것이다.
+예) 실제 데이터베이스와 유사하게 동작하는 가짜 객체를 만들어 테스트할 수 있다.

+

의존 구성 요소, DOC를 테스트 더블로 대체할 수 있다.
+테스트 더블은 DOC와 동일한 API를 제공해야 한다.

+

상호작용에 따른 목과 스텁 구분

+

단위 테스트 p.149 에서는 테스트 대역을 크게 목과 스텁으로 구분한다.
+목은 SUT와 관련된 상호작용을 모방하고 검사하는 반면, 스텁은 단순 모방만 한다.

+
TestDoubleMockStub
포함 유형목, 스파이스텁, 더미, 페이크
용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
예시이메일 발송데이터 검색
+

테스트 대상 시스템
+테스트를 하려는 대상

참고 자료

-

Mocking static methods
-Mockito mock static methods
-Enable mocking static methods in Mockito

]]>
- - +

소프트웨어 장인 정신 이야기 - 3장 고급 테스트 주도 개발, 로버트 C. 마틴
+단위 테스트 - 5장 목과 테스트 취약성, 블라디미르 코리코프
+테스트 주도 개발 시작하기 - 7장 대역, 최범균
+테스트 더블, Martin Fowler
+테스트 관련 용어 정리, Johngrib
+Test Double, Gerard Meszaros

]]>
+ +
- <![CDATA[경로 이미지 생성하기 - 기술 선택]]> - https://greeng00se.github.io/route-image-intro - - 2023-07-27T00:00:00.000Z - - ./route.png

-

이미지 생성의 책임

-

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
-따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

-

해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

-
    -
  • 이미지 생성
  • -
  • 선과 점 표현
  • -
  • 투명한 배경색
  • -
-

현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

-

고려한 기술

-

백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

-
    -
  • Python의 Matplotlib
  • -
  • AWT(Abstract Window Toolkit) [최종 선택]
  • -
  • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
  • -
  • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)
  • -
-

Python & Matplotlib

-

데이터 시각화 라이브러리
-이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

-
    -
  • 코드가 간단해서 유지 보수성이 좋다.
  • -
  • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
  • -
  • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.
  • -
-

Java AWT 이외의 라이브러리

-

Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

-
라이브러리설명제외 이유
SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
-

Java & AWT(Abstract Window Toolkit)

-

그래픽과 이미지를 그리기 위한 도구
-이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

+ <![CDATA[트랜잭션과 격리수준]]> + https://greeng00se.github.io/transaction-and-isolation + + 2023-04-05T00:00:00.000Z + + 트랜잭션(Transaction) +

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
+트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
+논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

+

트랜잭션의 속성(ACID)

+

원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
+일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
+격리성(Isolation): 각각의 트랜잭션은 독립적이라 서로에게 영향을 주지 않아야 한다.
+지속성(Durability): 트랜잭션이 성공적으로 완료된다면 영구적으로 결과에 반영되어야 한다.

+

트랜잭션 주의사항

+

트랜잭션은 꼭 필요한 최소의 코드에만 적용하는 것이 좋다.(트랜잭션의 범위를 최소화하라)
+구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

+

데이터의 일관성과 안전성을 보장하기 위해 배제해야 한다.
+네트워크 작업을 트랜잭션 내부에 포함한다면 다음과 같은 문제가 발생할 수 있다.

    +
  • 네트워크 작업이 중간에 실패할 가능성(안전성 X)
  • +
  • 통신으로 인해 데이터가 변경될 수 있는 부분(일관성 X)
  • +
+

격리 수준(Isolation level)

+

여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 데이터의 조회 및 변경을 허용할지 결정하는 것을 말한다.
+격리 수준이 높아질 수록 동시 처리 성능이 떨어지는 것이 일반적이지만, SERIALIZABLE이 아니라면 크게 성능의 저하가 발생하지 않는다.

+

READ UNCOMMITTED

+

각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다.
+더티 리드 현상이 발생하기 때문에 정합성의 문제가 많은 격리 수준이다.
+MySQL 사용시 최소 READ COMMITTED 이상의 격리 수준 사용을 권장한다.

+ +

READ COMMITTED

+

트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
+오라클 DBMS에서 기본으로 사용되는 격리 수준이다.
+REPEATABLE READ가 보장되지 않기 때문에 NON-REPEATABLE READ 문제가 발생한다.

+ +

REPEATABLE READ

+

트랜잭션이 시작되기 전에 COMMIT이 완료된 내용에 대해서만 조회할 수 있다.
+MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준이다.
+MVCC를 이용해 언두(Undo) 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장한다.
+동일한 결과를 보장하는 방법은 다음과 같다.

    -
  • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
  • -
  • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
  • -
  • 추가적인 api 호출을 하지 않아도 된다.
  • +
  • 모든 InnoDB 트랜잭션은 순차적으로 증가하는 고유한 트랜잭션 번호를 가진다.
  • +
  • Undo 영역에 백업된 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함되어있다.
  • +
  • Undo 영역의 백업된 데이터는 스토리지 엔진이 불필요하다고 판단하는 경우 삭제된다.
  • +
  • REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 가장 오래된 트랜잭션 번호보다 앞선 Undo 영역의 데이터는 삭제하지 않는다.
-

기술 선택

-

AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
-하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

-

유지 보수

-

AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
-따라서 다음과 같은 방법으로 공유하기로 했다.

-
    -
  1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
  2. -
  3. AWT를 사용한 부분을 문서화하여 공유한다.
  4. -
-

레벨 3를 마무리하며 내용 추가

-

기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
-AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

]]>
- - +

InnoDB에서는 갭 락과 넥스트 키 락을 이용하여 팬텀 리드 현상을 방지한다.

+ +

갭 락: 레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
+넥스트 키 락: 레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.

+

동시성을 제어하는 방법 중 하나로 하나의 레코드에 대해 여러 개의 버전이 동시에 관리되는 것이다.

    +
  • PostgreSQL은 다중 버전의 데이터를 저장하는 것으로 MVCC를 구현한다.
  • +
  • Oracle, InnoDB는 Undo log를 이용해 이 기능을 구현한다.(최신 버전의 데이터만 DB에 저장)
  • +

잠금을 사용하지 않는 읽관된 읽기를 제공하는 것이 목적이다.

+

SERIALIZABLE

+

트랜잭션을 순차적으로 진행시키는 격리 수준이고 따라서 동시 처리 성능도 다른 격리 수준보다 떨어진다.
+트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 접근할 수 없고 단순한 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야만 한다.
+InnoDB에서는 팬텀 리드 현상이 REPEATABLE READ 격리 수준에서 발생하지 않기 때문에 굳이 사용할 필요는 없다.

+

격리 수준에 따른 부정합 문제

+

격리 수준에 따라 더티 리드, 반복 가능하지 않은 조회, 팬텀 리드 문제가 발생한다.

+
격리 수준 / 부정합 문제더티 리드반복 가능하지 않은 조회팬텀 리드
READ UNCOMMITTEDOOO
READ COMMITTEDXOO
REPEATABLE READXXO(InnoDB는 X)
SERIALIZABLEXXX
+

더티 리드(Dirty read)

+

어떤 트랜잭션에서 처리한 작업이 완료되지 않았어도 다른 트랜잭션에서 볼 수 있는 현상
+트랜잭션 격리 수준이 READ UNCOMMITTED일 때 발생한다.
+예) B가 레코드를 추가하고 커밋을 하지 않았지만, A가 해당 레코드를 조회할 수 있는 경우

+

반복 가능하지 않은 조회(Non-repeatable read)

+

한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 그 값이 다른 현상
+예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

+ +

팬텀 리드(Phantom read, Phantom row)

+

한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
+예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

+ +

참고 자료

+

Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
+Isolation Level, MySQL

]]>
+ + +
- <![CDATA[자바 17, 스프링 6.0, 스프링 부트 3.1]]> - https://greeng00se.github.io/java-spring-springboot - - 2023-07-24T00:00:00.000Z - - 자바 17, 스프링 6.0, 스프링 부트 3.1 -

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
-2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

-

자바 변경 사항

-

우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
-따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

-

Switch Expressions(Java 14)

-

Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

-
enum RESULT {
-    WIN, LOSE, DRAW
-}
-
-RESULT result = RESULT.WIN;
-
-int prize = switch (result) {
-    case WIN -> 10_000_000;
-    case LOSE, DRAW -> 5_000_000;
-	default -> 0;
-};
-
-

주요 특징은 다음과 같다.

+ <![CDATA[MySQL 엔진의 잠금]]> + https://greeng00se.github.io/mysql-lock + + 2023-04-06T00:00:00.000Z + + MySQL 엔진의 잠금 +

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
+MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

+

글로벌 락(Global lock)

+

MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

    -
  • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
  • -
  • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
  • -
  • break 문이 필요 없다.
  • -
  • default 블록을 통해 기본 값을 지정할 수 있다.
  • +
  • 영향을 미치는 범위는 해당 서버 전체이다.
  • +
  • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.
-

Text Block(Java 15)

-

Java 15에는 새로운 문자열 표현방식이 추가되었다.
-긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

-
@Repository
-public interface PostRepository extends JpaRepository<Post, Long> {
-    @Query("""
-        SELECT p FROM Post p
-        WHERE p.title LIKE %:keyword%
-        OR p.content LIKE %:keyword%
-        """)
-    List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
-}
+

한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
+데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
+InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

+
-- GLOBAL LOCK
+FLUSH TABLES WITH READ LOCK;
+-- UNLOCK
+UNLOCK TABLES;
+
+-- BACKUP LOCK
+LOCK INSTANCE FOR BACKUP;
+-- UNLOCK
+UNLOCK INSTANCE;
+
+

MySQL 5.5 버전 이전의 기본 스토리지 엔진이다.
+트랜잭션을 지원하지 않고, SELECT 작업 속도가 빠르다.

+

테이블 락(Table lock)

+

개별 테이블 단위로 설정되는 잠금이다.
+명시적 또는 묵시적으로 특정 테이블의 락을 획득할 수 있다.
+묵시적 락은 MyISAM이나 MEMORY 테이블에 데이터를 변경하는 쿼리를 실행하면 발생한다.
+InnoDB 테이블에는 DML 쿼리는 무시되고 DDL 일 경우에만 묵시적으로 락을 획득한다.

+
-- TABLE LOCK
+LOCK TABLES table_name [ READ | WRITE ]
+
+-- UNLOCK
+UNLOCK TABLES;
+
+

네임드 락(Named lock)

+

임의의 문자열에 대한 잠금을 설정할 수 있는 잠금으로 유저 레벨 락으로도 불린다.
+여러 스레드나 프로세스가 동일한 데이터를 수정하려는 경우, 동시에 수정하지 못하도록 보호할 수 있다.

+
-- aGVyYg== 라는 문자열에 대한 잠금 획득, 이미 잠금을 사용중인 경우 1초 동안만 대기
+SELECT GET_LOCK('aGVyYg==', 1);
+
+-- 문자열에 대한 잠금이 설정되어 있는지 확인한다.
+SELECT IS_FREE_LOCK('aGVyYg==');
+
+-- 문자열에 대한 잠금을 해제한다.
+SELECT RELEASE_LOCK('aGVyYg==');
+
+-- 위 3개 함수 모두 정상적으로 락을 획득하거나 해제한 경우에 1을, 아니면 0을 반환한다.
+
+-- 모든 문자열에 대한 잠금을 해제한다. 해제된 잠금의 개수를 반환한다.
+SELECT RELEASE_ALL_LOCKS();
+
+

메타데이터 락(Metadata lock)

+

데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
+명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
+보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

+
-- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
+-- 아래 구문 실행 시 메타데이터 락을 자동으로 획득한다.
+RENAME TABLE rank TO rank_backup, rank_new TO rank;
 
-

NPE 메시지(Java 15)

-
String name = null;
-name.chars();
-
-/** 
-# before
-java.lang.NullPointerException
-	at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)
-
-# after
-Cannot invoke "String.chars()" because "name" is null
-java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
-*/
-
-

Record(Java 16)

-

Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
-Record를 선언하는 경우 접근자, 생성자, equals & hashcode, toString이 제공된다.
-데이터 전송 용도로 적합해 보인다.

-
public record PostDto(String title, String content) {
-}
-
-

추가적인 변경사항

-

이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

-

스프링, 스프링 부트 변경 사항

-

스프링과 스프링 부트에도 많은 변경 사항이 있었다.
-따라서 필요해보이는 몇개 정도만 정리했다.

-

스프링 요구사항

-

Java 17, Jakarta EE 9 이상이어야 한다.

-

네임스페이스 변경

-

Jakarta EE 9가 적용되면서 네임스페이스도 전반적으로 javax -> jakarta로 변경되었다.

-

PathPatternParser - trailing slash 허용하지 않음

-

6.0 이전의 경우 기본 설정 기준으로 @GetMapping("/hello")@GetMapping("/hello/")가 동일했다.
-6.0 이후의 PathPatternParser가 기본으로 사용되고, /hello/hello/는 서로 다른 URL로 매칭된다.

-
-

PathPatternParser used by default (with the ability to opt into PathMatcher).

-
-

HTTP interface client

-

자바 인터페이스와 어노테이션을 이용하여 HTTP 요청을 위한 서비스를 정의할 수 있는 방법이 추가되었다.
-자세한 내용은 토비님의 강의를 참고하면 좋을 것 같다.

-

스프링 부트 최소 요구사항

-

Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6
-이외에도 서드파티들의 최신 릴리즈 버전을 사용함으로, 문제가 발생하는 경우 해당 버전에 맞는 릴리즈 노트를 참고할 수 있을 것 같다.

참고 자료

-

어느 월급쟁이개발자 의 스프링 부트 따라잡기
-자바 9-16 주요 특징 복습하기
-Java EE에서 Jakarta EE로의 전환
-Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩
-What's New in Spring Framework 6.x
-Spring Boot 3.0 Release Notes
-Spring Boot 3.1 Release Notes

]]> - - - +

Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
+MySQL의 User Level Lock를 활용한다면?, gywndi
+Locking Functions, MySQL 5.7 Reference
+Locking Functions, MySQL 8.0 Reference

]]> + + + - <![CDATA[웹소켓]]> - https://greeng00se.github.io/websocket - - 2023-06-26T00:00:00.000Z - - 웹소켓 -

단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
-웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

-

웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

-

웹소켓 등장 배경

-

웹소켓이 등장하기 이전, 실시간성을 보장하기 위해 Polling, Long polling, Streaming 같은 기술을 사용했어야 했다.
-이는 실시간성이나 양방향성을 만족시키지 못했고, HTTP를 이용하기 때문에 과도한 오버헤드가 발생했다.

-

Polling: 주기적으로 서버에 요청을 보내 수신할 정보가 있는지 확인하는 방법

    -
  • 서버에서 보낼 내용이 없어도 클라이언트는 알 수 없다.
  • -
  • 계속해서 요청을 보내 확인을 해야하기 때문에 서버에 불필요한 부하를 주어야 한다.
  • -

Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

    -
  • 폴링 방식보다 서버에 적은 부하를 줄 수 있지만, 요청의 주기가 짧으면 폴링과 차이가 없어진다.
  • -

Streaming: 클라이언트가 request를 보내면 커넥션을 맺고, 이 커넥션을 유지하면서 서버가 계속 데이터를 보내는 방법

    -
  • 클라이언트가 서버에 요청을 하고 싶다면 새로운 커넥션을 맺어야 한다.
  • -
-

웹소켓의 동작

- -

1. Upgrade 요청

-

WebSocket 프로토콜로 전환하는 HTTP 요청을 보낸다.
-이는 HTTP와 같이 80, 443 포트를 사용한다.
-웹소켓으로 전환하기 위해서는 Upgrade: websocket, Connection: Upgrade 헤더가 필요하다.
-Sec-WebSocket-Key는 서버에서 Sec-WebSocket-Accept를 계산하여 응답하고 이 값이 예상한 값과 다르면 연결이 수립되지 않는다.
-Sec-WebSocket-Protocol의 경우 서브프로토콜의 목록으로 서버 측에서는 해당 목록 중 하나를 선택하여 반환해야 한다.
-만약 서버측에서 여러 개 지원이 가능한 경우 지원 가능한 프로토콜 중 첫번째 프로토콜을 클라이언트측으로 보낸다.

-
GET /chats HTTP/1.1
-Host: localhost:8080
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
-Sec-WebSocket-Protocol: v10.stomp, v11.stomp
-Sec-WebSocket-Version: 13
-Origin: http://localhost:8080
+        <![CDATA[InnoDB 스토리지 엔진의 잠금]]>
+        https://greeng00se.github.io/innodb-lock
+        
+        2023-04-07T00:00:00.000Z
+        
+        InnoDB 스토리지 엔진의 잠금
+

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
+보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

+

동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
+InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

+

트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

+

트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
+일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

+

Shared & Exclusive Locks

+

InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

+

공유 잠금(S, shared lock)

+

데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
+다른 트랜잭션에서 읽기가 가능하지만, 쓰기는 불가능하다.
+예) SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;

+

배타적 잠금(X, exclusive lock)

+

데이터 변경을 위한 락, 쓰기 잠금(write lock)으로도 불린다.
+락을 건 트랜잭션만이 해당 데이터에 접근 가능하다. 다른 트랜잭션의 경우 읽기, 쓰기가 불가능하다.
+예) SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

+

Intention Locks

+

InnoDB는 로우 단위 잠금과 테이블 잠금의 공존을 위해 인텍션 잠금을 지원한다.
+테이블에 있는 로우에 대해서 나중에 요청되는 것이 어떤 형태의 잠금인지 가리키기 위해 사용된다.
+기본적으로 로우 단위 잠금을 수행하기 전에 인텐션 잠금을 먼저 획득한다.
+인텐션 락은 기본적으로 충돌을 방지하고 데드락을 방지하는 역할을 한다.

+

인텐션 공유 잠금(IS, intention shared lock)

+

트랜잭션이 테이블의 개별 로우에 대한 공유 잠금을 수행하는 것을 의미한다.

+

인텐션 배타적 잠금(IX, intention exclusive lock)

+

트랜잭션이 테이블의 개별 로우에 대한 배타적 잠금을 수행하는 것을 의미한다.

+

** 잠금간의 호환성 **

+
XIXSIS
XConflictConflictConflictConflict
IXConflictCompatibleConflictCompatible
SConflictConflictCompatibleCompatible
ISConflictCompatibleCompatibleCompatible
+

Record Locks

+

레코드 자체만을 잠그는 락이다.
+InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다.

+

Gap Locks

+

레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
+레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하고, 넥스트 키 락의 일부로 사용된다.

+

Next-Key Locks

+

레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.
+REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하기 위한 잠금이다.

+

AUTO-INC Locks

+

AUTO_INCREMENT 칼림이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 한다.
+InnoDB 는 내부적으로 AUTO-INC 락이라고 하는 테이블 수준의 잠금을 사용한다.
+트랜잭션과 관계 없이 INSERTREPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 해제된다.

+

잠금 예시

+
-- 레코드는 id 기준 10, 20, 30, 40, 50이 있다고 가정
+-- Record Locks: 10에 대해 락이 걸린다.
+SELECT * FROM table_name where id = 10 for update;
+
+-- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다.
+SELECT * FROM table_name where id > 100 for update;
+
+-- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다.
+SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;
 
-

2. Switching Protocols

-

서버는 101 Switching Protocols 응답을 반환한다.
-Sec-WebSocket-Accept은 Sec-WebSocket-Key 뒤에 258EAFA5-E914-47DA-95CA-C5AB0DC85B11를 붙이고 SHA1로 해싱 후 Base64로 인코딩하여 반환한다.
-이는 서버 웹소켓 프로토콜의 지원 여부를 클라이언트에게 명확히 알리기 위해 존재한다.

-
HTTP/1.1 101 Switching Protocols 
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
-Sec-WebSocket-Protocol: v10.stomp
-
-

3. 통신 후 종료

-

연결이 수립되면 웹소켓 프레임 단위로 양방향 통신을 한다.
-연결 종료를 원하는 경우 클라이언트, 서버 모두 연결 종료를 요청할 수 있다.

-

참고 자료

-

https://datatracker.ietf.org/doc/html/rfc6455
-https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
-https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
-https://docs.spring.io/spring-framework/reference/web/websocket.html

]]>
- +

참고 자료

+

Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
+Optimistic and Pessimistic record locking, IBM
+MySQL Innodb Locks, cecil1018
+MySQL 8.0 InnoDB Locks, MySQL
+Locks Set by Different SQL Statements in InnoDB, MySQL

]]> + + + - <![CDATA[Docusaurus]]> - https://greeng00se.github.io/docusaurus - - 2023-06-18T00:00:00.000Z - - 팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

-

설치

-

공식 홈페이지에 들어가서 최신 버전을 설치한다.

-
yarn create docusaurus
-
-

배포

-

배포 안내 문서
-netlify나 vercel 같은 서버리스 플랫폼을 추천하고 있고, 간단하고, 빠른 시간 안에 배포를 할 수 있다.
-이 글에서는 github pages를 이용해서 배포하는 방법을 설명한다.

-

레포지토리 생성

-

github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
-이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

-

설정 파일 수정

-
module.exports = {
-  // ...
-  url: 'https://greeng00se.github.io',
-  baseUrl: '/',
-  projectName: 'greeng00se.github.io',
-  organizationName: 'greeng00se',
-  trailingSlash: false,
-  // ...
-};
-
-

토큰 설정

-

github action을 위해 배포용 토큰을 하나 생성하여 생성한 레포지토리에 Repository secrets으로 설정한다.
-이 글에서는 토큰을 클래식 방식으로 생성했고 스코프는 [repo, user, workflow] 을 설정했다.

-

github

-

브랜치 생성

-

github에서 gh-pages 브랜치를 하나 생성한다.
-repository -> settings -> pages -> branch에서 생성한 gh-pages로 브랜치를 변경한다.
-설정한 브랜치가 배포 브랜치가 되며, 해당 브랜치에 있는 파일들을 이용해서 정적 웹사이트를 제공한다.

-

워크플로 작성

-

Docusaurus 2.0 기준 Node.js 16.14 이상의 버전을 사용해야 합니다.
-배포시에는 Repository secrets으로 설정한 DEPLOY_TOKEN 을 이용합니다.

-
name: blog
-
-on:
-  push:
-    branches: [main]
-
-jobs:
-  deploy:
-    name: Deploy to GitHub Pages
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-node@v3
-        with:
-          node-version: 18
-          cache: yarn
-
-      - name: Install dependencies
-        run: yarn install --frozen-lockfile
-      - name: Build website
-        run: yarn build
-
-      - name: Deploy to GitHub Pages
-        uses: peaceiris/actions-gh-pages@v3
-        with:
-          github_token: ${{ secrets.DEPLOY_TOKEN }}
-          publish_dir: ./build
-          user_name: github-actions[bot]
-          user_email: 41898282+github-actions[bot]@users.noreply.github.com
-
-

댓글 기능

-

giscus를 이용하여 댓글 기능을 추가한다.

-

giscus 설정

-
    -
  1. 공개 저장소여야 한다.
  2. -
  3. giscus 앱이 설치되어 있어야 한다.
  4. -
  5. Discussions 기능이 해당 저장소에서 활성화되어 있어야 한다.
  6. -
-

자세한 내용은 giscus를 확인하자.

-

docusaurus 설정

-

swizzling을 이용하여 컴포넌트를 감싼다.
-기존에 게시물을 giscus가 포함된 리액트 컴포넌트로 감싸는 형태가 된다.
-아래 명령어를 이용하여 BlogPostItem을 추출할 수 있다.

-
yarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap
-
-

명령어를 입력하면 /src/theme/BlogPostItem/index.js 위치에 파일이 생성된다.
-파일의 내용을 아래와 같이 수정하고, 이때 setAttribute 부분은 적절하게 자신의 giscus 설정을 이용한다.

-
import OriginalBlogPostItem from "@theme-original/BlogPostItem";
-import React, { useEffect, useRef } from "react";
-// @ts-expect-error internal code
-import { useColorMode } from "@docusaurus/theme-common";
-import { useBlogPost } from "@docusaurus/theme-common/internal";
-
-const giscusSelector = "iframe.giscus-frame";
-
-function BlogPostItem(props) {
-  const { colorMode } = useColorMode();
-  const { isBlogPostPage } = useBlogPost();
-  const giscusTheme = colorMode === "dark" ? "dark" : "light";
-  const containerRef = useRef(null);
-
-  useEffect(() => {
-    if (!isBlogPostPage) return;
-
-    const giscusEl = containerRef.current.querySelector(giscusSelector);
-
-    const createGiscusEl = () => {
-      const script = document.createElement("script");
-
-      script.src = "https://giscus.app/client.js";
-      script.setAttribute("data-repo", "teco-chat/teco-chat.github.io");
-      script.setAttribute("data-repo-id", "R_kgDOJZ5j0Q");
-      script.setAttribute("data-category", "Announcements");
-      script.setAttribute("data-category-id", "DIC_kwDOJZ5j0c4CXS_Q");
-      script.setAttribute("data-mapping", "pathname");
-      script.setAttribute("data-strict", "0");
-      script.setAttribute("data-reactions-enabled", "1");
-      script.setAttribute("data-emit-metadata", "0");
-      script.setAttribute("data-input-position", "bottom");
-      script.setAttribute("data-theme", giscusTheme);
-      script.setAttribute("data-lang", "ko");
-      script.crossOrigin = "anonymous";
-      script.async = true;
-      
-      containerRef.current.appendChild(script);
-    };
-
-    const postThemeMessage = () => {
-      const message = {
-        setConfig: {
-          theme: giscusTheme,
-        }
-      };
-
-      giscusEl.contentWindow.postMessage({ giscus: message }, "https://giscus.app");
-    };
-
-    giscusEl ? postThemeMessage() : createGiscusEl();
-  }, [giscusTheme]);
-
-  return (
-    <>
-      <OriginalBlogPostItem {...props} />
-      {isBlogPostPage && <div ref={containerRef} />}
-    </>
-  );
-}
-
-export default BlogPostItem;
-
-

알고리아 설정 및 직접 관리하기

-

알고리아를 사용하면 검색 기능을 추가할 수 있다.
-유료 플랜이나 netlify를 사용하는 경우 크롤러를 따로 제공해 주는 것 같다.

-

무료 플랜은 직접 인덱스를 수집하는 방법과, docsearch를 이용하는 방법이 있다.
-docsearch에 등록한다면 일주일에 한 번씩 크롤링이 진행된다.
-이 글에서는 직접 인덱스를 수집하는 방법을 사용한다.

+ <![CDATA[[책] 상자 밖에 있는 사람]]> + https://greeng00se.github.io/book-leadership-and-self-deception + + 2023-04-08T00:00:00.000Z + + 책 정보 +
+

상자 밖에 있는 사람
+아빈저연구소

+
+

자기기만과 자기배반

+

책에서는 자기기만과 자기배반에 대한 내용을 다룬다.

    -
  • 직접 인덱스 수집
  • -
  • 설정 파일
  • +
  • 자기기만: 자신의 문제를 인정하지 않는 것
  • +
  • 자기배반: 다른 사람을 위해 무언가 해야만 한다는 생각을 반하는 행위
-

알고리아 애플리케이션 생성 및 키 확인

-

회원가입을 하고 새로운 애플리케이션 생성을 누른다.
-생성을 다 마치면 다음과 같이 api 키를 확인할 수 있다.

-

algolia

-

키 생성

-

직접 인덱스를 수집하기 위한 키를 생성한다.
-addObject, editSettings, deleteIndex acl(접근 제어 목록)이 있으면 된다.

-

key

-

.env 파일 생성

-

프로젝트 폴더 상단에 .env 파일을 생성한다.

-
APPLICATION_ID=MVIU5UEMOM
-API_KEY=인덱스_생성용_키
-
-

config 파일 생성

-

마찬가지로 최상단에 config.json 파일을 생성한다. -설정 파일은 해당 링크를 참고한다.
-또는 Docusaurus의 설정 파일을 참고한다.

-
{
-  "index_name": "teco",
-  "start_urls": [
-    "https://teco-chat.github.io/"
-  ],
-  "sitemap_urls": [
-    "https://teco-chat.github.io/sitemap.xml"
-  ],
-  "sitemap_alternate_links": true,
-  "stop_urls": [
-    "/tests"
-  ],
-  "selectors": {
-    "lvl0": {
-      "selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",
-      "type": "xpath",
-      "global": true,
-      "default_value": "Documentation"
-    },
-    "lvl1": "header h1",
-    "lvl2": "article h2",
-    "lvl3": "article h3",
-    "lvl4": "article h4",
-    "lvl5": "article h5, article td:first-child",
-    "lvl6": "article h6",
-    "text": "article p, article li, article td:last-child"
-  },
-  "strip_chars": " .,;:#",
-  "custom_settings": {
-    "separatorsToIndex": "_",
-    "attributesForFaceting": [
-      "language",
-      "version",
-      "type",
-      "docusaurus_tag"
-    ],
-    "attributesToRetrieve": [
-      "hierarchy",
-      "content",
-      "anchor",
-      "url",
-      "url_without_anchor",
-      "type"
-    ]
-  },
-  "conversation_id": [
-    "833762294"
-  ],
-  "nb_hits": 46250
-}
-
-

docker 이용하여 크롤링

-

docker와 jq가 필요하다.
-jq가 설치되어 있지 않으면 mac 기준 brew를 이용해서 설치할 수 있다.

-
brew install jq
-
-

다음 명령어를 이용하여 .env와 config.json을 이용하여 크롤링을 한다.

-
docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper
-
-

docusaurus 설정

-

전에 확인한 APP ID, Search-Only API KEY, IndexName을 이용하여 docusaurus.config 파일에 설정한다.

-
themeConfig:
-  /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
-  ({
-    ...
-    algolia: {
-      appId: 'MVIU5UEMOM', // Application ID
-      apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key
-      indexName: 'teco', // config.json에 설정한 인덱스명
-      contextualSearch: true,
-    },
-  })
-
-

부가 설정

-

화면 상단 Github Icon

-

파일 최하단에 아래 css 구문을 추가한다.

-
.header-github-link:hover {
-  opacity: 0.6;
-}
-
-.header-github-link:before {
-  content: '';
-  width: 24px;
-  height: 24px;
-  display: flex;
-  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
-    no-repeat;
-}
-
-html[data-theme='dark'] .header-github-link:before {
-  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
-    no-repeat;
-}
-
-

themeconfig -> navbar에 github link를 설정한다.

-
navbar: {
-  title: 'HELLO',
-  items: [
-    {
-        href: 'https://github.com/greeng00se',
-        position: 'right',
-        className: 'header-github-link',
-        'aria-label': 'GitHub repository',
-    },
-  ],
-},
-
-

코드블럭

-

java나 kotlin의 경우 기본적으로 하이라이팅을 지원해 주지 않는다.
-prism 설정을 아래와 같이 변경해 준다.

-
prism: {
-  theme: lightCodeTheme,
-  darkTheme: darkCodeTheme,
-  additionalLanguages: ['java', 'kotlin'],
-}
-
-

mermaid

-

mermaid를 사용하려면 @docusaurus/theme-mermaid 를 설치해야 한다.

-
yarn add @docusaurus/theme-mermaid
-
-

설치 후 아래와 같이 설정을 추가한다.

-
const config = {
-  ...
-  markdown: {
-    mermaid: true,
-  },
-  themes: [
-    '@docusaurus/theme-mermaid'
-  ],
-};
-
-

themeConfig에서 mermaid의 테마를 지정할 수 있다.

-
themeConfig:
-    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
-    ({
-      ...
-      mermaid: {
-        theme: {
-          light: 'neutral', 
-          dark: 'dark'
-        },
-      },
-    }),
-
-

국제화 설정

-

국제화 설정을 한다면 Older Entries 형태의 설명이 다음 페이지 로 변경된다.
-설정파일에서 i18n에 있는 로케일 설정을 ko로 변경하면 된다.

-
i18n: {
-  defaultLocale: "ko",
-  locales: ["ko"],
-},
-
-

블로그 글 author

-

팀원 별로 문서를 관리한다면 다음과 같이 어떤 팀원이 글을 작성했는지 설정해야 한다.

-

author

-

authors.yml 파일을 이용하여 사용자에 대한 기본 설정을 할 수 있다.

-
herb:
-  name: 허브
-  title: Backend
-  url: https://github.com/greeng00se
-  image_url: https://github.com/greeng00se.png
-
-mallang:
-  name: 말랑
-  title: Backend
-  url: https://github.com/shin-mallang
-  image_url: https://github.com/shin-mallang.png
-
-

블로그 글을 작성할 때 다음과 같이 authors에 넣어주기만 하면 된다.

-
---
-slug: 1
-title: Hello World
-authors: [herb, mallang]
-tags: [hello, docusaurus]
----
-
-첫 번째 문서 내용
-
]]>
- -
- - <![CDATA[우아한테크코스 레벨 2 회고]]> - https://greeng00se.github.io/woowacourse-level2-retrospective - - 2023-06-11T00:00:00.000Z - - 23년의 6월이 오고, 레벨 2가 끝났다.
-빠르게 지나가서 조금 아쉽다.

-

학습

-

회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
-항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
-미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

-

고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
-방학 그리고 레벨 3 때는 조금 더 이론적인 부분을 학습하는데 집중해야겠다.

-

점차 학습 범위가 넓어지면서 자연스럽게 모르는 내용이 쌓여간다.
-필요한 내용은 앞으로 천천히 학습하면 되니까 조급해지지 말아야겠다.

-

수면

-

레벨 2를 진행하는 동안 수면이 많이 부족했었고, 결과적으로는 그날의 컨디션을 많이 좌우했던 것 같다.
-앞으로 수면 시간을 늘리고, 좋은 수면 습관을 가지도록 노력해야겠다.

-

협업

-

레벨 2 마지막에 협업 미션이 있었다.
-지금까지는 백엔드 크루들과 페어 프로그래밍을 하면서 협업을 경험했다.
-이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

-

레벨 3 때부터 본격적으로 프로젝트가 시작된다.
-팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

-

레벨 2를 마무리하며

-

회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. -읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

]]>
- - +

자기배반을 한다면 자기기만 상태가 된다.
+자기기만 상태에 빠지는 것을 책에서는 상자 안에 들어간다고 표현한다.

+

읽고 나서

+

최근에 읽은 책 중 가장 마음이 불편했다.
+그렇기에 더더욱 나에게 필요한 내용이 담겨있었다.

+

살면서 많은 선택의 순간이 존재했고, 그 순간마다 자기배반을 택하는 경우가 많았다.
+작게는 집안일을 해야 하는데 몸이 조금 힘들다고 하지 않거나
+크게는 잘못을 인정해야 하는 상황에서 그러지 않은 경우가 있었다.
+이런 상황이 반복되어 결국 상자 안에 나 자신을 가두는 경우가 많았다.

+

더 나은 삶을 위해 내가 상자 안에 있는지 지속적으로 확인하고, 상자 밖으로 나가려는 연습을 해야겠다.
+넓은 시선을 가지고, 항상 내가 틀릴 수 있다는 것을 생각하고 살아가자.

+

밑줄 친 문장들

+
+

우리의 생각은 지식보다 작다.
+우리의 지식은 사랑보다 작다.
+우리의 사랑은 존재보다 작다.
+그리고 우리가 생각하는 나는 실제의 나보다 그만큼 작다.
+R. D. 랭
+p.19

+
+
+

우리가 외적으로 어떤 행동을 하든지 간에, 사람들은 우리 마음에서 그들을 어떻게 대하고 있는지에 따라 주로 반응합니다.
+우리가 사람들에 대해 어떻게 느끼게 되는지는 우리가 상자 안에 있는지 혹은 상자 밖에 있는지에 따라 달라지게 됩니다.
+p.66

+
+
+

비난은 감정에 속하고 낙관은 의지에 속한다.
+인간은 감정보다 더 큰 존재이다.
+알랭, 탁닛한
+p.103

+
+
+

우리가 자신에게만 집중하고 있는 한, 혼자서 일하는 것 이상의 창조적인 결과나 협력을 이끌어 낸다는 것은 불가능합니다.
+오늘날 경제 환경에서는 혼자서는 일의 결과를 탁월하게 만들어 내기가 어렵습니다.
+내가 중심이어야 된다는 폐쇄적인 사고는 함께 일하는 사람들의 열정을 불러오지 못합니다.
+p.175

+
+
+

솔직함은 우리의 문제를 해결하는 열쇠입니다.
+그것은 자신의 행동과 관련된 사람에 대해 기꺼이 사과를 하는 것입니다.
+그것만이 실타래처럼 엉킨 관계의 문제를 해결할 수 있기 때문이죠.
+p.188

+
+
+

누군가를 나와 같이 동일한 가치를 지닌 한 인간으로 생각해서 그 사람을 위해 내가 상자 밖에 계속 머무르고 싶은 열망이 생길 때, 나는 이미 그 사람에 대해 상자 밖에 있다.
+p.214

+
+
+

대부분의 사람들이 관계 기술을 가지고 그들이 겪고 있는 문제를 바로잡으려고 하는 노력이 결실을 얻지 못하는 것은 결코 그러한 기술 부족 때문에 생기는 것이 아닙니다.
+그것들은 자기배반 때문에 생겨납니다.
+p.224

+
+
+

우리는 함께 일하고 우리와 함께 살아가는 사람이 진정으로 누구인지 알지 못합니다.
+우리가 그들과 진정으로 함께 소통하기 전까지는 우리는 그들의 가치를 잘 모릅니다.
+우리의 위대함이란 다른 사람들의 위대한 점을 발견해 주는 것에 있습니다.
+p.280

+
]]> +
\ No newline at end of file diff --git a/blackjack-retrospective.html b/blackjack-retrospective.html index 2aada443b..c8a3183bf 100644 --- a/blackjack-retrospective.html +++ b/blackjack-retrospective.html @@ -13,11 +13,11 @@ - - + + -

블랙잭 미션 회고

· 약 6분

1단계: https://github.com/woowacourse/java-blackjack/pull/427
+

블랙잭 미션 회고

· 약 6분

1단계: https://github.com/woowacourse/java-blackjack/pull/427
2단계: https://github.com/woowacourse/java-blackjack/pull/537

블랙잭

블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
@@ -27,8 +27,8 @@

블랙잭

미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
-중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
-부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

+중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
+부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

이 부분에 대해 생각이 많아져서 전 리뷰어인 터틀🐢과도 대화를 나누었다.
터틀은 제어할 수 없는 부분보다 제어할 수 있는 부분(궁극적인 목표인 좋은 코드를 작성하는 것)에 집중해보라고 하셨다.

좋은 코드, 좋은 페어에 대한 부분을 일단 지속적으로 생각해봐야겠다.

@@ -50,8 +50,8 @@

새로 학습한 부분

처음 적용하기 전에는 별로라고 생각했는데, 생각보다 괜찮은 것 같다.

일관성, 가독성, 추상화
이번 리뷰어는 검프🍫 였다!
-검프의 리뷰는 간결함에 관련된 내용이 많았다.
-일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
+검프의 리뷰는 간결함에 관련된 내용이 많았다.
+일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
읽기 좋고, 간결한 방향으로 코드를 작성하는 방법을 배운 것 같다.
코드를 바라보는 시점이 하나 늘어난 기분이다!(앞으로 적용하는 것은 나의 몫이지만)

페어에게 배울 부분

@@ -66,6 +66,6 @@

페어에게 배울 부분

도메인 언어에 신경쓰는 부분
클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
요구사항 정리도 깔끔하게 잘하는 것 같다.

-

후추 최고 👍

+

후추 최고 👍

\ No newline at end of file diff --git a/blog.html b/blog.html index e797adc77d4b6da9665744b73e9293a98270550a..8850fe1129156637243c4b2d1c146bf5feedb1eb 100644 GIT binary patch delta 281 zcmW-bJxc-s0EQ(B6iO6_mi)duKTka`(`X4ADk2Dsh`^>(OVrfFC5$p_h=||;v!S5~ z99n|Lf__0;{eY&Xq9NRhj)r%5c;Mmv%zx$YK8(ik2`#5&bCV=Z4s50|qs}Qco66lM zP2V;WYJ+L_2oLd<0fPanDzF^S^RARADmx4+8=S{V$gu*w=n*cDl|-~gH*$hGa;$Hd zOSy?4m*|8~k-`=p9fZQ6hCDydkJHoh9IP>FD^#$e2183b6VLQAA~cDLrU>FKE%pP7 zB4}}KXo`l2en1e^k~TC)N81}7?|o~1?e@!JNvK72b-gf2(kfuLj$2Bl!bDOjsCP;0 zkDZys23IZ{A8L*@^@uTbmdkjJx%dj7N|C10WJsxV9;+h7YCJ?s48#%UqXsW>ow8hE zSYF~HVlWlS@fxnO5Z)&r7^N?1w4^P9QkHJ0i9fVMFSto2Smrs

컴포지트 패턴으로 요금 정책 추상화하기

· 약 5분

요구사항

+

컴포지트 패턴으로 요금 정책 추상화하기

· 약 5분

요구사항

지하철 미션에는 다음과 같은 요구사항이 있었다.

  • 거리별 추가 요금 정책
  • @@ -37,7 +37,7 @@

    인터페이스 사용

composite1

모든 요금 정책을 포함하는 새로운 요금 정책 만들기

-

나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
+

나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
이 또한 FarePolicy를 구현한 형태가 되고, 필드로는 나머지 구현체들을 가지고 있다.

public class SubwayFarePolicy implements FarePolicy {
 
@@ -82,7 +82,7 @@ 

컴포지트 패턴이란?

GOF의 디자인 패턴 책에서는 컴포지트 패턴을 다음과 같이 설명하고 있다.

부분과 전체의 계층을 표현하기 위해 객체들을 모아 트리 구조로 구성합니다.
-사용자로 하여금 개별 객체와 복합 객체를 모두 동일하게 다룰 수 있도록 하는 패턴입니다.

+사용자로 하여금 개별 객체와 복합 객체를 모두 동일하게 다룰 수 있도록 하는 패턴입니다.

컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
이 때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

@@ -116,6 +116,6 @@

패턴 사용시 주의해야 항상 트레이드오프를 생각하자!

참고 자료

컴포지트 패턴, GoF의 디자인 패턴
-디자인 패턴과 프레임워크, 오브젝트

+디자인 패턴과 프레임워크, 오브젝트

\ No newline at end of file diff --git a/custom-jdbc-template.html b/custom-jdbc-template.html index 543fca9a4..bff8a217e 100644 --- a/custom-jdbc-template.html +++ b/custom-jdbc-template.html @@ -13,11 +13,11 @@ - - + + -

커스텀 JdbcTemplate 만들기

· 약 10분

체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
+

커스텀 JdbcTemplate 만들기

· 약 10분

체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

기존 코드

@@ -362,6 +362,6 @@

태그:

+
\ No newline at end of file diff --git a/db-replication.html b/db-replication.html index a3782a614..c3cb5c659 100644 --- a/db-replication.html +++ b/db-replication.html @@ -13,11 +13,11 @@ - - + + -

DB 복제, @Transactional에 따라 요청 분리해보기

· 약 21분

복제(Replication)

+

DB 복제, @Transactional에 따라 요청 분리해보기

· 약 21분

복제(Replication)

한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
원본 데이터를 가지는 서버를 Primary 또는 Source 라고 부르고, 복제된 데이터를 가지는 서버를 Secondary 또는 Replica 라고 부른다.

복제를 하는 이유

@@ -112,7 +112,7 @@

복제 토폴로지

ACTIVE-ACTIVE: 2개의 서버 모두 쓰기 작업을 수행하는 형태
ACTIVE-PASSIVE: 하나의 서버에서만 쓰기 작업을 수행하는 형태

멀티 소스 복제 구성

-

여러개의 source 서버와 하나의 replica 서버를 사용하는 구성이다.
+

여러개의 source 서버와 하나의 replica 서버를 사용하는 구성이다.
이는 source 서버의 데이터를 한 곳에 백업하는 용도로 사용, 여러 서버에 존재하는 데이터를 통합, 샤딩되어있는 테이블 데이터를 통합할 때 사용한다.

참고 자료 LazyConnectionDataSourceProxy
데이터베이스 레플리케이션을 통한 쿼리 성능 개선 (feat. Mysql, SpringBoot)
부하 분산을 위한 MySQL Replication 구성 및 쿼리 요청 분기
-Use Docker Compose, Docker

+Use Docker Compose, Docker

\ No newline at end of file diff --git a/docs.html b/docs.html index eaa03e72c..09ec181ef 100644 --- a/docs.html +++ b/docs.html @@ -13,10 +13,10 @@ - - + + - + \ No newline at end of file diff --git a/docs/architecture/virtical-slice-architecture.html b/docs/architecture/virtical-slice-architecture.html index c162045dc..5f79264d0 100644 --- a/docs/architecture/virtical-slice-architecture.html +++ b/docs/architecture/virtical-slice-architecture.html @@ -13,8 +13,8 @@ - - + +

버티컬 슬라이스 아키텍처

개요

diff --git a/docs/book/getting-out-of-the-box.html b/docs/book/getting-out-of-the-box.html index d4764d2b8..bee9e3b3d 100644 --- a/docs/book/getting-out-of-the-box.html +++ b/docs/book/getting-out-of-the-box.html @@ -13,8 +13,8 @@ - - + +

상자 밖으로 탈출하기

⚠️ 자기배반의 원리

diff --git a/docs/culture/postmortem.html b/docs/culture/postmortem.html index 851623c40..021dde2cc 100644 --- a/docs/culture/postmortem.html +++ b/docs/culture/postmortem.html @@ -13,8 +13,8 @@ - - + +

포스트 모템

포스트 모템(Postmortem)

diff --git a/docs/database/maximumPoolSize.html b/docs/database/maximumPoolSize.html index 92486ef2b..526dcdbc7 100644 --- a/docs/database/maximumPoolSize.html +++ b/docs/database/maximumPoolSize.html @@ -13,8 +13,8 @@ - - + +

maximumPoolSize

maximumPoolSize

diff --git a/docs/database/query-execution.html b/docs/database/query-execution.html index 5f7781ac5..14d1a0585 100644 --- a/docs/database/query-execution.html +++ b/docs/database/query-execution.html @@ -13,8 +13,8 @@ - - + +

쿼리 실행 구조

실행 구조

diff --git a/docs/deploy/zero-downtime.html b/docs/deploy/zero-downtime.html index ba032afea..2a81922de 100644 --- a/docs/deploy/zero-downtime.html +++ b/docs/deploy/zero-downtime.html @@ -13,8 +13,8 @@ - - + +

무중단 배포

무중단 배포

diff --git a/docs/design/package.html b/docs/design/package.html index 25a710d87..e3c3db855 100644 --- a/docs/design/package.html +++ b/docs/design/package.html @@ -13,8 +13,8 @@ - - + +

패키지

계층 기반 패키지

diff --git a/docs/etc/communication.html b/docs/etc/communication.html index dd2fb9a5d..497e2438b 100644 --- a/docs/etc/communication.html +++ b/docs/etc/communication.html @@ -13,8 +13,8 @@ - - + +

커뮤니케이션 잘하는 개발자의 4가지 습관

커뮤니케이션 잘 하는 개발자?

diff --git a/docs/etc/develop-with-spring.html b/docs/etc/develop-with-spring.html index 5106d4f6b..54b001840 100644 --- a/docs/etc/develop-with-spring.html +++ b/docs/etc/develop-with-spring.html @@ -13,8 +13,8 @@ - - + +

스프링과 함께 더 나은 개발자 되기

어떤 기술을 통해서도 성장할 수 있다.

diff --git a/docs/etc/experience-and-self-question.html b/docs/etc/experience-and-self-question.html index 9525a9631..9294d2372 100644 --- a/docs/etc/experience-and-self-question.html +++ b/docs/etc/experience-and-self-question.html @@ -13,8 +13,8 @@ - - + +

경험과 질문

우아한테크코스 2023년 10월 6일
diff --git a/docs/etc/healthful-growth.html b/docs/etc/healthful-growth.html index b9780b13e..4d91b0783 100644 --- a/docs/etc/healthful-growth.html +++ b/docs/etc/healthful-growth.html @@ -13,8 +13,8 @@ - - + +

건강하게 나아지기

우아한테크코스 2023년 4월 19일
diff --git a/docs/java/sequenced-collection.html b/docs/java/sequenced-collection.html index ea2f1eb42..c76d21ba3 100644 --- a/docs/java/sequenced-collection.html +++ b/docs/java/sequenced-collection.html @@ -13,8 +13,8 @@ - - + +

SequencedCollection

JEP 431: Sequenced Collections

diff --git a/docs/jpa/key.html b/docs/jpa/key.html index 75ff1a0bd..4426e559e 100644 --- a/docs/jpa/key.html +++ b/docs/jpa/key.html @@ -13,8 +13,8 @@ - - + +

기본 키 매핑

기본 키 매핑

diff --git a/docs/linux/shell.html b/docs/linux/shell.html index b9ebd1369..130e2d63d 100644 --- a/docs/linux/shell.html +++ b/docs/linux/shell.html @@ -13,8 +13,8 @@ - - + +

터미널 쉘 프롬프트 설정

계정 별 터미널 설정

diff --git a/docs/linux/swap.html b/docs/linux/swap.html index 723e7def3..6f0481850 100644 --- a/docs/linux/swap.html +++ b/docs/linux/swap.html @@ -13,8 +13,8 @@ - - + +

Swap 메모리 설정

Swap 메모리

diff --git a/docs/mac/java.html b/docs/mac/java.html index 7c502ec9d..e14546863 100644 --- a/docs/mac/java.html +++ b/docs/mac/java.html @@ -13,8 +13,8 @@ - - + +

맥 OS 자바 버전 변경

설치된 자바 버전 확인

diff --git a/docs/monitoring/intro.html b/docs/monitoring/intro.html index 440e08cde..b5ba5ff3e 100644 --- a/docs/monitoring/intro.html +++ b/docs/monitoring/intro.html @@ -13,8 +13,8 @@ - - + +

모니터링 환경 구성

모니터링 3단계

diff --git a/docs/network/load-balancing-algorithm.html b/docs/network/load-balancing-algorithm.html index 547a1e3f9..bbaa27a9e 100644 --- a/docs/network/load-balancing-algorithm.html +++ b/docs/network/load-balancing-algorithm.html @@ -13,8 +13,8 @@ - - + +

로드 밸런싱 알고리즘

라운드로빈 방식(Round Robin Method)

diff --git a/docs/network/load-balancing.html b/docs/network/load-balancing.html index 5ed43b2f8..5d72a6ca6 100644 --- a/docs/network/load-balancing.html +++ b/docs/network/load-balancing.html @@ -13,8 +13,8 @@ - - + +

로드 밸런싱

로드 밸런싱이란?

diff --git a/docs/nginx/command.html b/docs/nginx/command.html index c19cdcdc7..c00d9a90f 100644 --- a/docs/nginx/command.html +++ b/docs/nginx/command.html @@ -13,8 +13,8 @@ - - + +

구조 및 명령어

폴더 및 파일

diff --git a/docs/nginx/static-file.html b/docs/nginx/static-file.html index e83dbbad2..2a5c1ac01 100644 --- a/docs/nginx/static-file.html +++ b/docs/nginx/static-file.html @@ -13,8 +13,8 @@ - - + +

정적 컨텐츠 제공

root

diff --git a/docs/performance/throughput-latency.html b/docs/performance/throughput-latency.html index 20fd6cf63..3714e9ed6 100644 --- a/docs/performance/throughput-latency.html +++ b/docs/performance/throughput-latency.html @@ -13,8 +13,8 @@ - - + +

시스템 성능 지표

시스템 성능 지표

diff --git a/docs/performance/throughput.html b/docs/performance/throughput.html index 89a5bf26d..290c69d2a 100644 --- a/docs/performance/throughput.html +++ b/docs/performance/throughput.html @@ -13,8 +13,8 @@ - - + +

Throughput 목푯값

Throughput

diff --git a/docs/performance/types.html b/docs/performance/types.html index 762b41e1d..684460fb6 100644 --- a/docs/performance/types.html +++ b/docs/performance/types.html @@ -13,8 +13,8 @@ - - + +

성능 테스트 유형

테스트설명
지연 테스트(latency test)요청에 대한 응답 시간을 측정
처리율 테스트(throughput test)시스템 성능이 급락하기 직전, 최대 처리율 수치를 측정
부하 테스트(load test)비즈니스 이벤트를 대비해 트래픽을 견딜 수 있는지 확인
스트레스 테스트(stress test)시스템의 한계점을 확인
내구 테스트(endurance test)장시간 실행할 경우 성능 이상이 발생하는지 확인
용량 계획 테스트(capacity planning test)리소스를 추가한 만큼 시스템이 확장되는지 확인
저하 테스트(degradation test)시스템이 부분적으로 실패할 경우 어떤 일이 발생하는지 확인(장애 복구 및 회복 등)
diff --git a/docs/spring/essence.html b/docs/spring/essence.html index 8cc317b21..51d8558f5 100644 --- a/docs/spring/essence.html +++ b/docs/spring/essence.html @@ -13,8 +13,8 @@ - - + +

스프링의 특징

스프링의 핵심 개발자들이 쓴 Professional Spring Framework 라는 책에서는 스프링의 정수(essence)는 "엔터프라이즈 서비스 기능을 POJO에 제공하는 것" 이라고 했다.

diff --git a/docs/tags.html b/docs/tags.html index f179004fe..11e0fe1a2 100644 --- a/docs/tags.html +++ b/docs/tags.html @@ -13,8 +13,8 @@ - - + + diff --git a/docs/tags/architecture.html b/docs/tags/architecture.html index ca55572a0..d29da86f5 100644 --- a/docs/tags/architecture.html +++ b/docs/tags/architecture.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "architecture" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/book.html b/docs/tags/book.html index c017c3ce9..192534f9e 100644 --- a/docs/tags/book.html +++ b/docs/tags/book.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "book" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/collection.html b/docs/tags/collection.html index b89d6e710..888932d29 100644 --- a/docs/tags/collection.html +++ b/docs/tags/collection.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "collection" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/deploy.html b/docs/tags/deploy.html index b78040149..93ece9200 100644 --- a/docs/tags/deploy.html +++ b/docs/tags/deploy.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "deploy" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/etc.html b/docs/tags/etc.html index 1a4ad92ae..1224467ca 100644 --- a/docs/tags/etc.html +++ b/docs/tags/etc.html @@ -13,8 +13,8 @@ - - + +

4개 문서가 "etc" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/java.html b/docs/tags/java.html index 16e665530..1e6f51b95 100644 --- a/docs/tags/java.html +++ b/docs/tags/java.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "java" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/jpa.html b/docs/tags/jpa.html index c9537987b..245161af4 100644 --- a/docs/tags/jpa.html +++ b/docs/tags/jpa.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "JPA" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/latency.html b/docs/tags/latency.html index 1563d2863..9f9208197 100644 --- a/docs/tags/latency.html +++ b/docs/tags/latency.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "latency" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/load-balancing.html b/docs/tags/load-balancing.html index 071d8222c..ea6251fdd 100644 --- a/docs/tags/load-balancing.html +++ b/docs/tags/load-balancing.html @@ -13,8 +13,8 @@ - - + +

2개 문서가 "load balancing" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/monitoring.html b/docs/tags/monitoring.html index 0277fb3e3..44a535d28 100644 --- a/docs/tags/monitoring.html +++ b/docs/tags/monitoring.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "monitoring" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/network.html b/docs/tags/network.html index 8bfa8b5e3..31be25b52 100644 --- a/docs/tags/network.html +++ b/docs/tags/network.html @@ -13,8 +13,8 @@ - - + +

2개 문서가 "network" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/nginx.html b/docs/tags/nginx.html index de5985985..e0204f079 100644 --- a/docs/tags/nginx.html +++ b/docs/tags/nginx.html @@ -13,8 +13,8 @@ - - + +

2개 문서가 "nginx" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/package.html b/docs/tags/package.html index d2157932d..dafe2beff 100644 --- a/docs/tags/package.html +++ b/docs/tags/package.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "package" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/performance.html b/docs/tags/performance.html index f31cb428d..4058b225f 100644 --- a/docs/tags/performance.html +++ b/docs/tags/performance.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "performance" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/postmortem.html b/docs/tags/postmortem.html index c46d256b5..7fe6e9868 100644 --- a/docs/tags/postmortem.html +++ b/docs/tags/postmortem.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "postmortem" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/sequenced.html b/docs/tags/sequenced.html index ec9736c88..cab9da09b 100644 --- a/docs/tags/sequenced.html +++ b/docs/tags/sequenced.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "sequenced" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/spring.html b/docs/tags/spring.html index b9b3845e1..895367dfc 100644 --- a/docs/tags/spring.html +++ b/docs/tags/spring.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "spring" 태그에 분류되었습니다

모든 태그 보기

스프링의 특징

스프링의 핵심 개발자들이 쓴 Professional Spring Framework 라는 책에서는 스프링의 정수(essence)는 "엔터프라이즈 서비스 기능을 POJO에 제공하는 것" 이라고 했다.

diff --git a/docs/tags/test.html b/docs/tags/test.html index bfbbd48d1..125b4e9dc 100644 --- a/docs/tags/test.html +++ b/docs/tags/test.html @@ -13,8 +13,8 @@ - - + +

5개 문서가 "test" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/throughput.html b/docs/tags/throughput.html index 5488653cb..65be5d77d 100644 --- a/docs/tags/throughput.html +++ b/docs/tags/throughput.html @@ -13,8 +13,8 @@ - - + +

2개 문서가 "throughput" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/tags/zero-downtime.html b/docs/tags/zero-downtime.html index a5b11cf5e..65124f27c 100644 --- a/docs/tags/zero-downtime.html +++ b/docs/tags/zero-downtime.html @@ -13,8 +13,8 @@ - - + +

1개 문서가 "zero-downtime" 태그에 분류되었습니다

모든 태그 보기
diff --git a/docs/test/benefit.html b/docs/test/benefit.html index c667ec0d3..814be76f4 100644 --- a/docs/test/benefit.html +++ b/docs/test/benefit.html @@ -13,8 +13,8 @@ - - + +

테스트 코드가 주는 혜택

디버깅 감소

diff --git a/docs/test/first.html b/docs/test/first.html index 3a5a15500..86be1dea7 100644 --- a/docs/test/first.html +++ b/docs/test/first.html @@ -13,8 +13,8 @@ - - + +

FIRST

FIRST란?

diff --git a/docs/test/heuristics.html b/docs/test/heuristics.html index 0aa2fd5ca..8bcd07926 100644 --- a/docs/test/heuristics.html +++ b/docs/test/heuristics.html @@ -13,8 +13,8 @@ - - + +

TDD heuristics

TDD heuristics

diff --git a/docs/test/stairstep.html b/docs/test/stairstep.html index 591bfc046..4747728f2 100644 --- a/docs/test/stairstep.html +++ b/docs/test/stairstep.html @@ -13,8 +13,8 @@ - - + +

계단 테스트

계단 테스트(Stairstep Test)

diff --git a/docusaurus.html b/docusaurus.html index c16e52451..9928cf3c1 100644 --- a/docusaurus.html +++ b/docusaurus.html @@ -13,11 +13,11 @@ - - + + -

Docusaurus

· 약 11분

팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

+

Docusaurus

· 약 11분

팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

설치

공식 홈페이지에 들어가서 최신 버전을 설치한다.

yarn create docusaurus
@@ -29,7 +29,7 @@ 

배포

레포지토리 생성

github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

-

설정 파일 수정

+

설정 파일 수정

module.exports = {
   // ...
   url: 'https://greeng00se.github.io',
@@ -365,6 +365,6 @@ 

블로그 글 author

--- 첫 번째 문서 내용 -
+
\ No newline at end of file diff --git a/grasp.html b/grasp.html index 2c8305a1a..3c05d557e 100644 --- a/grasp.html +++ b/grasp.html @@ -13,11 +13,11 @@ - - + + -

일반적인 책임 할당을 위한 패턴

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

+

일반적인 책임 할당을 위한 패턴

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

@@ -70,7 +70,7 @@

높은 응집도 패턴(High Cohes
  • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
  • 유지보수가 쉬워진다.
  • 낮은 결합도 또한 지원한다.
  • -
  • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.
  • +
  • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.
  • 컨트롤러 패턴(Controller)

    Q. 사용자의 요청을 처리하는 것은 누가 담당해야 하는가?

    @@ -92,7 +92,7 @@

    변경 보호 패턴(Protected

    간접 참조 패턴(Indirection)

    Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

    A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

    -

    중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

    +

    중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

    중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

    순수한 가공물 패턴(Pure Fabrication)

    Q. 책임을 할당한 도메인 객체가 Low Coupling, High Cohesion, 재사용성 등의 목적을 위반한다면 어떻게 해야 할까?

    @@ -107,6 +107,6 @@

    순수한 가공물 패턴(P

    참고 자료

    오브젝트 5장. 책임 할당하기, 조영호

    Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman

    -

    GRASP, 한빛 네트워크

    +

    GRASP, 한빛 네트워크

    \ No newline at end of file diff --git a/index.html b/index.html index eb66c4a65..0135cccf8 100644 --- a/index.html +++ b/index.html @@ -13,8 +13,8 @@ - - + +
    diff --git a/innodb-lock.html b/innodb-lock.html index 17a062791..2ac6bc2dc 100644 --- a/innodb-lock.html +++ b/innodb-lock.html @@ -13,11 +13,11 @@ - - + + -

    InnoDB 스토리지 엔진의 잠금

    · 약 6분

    InnoDB 스토리지 엔진의 잠금

    +

    InnoDB 스토리지 엔진의 잠금

    · 약 6분

    InnoDB 스토리지 엔진의 잠금

    MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
    보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

    동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
    @@ -75,6 +75,6 @@

    참고 자료

    Optimistic and Pessimistic record locking, IBM
    MySQL Innodb Locks, cecil1018
    MySQL 8.0 InnoDB Locks, MySQL
    -Locks Set by Different SQL Statements in InnoDB, MySQL

    +Locks Set by Different SQL Statements in InnoDB, MySQL

    \ No newline at end of file diff --git a/intellij-settings.html b/intellij-settings.html index 4f64f8f5c..be852b1ac 100644 --- a/intellij-settings.html +++ b/intellij-settings.html @@ -13,11 +13,11 @@ - - + + -

    IntelliJ 설정

    · 약 1분

    Import 자동 적용

    +

    IntelliJ 설정

    · 약 1분

    Import 자동 적용

    Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

    auto-import

    저장시 동작

    @@ -28,6 +28,6 @@

    저장시 동작

    Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

    메소드 추출, 변수 추출시 final 적용

    Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

    -

    final-modifier

    +

    final-modifier

    \ No newline at end of file diff --git a/java-class-file.html b/java-class-file.html index 036cf01d4..23397c88d 100644 --- a/java-class-file.html +++ b/java-class-file.html @@ -13,11 +13,11 @@ - - + + -

    자바 클래스 파일 구조

    · 약 6분

    클래스 파일

    +

    자바 클래스 파일 구조

    · 약 6분

    클래스 파일

    자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
    컴파일된 클래스파일은 어떤 구조로 되어있을까?

    클래스 파일의 데이터 형식

    @@ -61,7 +61,7 @@

    클래스 파일 포맷 버전

    상수 풀

    2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
    클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
    -JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

    +JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

    액세스 플래그

    클래스, 인터페이스와 같은 파일의 속성을 표시한다.
    예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.

    @@ -75,7 +75,7 @@

    this_class

    클래스명과 같은 이름을 표현하는 값으로, 상수 풀에서 클래스명과 일치하는 항목의 인덱스를 참조한다.
    해당 인덱스의 항목은 CONSTANT_Class_infoclass 형식의 값이어야 한다.

    super_class

    -

    상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
    +

    상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
    아무것도 상속하지 않는 클래스의 경우 java.lang.Object의 인덱스 값이 들어있다.

    interface, field, method

    각각의 개수와, 정보에 대한 값이 들어있다.
    @@ -90,6 +90,6 @@

    참고 자료

    2장 JVM 이야기, 자바 최적화
    Class file in Java, File Format
    java se11 Class 파일 형식, Oracle
    -java se17 Class 파일 형식, Oracle

    +java se17 Class 파일 형식, Oracle

    \ No newline at end of file diff --git a/java-spring-springboot.html b/java-spring-springboot.html index 934809e62..53acab9bf 100644 --- a/java-spring-springboot.html +++ b/java-spring-springboot.html @@ -13,11 +13,11 @@ - - + + -

    자바 17, 스프링 6.0, 스프링 부트 3.1

    · 약 5분

    자바 17, 스프링 6.0, 스프링 부트 3.1

    +

    자바 17, 스프링 6.0, 스프링 부트 3.1

    · 약 5분

    자바 17, 스프링 6.0, 스프링 부트 3.1

    팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
    2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

    자바 변경 사항

    @@ -39,7 +39,7 @@

    Switch Expressions(Java 14)

    주요 특징은 다음과 같다.

      -
    • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
    • +
    • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
    • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
    • break 문이 필요 없다.
    • default 블록을 통해 기본 값을 지정할 수 있다.
    • @@ -81,7 +81,7 @@

      Record(Java 16)

      추가적인 변경사항

      이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

      스프링, 스프링 부트 변경 사항

      -

      스프링과 스프링 부트에도 많은 변경 사항이 있었다.
      +

      스프링과 스프링 부트에도 많은 변경 사항이 있었다.
      따라서 필요해보이는 몇개 정도만 정리했다.

      스프링 요구사항

      Java 17, Jakarta EE 9 이상이어야 한다.

      @@ -106,6 +106,6 @@

      참고 자료

      Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩
      What's New in Spring Framework 6.x
      Spring Boot 3.0 Release Notes
      -Spring Boot 3.1 Release Notes

    +Spring Boot 3.1 Release Notes

    \ No newline at end of file diff --git a/jdbc-retrospective.html b/jdbc-retrospective.html index c72e0fcf0..90d505a89 100644 --- a/jdbc-retrospective.html +++ b/jdbc-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    Jdbc 라이브러리 구현 미션 회고

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
    +

    Jdbc 라이브러리 구현 미션 회고

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
    2단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358
    3단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448
    4단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515

    @@ -100,6 +100,6 @@

    트랜잭션 적용

    마무리

    Jdbc 미션을 진행하면서 AOP나 Transactional에 대한 학습 테스트도 진행하고, 약간 알찬 미션이었던 것 같다.
    꼼꼼히 코드를 봐준 리뷰어 호이 그리고 연휴 동안 계속 티키타카 하면서 재밌게 리뷰한 민트에게 감사하다.
    -회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

    +회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

    \ No newline at end of file diff --git a/jenkins.html b/jenkins.html index 6be283ba9..86ffeef0a 100644 --- a/jenkins.html +++ b/jenkins.html @@ -13,11 +13,11 @@ - - + + -

    Jenkins로 CI/CD 설정

    · 약 8분

    설정 환경

    + +Amazon Linux 2023 packages, AWS

    \ No newline at end of file diff --git a/jsr-310.html b/jsr-310.html index 70030156f..2c48fcc55 100644 --- a/jsr-310.html +++ b/jsr-310.html @@ -13,11 +13,11 @@ - - + + -

    JSR-310

    · 약 2분

    이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    +

    JSR-310

    · 약 2분

    이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    ISO-8601을 기반으로 작성
    설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

    날짜와 시간에 관련된 데이터를 다루는 국제 표준

    @@ -53,6 +53,6 @@

    참고 자료

  • JSR-310 Spec
  • Temporal Adjuster
  • DateTimeFormatter
  • -
    +
    \ No newline at end of file diff --git a/kotlin-null.html b/kotlin-null.html index ac9809c20..f2873548e 100644 --- a/kotlin-null.html +++ b/kotlin-null.html @@ -13,11 +13,11 @@ - - + + -

    Kotlin에서 null을 다루는 방법

    · 약 5분

    nullable 타입

    +

    Kotlin에서 null을 다루는 방법

    · 약 5분

    nullable 타입

    코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
    이는 실행 시점이 아닌 컴파일 시 미리 오류가 발생할 가능성이 있는 부분을 미리 감지하여 NPE 발생의 가능성을 줄여준다.

    코틀린의 경우 nullable 타입을 다음과 같이 표현한다.

    @@ -29,7 +29,7 @@

    ?. Safe Calls 연산자

    자바에서 NPE를 발생시키지 않기 위해 null을 처리하는 가장 간단한 방법으로는 분기를 사용하는 방법이 있다.

    코틀린은 안전한 호출 연산자인 ?. 연산자를 지원한다.
    따라서 참조 값이 null이 아닐 경우에만 메서드 호출을 할 수 있다.
    -참조 값이 null인 경우 메서드 호출이 무시되고, null을 반환한다.

    +참조 값이 null인 경우 메서드 호출이 무시되고, null을 반환한다.

    public String repeat(String word) {
         if (word == null) {
             return null;
    @@ -82,6 +82,6 @@ 

    참고 자료

  • Effective Kotlin Item 8
  • Comprehensive Guide to Null Safety in Kotlin
  • Kotlin NullSafety
  • -
    +
    \ No newline at end of file diff --git a/ladder-retrospective.html b/ladder-retrospective.html index adfc97a3a..c5f476095 100644 --- a/ladder-retrospective.html +++ b/ladder-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    사다리 타기 미션 회고

    · 약 11분

    1단계: https://github.com/woowacourse/java-ladder/pull/97
    +

    사다리 타기 미션 회고

    · 약 11분

    1단계: https://github.com/woowacourse/java-ladder/pull/97
    2단계: https://github.com/woowacourse/java-ladder/pull/234

    사다리 타기

    사다리 타기 미션에서는 우가와 페어가 매칭되었다.
    @@ -28,7 +28,7 @@

    사다리 타기

  • LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
  • Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법
  • -

    Position 기준으로 사다리 게임을 진행하는 방법

    +

    Position 기준으로 사다리 게임을 진행하는 방법

    사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
    구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
    또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

    @@ -120,7 +120,7 @@

    부족했던 부분

    다음 미션에는 조금 더 신경 써야겠다.

    좋은 질문을 생각하기
    첫 PR때 리뷰어에게 질문을 남기지 못했다.
    -리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

    +리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

    PR 후에도 꼼꼼하게 확인하기
    분명 알고 있는 부분이지만, 놓친 부분이 많은 것 같았다.
    PR 하기 전에도 계속 확인을 했지만, 아무래도 IntelliJ에서 보니 코드에 익숙해져서 그런지 변경해야 할 부분이 잘 안보였다.
    @@ -139,7 +139,7 @@

    새로 학습한 부분

  • B가 A를 긴밀하게 사용한다.
  • B가 A의 초깃값을 가지고 있다.
  • -

    실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

    +

    실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

    패키지 분리 기준
    패키지 분리에 대한 나만의 기준이 아직 명확하지 않아 질문이 들어와도 명확하게 답변을 하지 못했다.
    마지막 제출 전에 도메인 패키지 내부를 분리해 봤는데, 기준이 명확하지 않았기 때문에 좋지 않은 선택이었던 것 같다. @@ -153,9 +153,9 @@

    페어에게 배울 부분

    이번에 페어 할 때 컨디션 관리를 제대로 못해서 많이 미안했다. 다음에는 최상의 컨디션으로 페어를 준비해 봐야겠다.
    그리고 우가랑 페어를 하고 나서, 나도 다른 사람들과 더 잘 지내봐야겠다는 생각이 들어 조금 더 용기를 내 잡담 중이다!

    의견을 적극적으로 내줘서 페어프로그래밍 진행이 잘 되었다.
    -또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
    +또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
    페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

    항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
    -웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

    +웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

    \ No newline at end of file diff --git a/level2-interview-retrospective.html b/level2-interview-retrospective.html index 1b85d28b0..bc27c9035 100644 --- a/level2-interview-retrospective.html +++ b/level2-interview-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    레벨 2 - 레벨 인터뷰 회고

    · 약 4분

    레벨 인터뷰

    +

    레벨 2 - 레벨 인터뷰 회고

    · 약 4분

    레벨 인터뷰

    레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
    따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
    이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
    @@ -42,6 +42,6 @@

    그 외 개선할 점

    인터뷰할 때 특유의 말버릇을 개선하기
    생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
    기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
    -이전에 공부했던거 되돌아 보는 시간 가지기

    +이전에 공부했던거 되돌아 보는 시간 가지기

    \ No newline at end of file diff --git a/log-async-exception.html b/log-async-exception.html index 46c897b8a..3d98096bc 100644 --- a/log-async-exception.html +++ b/log-async-exception.html @@ -13,18 +13,18 @@ - - + + -

    비동기 예외 로깅

    · 약 4분

    문제 상황

    +

    비동기 예외 로깅

    · 약 4분

    문제 상황

    현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
    확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

    비동기 예외 발생시 로깅 설정

    스프링 4.1 부터 제공되는 AsyncUncaughtExceptionHandler의 경우 반환 타입이 void인 비동기 메서드를 예외 처리하기 쉽도록 도와준다.

    따라서 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 핸들링하는 클래스를 생성했다.
    기존의 동기 예외 처리의 경우 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다.
    -비동기 예외 처리도 마찬가지로 MDC의 정보를 가져와서 로그를 출력하도록 설정했다.

    +비동기 예외 처리도 마찬가지로 MDC의 정보를 가져와서 로그를 출력하도록 설정했다.

    @Slf4j
     public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
     
    @@ -52,7 +52,7 @@ 

    비동기 예외 발생시 로

    MDC 정보 연동 문제

    비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없는 문제가 발생했다.

    ./mdc-null.png

    -

    스프링 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

    +

    스프링 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

    public class MdcTaskDecorator implements TaskDecorator {
     
         @Override
    @@ -100,6 +100,6 @@ 

    참고 자료

    @Async will not call by @ControllerAdvice for global exception
    Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
    TaskDecorator, Spring docs
    -AsyncUncaughtExceptionHandler

    +AsyncUncaughtExceptionHandler

    \ No newline at end of file diff --git a/mock-static-method.html b/mock-static-method.html index fd579c55f..6b641bc34 100644 --- a/mock-static-method.html +++ b/mock-static-method.html @@ -13,11 +13,11 @@ - - + + -

    Mockito 이용해서 static 메서드 모킹하기

    · 약 3분

    개요

    +

    Mockito 이용해서 static 메서드 모킹하기

    · 약 3분

    개요

    정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
    하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

    예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

    @@ -34,7 +34,7 @@ }

    Mocking static methods

    -

    Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
    +

    Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
    mockStatic을 사용하면 MockedStatic<T>이 반환되는데 사용 후 꼭 close를 해줘야 한다.

    JUnit의 @BeforeAll로 설정하고 @AfterAll 메서드로 종료하는 방법도 있지만 MockedStatic<T>의 상위 인터페이스인 ScopedMock이 AutoCloseable을 구현하고 있기에 try-with-resources를 사용하는 방법이 더욱 좋은 것 같다.

    // given
    @@ -57,6 +57,6 @@ 

    마치며

    참고 자료

    Mocking static methods
    Mockito mock static methods
    -Enable mocking static methods in Mockito

    +Enable mocking static methods in Mockito

    \ No newline at end of file diff --git a/mvc-retrospective.html b/mvc-retrospective.html index a165ddc6d..b5dbb1e8b 100644 --- a/mvc-retrospective.html +++ b/mvc-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    MVC 구현 미션 회고

    · 약 6분

    1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
    +

    MVC 구현 미션 회고

    · 약 6분

    1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
    2단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465
    3단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580

    MVC 구현

    @@ -28,7 +28,7 @@

    MVC 구현

  • 점진적인 리팩토링을 경험한다.
  • 미션의 목표와 더불어 각 클래스들이 역할과 책임을 적절히 가지도록 하고, 패키지의 의존 방향을 고민하면서 미션을 진행하는 것에 중점을 두었다.

    -

    애너테이션 기반 프레임워크 만들기

    +

    애너테이션 기반 프레임워크 만들기

    기존 코드에 ManualHandlerMapping이라는 서블릿을 직접 등록해서 사용하는 HandlerMapping 클래스가 있었고, 1단계에서는 애너테이션 기반의 AnnotationHandlerMapping을 구현해야 했기 때문에 @Controller, @RequestMapping을 Reflection을 이용하여 스캔하고, 핸들러 매핑을 등록하는 부분까지 진행해야 했다.
    테오가 @GetMapping이나 @PostMapping 부분도 진행하면 재밌을 것 같다고 해서 같이 진행해 보았다.
    추가로 미션 요구사항은 아니었지만 클래스 레벨에 적용된 @RequestMapping도 동작하도록 구현해보았다.

    @@ -102,6 +102,6 @@

    정리

    지금까지 스프링의 DispatcherServlet의 동작을 이론적으로만 알고 있었는데, 실제로 구현해 보니 조금 더 이해가 잘 가는 것 같다.
    이번 미션에서 나의 리뷰어는 루카, 리뷰이는 헤나였다.
    매 단계마다 꼼꼼하게 리뷰해 준 루카에게 너무 감사하고, 헤나에게 이상한 리뷰를 많이 남긴 것 같은데 꼼꼼히 반영해줘서 감사하다.
    -오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

    +오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

    \ No newline at end of file diff --git a/mysql-lock.html b/mysql-lock.html index 56a855a27..e7172603a 100644 --- a/mysql-lock.html +++ b/mysql-lock.html @@ -13,11 +13,11 @@ - - + + -

    MySQL 엔진의 잠금

    · 약 5분

    MySQL 엔진의 잠금

    +

    MySQL 엔진의 잠금

    · 약 5분

    MySQL 엔진의 잠금

    MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
    MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

    글로벌 락(Global lock)

    @@ -71,8 +71,8 @@

    네임드 락(Named lock)

    메타데이터 락(Metadata lock)

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    -명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    -보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    +명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    +보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    -- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
     -- 아래 구문 실행 시 메타데이터 락을 자동으로 획득한다.
     RENAME TABLE rank TO rank_backup, rank_new TO rank;
    @@ -81,6 +81,6 @@ 

    참고 자료

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    MySQL의 User Level Lock를 활용한다면?, gywndi
    Locking Functions, MySQL 5.7 Reference
    -Locking Functions, MySQL 8.0 Reference

    +Locking Functions, MySQL 8.0 Reference

    \ No newline at end of file diff --git a/order-retrospective.html b/order-retrospective.html index 47041d89e..ca81f722e 100644 --- a/order-retrospective.html +++ b/order-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    장바구니 주문 미션 회고

    · 약 5분

    1단계: AWS 배포
    +

    장바구니 주문 미션 회고

    · 약 5분

    1단계: AWS 배포
    2단계: https://github.com/woowacourse/jwp-shopping-order/pull/7

    장바구니 주문 미션

    배포 및 협업을 할 수 있는 미션이었다.
    @@ -72,7 +72,7 @@

    새로 배운 부분

    읽기 전용 트랜잭션

    단순 조회 요청에 대한 성능을 향상시켜준다는 것이라고 간단히만 알고 있었다.
    이번에 코멘트가 달려서 조금 더 자세히 공부해 보기로 했다.
    -Transactional(readOnly = true)를 사용하는 경우 다음과 같이 동작한다.

    +Transactional(readOnly = true)를 사용하는 경우 다음과 같이 동작한다.

    setReadOnly(true) 설정이 된 Connection으로 연결을 시도를 한다. 이 설정을 하는 경우 DB마다 다르게 동작한다.

    • h2의 Connection 구현체는 readOnly 설정을 무시하는 방향으로 구현되어 Transactional 적용되지 않는다.
    • @@ -83,6 +83,6 @@

      새로 배운 부분

      DAO에 @Transactional 적용

      DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
      Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
      -DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

    +DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

    \ No newline at end of file diff --git a/page/10.html b/page/10.html index e02b8c22f..e5dcafe89 100644 --- a/page/10.html +++ b/page/10.html @@ -13,42 +13,59 @@ - - + + -

    · 약 4분

    회고

    -

    지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
    -레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
    -부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
    -내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

    -

    아쉬운 점

    -

    문서화

    -

    개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
    -프로젝트를 진행하면서 내가 한 부분을 조금 더 꼼꼼하게, 이해하기 쉽게 문서화를 했더라면 팀원들에게 더욱 도움이 되었을 텐데 이 부분에 시간을 조금 더 투자하지 못했던 부분에서 아쉬움이 많이 들었다.
    -방학 기간 동안 문서화를 하지 못했던 부분을 개인 블로그 올리면서 조금 더 채워보려고 한다.

    -

    내가 못하는 부분이라면 시간을 들이자

    -

    잘 못하는 부분이라면 시간을 들여서라도 중간은 가도록 해야겠다는 생각이 많이 들었다.
    -말을 하기 전에 정리해서 의견을 내는 것, 발표 준비, 감정 조절 등등 -못하는 부분을 인지하고, 개선하자.

    -

    컴포트 존 벗어나기

    -

    조금 더 도전적으로 목표를 잡았으면 좋았을 것 같다.
    -매번 근거를 가지고 기술을 도입하고, 코드를 작성하려고 노력했다.
    -하지만 지속적으로 개선하려고 하는 부분이 다소 부족했다.

    -

    좋았던 점

    -

    좋았던 점도 문서화

    -

    팀 블로그도 먼저 도입하자고 제안하고, 내가 했던 부분은 문서화를 꽤 많이 해서 팀원들과 공유할 수 있었다.
    -백엔드 크루 4명이서 같이 한 부분에 대해서는 기능 구현한다고 문서화가 조금 미흡해서 보충을 해야겠다.

    -

    내가 디자인한 트립드로우 로고

    - -

    트립드로우 로고를 만들었다.
    -팀원들이 대표 색상(파란색)을 정해줬고, 주말 동안 신나게 로고 디자인을 했던 것 같다.
    -아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

    -

    기술 선택의 이유

    -

    기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
    -100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

    -

    마치며

    -

    플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
    -안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

    +

    · 약 6분

    1단계: https://github.com/woowacourse/java-blackjack/pull/427
    +2단계: https://github.com/woowacourse/java-blackjack/pull/537

    +

    블랙잭

    +

    블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
    +이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

    +

    블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
    +후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

    +

    미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
    +"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

    +

    곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
    +중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
    +부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

    +

    이 부분에 대해 생각이 많아져서 전 리뷰어인 터틀🐢과도 대화를 나누었다.
    +터틀은 제어할 수 없는 부분보다 제어할 수 있는 부분(궁극적인 목표인 좋은 코드를 작성하는 것)에 집중해보라고 하셨다.

    +

    좋은 코드, 좋은 페어에 대한 부분을 일단 지속적으로 생각해봐야겠다.

    +

    부족했던 부분

    +

    페어 신경쓰기
    +이번 페어할 때 적극적으로 의견을 내보도록 했다. 그렇기에 너무 의견을 강하게 밀어붙인 느낌이 들어서 미안했다.
    +후추가 압박을 느꼈을 수도 있을 것 같다는 생각이 든다.
    +중간 중간 작은 회고를 진행해보는 것이 좋을까?

    +

    체력 관리
    +요즘 잘 못먹는 것 같다.
    +앞으로 살 날이 많은데 잘 챙겨먹고, 힘내야겠다.

    +

    중간 중간 돌아보기
    +이번 미션과 관련된 내용은 아니지만 우테코를 잘 활용 하고 있는지 생각을 해봐야겠다.
    +내가 우테코에 지원한 이유를 항상 잊지 않아야겠다.

    +

    새로 학습한 부분

    +

    상태 패턴
    +객체의 내부 상태에 따라 스스로 행동을 변경하도록 하는 패턴으로 if/else/switch와 같은 조건문을 효과적으로 제거할 수 있다.
    +블랙잭 미션을 진행하면서 상태 패턴에 대한 부분을 처음 적용해보았다.
    +처음 적용하기 전에는 별로라고 생각했는데, 생각보다 괜찮은 것 같다.

    +

    일관성, 가독성, 추상화
    +이번 리뷰어는 검프🍫 였다!
    +검프의 리뷰는 간결함에 관련된 내용이 많았다.
    +일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
    +읽기 좋고, 간결한 방향으로 코드를 작성하는 방법을 배운 것 같다.
    +코드를 바라보는 시점이 하나 늘어난 기분이다!(앞으로 적용하는 것은 나의 몫이지만)

    +

    페어에게 배울 부분

    +

    생각 정리
    +중간 중간 현재 상황에 대해 그림을 그리거나, 글을 적으면서 정리한다.
    +페어와 동일한 부분을 이해하고 있는지 확인한다.
    +진행하는데 매우 도움이 되었던 것 같다.
    +나도 다음 페어때부터 펜이랑 종이를 준비해야겠다.

    +

    가감없이 의견을 말해주는 부분
    +진행 상황에 대한 부분, 진행 속도, 지금 자신이 이해하고 있는 부분을 말해줘서 편했다.
    +회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

    +

    도메인 언어에 신경쓰는 부분
    +클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
    +요구사항 정리도 깔끔하게 잘하는 것 같다.

    +

    후추 최고 👍

    \ No newline at end of file diff --git a/page/11.html b/page/11.html index de459d6e3..5ddce0ebb 100644 --- a/page/11.html +++ b/page/11.html @@ -13,91 +13,100 @@ - - + + -

    · 약 6분

    CloudWatch

    -

    AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
    -지표를 감시하여 알림을 보내는 기능도 제공한다.
    -프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
    -요금 정보에 대한 자세한 정보는 다음 링크에서 확인할 수 있다.

    -

    CloudWatch Metrics

    -

    기본적으로 5분마다 지표에 대한 정보가 수집된다.
    -세부 모니터링(Detailed Monitoring)을 활성화하면 1분마다 지표를 수집한다.
    -대시보드에서 InstanceId로 검색하여 수집된 지표를 확인할 수 있다.

    -

    ./cloudwatch1.png

    -

    CPUUtilization, NetworkIn, NetworkOut과 같은 기본적인 지표를 제공하고, 메모리, 디스크 공간과 같은 지표를 확인하려면 사용자 지정 지표를 설정해야 한다.

    -

    CloudWatch Agent 설치

    -

    CloudWatch Agent 사용자 지정 지표와 로그를 수집할 수 있다.

    -

    IAM 역할 설정

    -

    기본적으로 EC2 인스턴스가 CloudWatchAgentServerPolicy에 대한 권한이 있어야 한다.
    -IAM → 역할에서 역할 생성을 클릭한다.

    -

    ./cloudwatch2.png

    -

    CloudWatchAgentServerPolicy 권한 정책을 선택하고, 적당한 역할 이름을 입력해서 역할을 생성한다.

    -

    ./cloudwatch3.png

    -

    EC2 인스턴스 목록으로 들어가서, CloudWatch Agent를 설치할 EC2 인스턴스를 클릭한다.
    -작업 → 보안 → IAM 역할 수정에서 이전에 생성한 역할을 지정한다.

    -

    ./cloudwatch4.png

    -

    설치

    -

    환경은 다음과 같다.

    -

    OS: ubuntu 22.04
    -인스턴스 유형: t4g.small (ARM64)

    -

    아래 명령어를 입력하여 설치한다.

    -
    wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb
    -sudo dpkg -i -E ./amazon-cloudwatch-agent.deb
    -
    -

    사용 설명서에 각 인스턴스 유형마다 다운로드 링크가 자세하게 안내되어 있다.

    -

    Wizard

    -

    CloudWatch Wizard를 사용하면 간단하게 설정 파일 생성할 수 있다.
    -로그를 수집하도록 설정하는 경우 Wizard 실행 명령어 입력 전 log 파일의 절대 경로를 복사해두는 것이 좋다.
    -아래의 명령어를 입력하여 Wizard를 실행할 수 있다.

    -
    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
    -
    -

    설정을 진행하다 보면 설정 파일이 어떻게 구성될지 확인할 수 있다.
    -로그를 추가할 것이냐고 물어보는 입력창이 나오면 준비해뒀던 로그 파일의 절대 경로를 입력한다.

    -

    ./cloudwatch5.png

    -

    중간에 SSM parameter store에 설정 파일을 저장할 것이냐고 물어보는 창이 나온다.

    -
    Do you want to store the config in the SSM parameter store?
    -1. yes
    -2. no
    -
    -

    추가적으로 설정하지 않는 경우 2번을 선택한다.
    -Parameter Store 관리에 대한 내용은 다음의 문서를 참고하면 좋을 거 같다.
    -설정이 완료되면 /opt/aws/amazon-cloudwatch-agent/bin/config.json 에 설정에 대한 내용이 저장된다.

    -

    설정 파일 적용

    -

    아래의 명령어를 입력하여 설정파일을 적용할 수 있다.
    -file 뒤에는 설정 파일에 대한 절대경로(아래 명령어 기준 기본 생성 위치)를 입력하면 된다.

    -
    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
    -
    -

    types.db: no such file or directory 에러

    -

    다음과 같은 에러가 발생한다면 types.db 파일을 생성해서 문제를 해결할 수 있다.

    -
    Error running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory
    -
    -

    types.db 파일 생성

    -
    sudo mkdir /usr/share/collectd
    -sudo touch /usr/share/collectd/types.db
    -
    -

    지표 확인

    -

    CloudWatch Metrics에 가보면 CWAgent라는 네임스페이스가 추가된 것을 볼 수 있다.

    -

    ./cloudwatch6.png

    -

    다음과 같이 설정 파일에 네임스페이스를 추가하여 지표에 대한 네임스페이스를 변경할 수 있다.

    -
    {
    -  "metrics": {
    -    "namespace": "2023-hello-world",
    -    ......
    -   },
    -} 
    -
    -

    로그

    -

    CloudWatch → 로그 그룹으로 가면 Wizard로 추가한 로그를 확인할 수 있다.

    -

    ./cloudwatch7.png

    -

    참고 자료

    -

    CloudWatch란 무엇입니까?
    -Amazon CloudWatch 요금
    -Linux 인스턴스 지표
    -서버에 CloudWatch 에이전트 설치 및 실행
    -CloudWatch Agent를 Parameter Store에서 관리해 보기
    -CloudWatch에이전트 구성 파일

    +

    · 약 9분

    GRASP(General Responsibility Assignment Software Pattern)

    +

    크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

    +

    각 패턴마다 Solution과 Problem로 구성되어 있다.

    +

    정보 전문가 패턴(Information Expert)

    +

    Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

    +

    A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

    +

    정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

    +

    필요한 정보를 가진 객체들로 책임이 분산된다.

    +

    창조자 패턴(Creator)

    +

    Q: 누가 객체 A를 생성하는가?

    +

    A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

    +
      +
    • B가 A 객체를 포함 또는 참조한다.
    • +
    • B가 A 객체를 기록한다.
    • +
    • B가 A 객체를 긴밀하게 사용한다.
    • +
    • B가 A 객체의 초기값을 가지고 있다.
    • +
    +

    생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

    +

    낮은 결합도 패턴(Low Coupling)

    +

    Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

    +

    A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

    +
    +

    결합도(Coupling) +객체 사이의 의존성이 과한 경우 결합도가 높다고 말한다.

    +
    +
      +
    • 오브젝트 p.17
    • +
    +
    +
    +

    결합도를 낮춘다면 다음과 같은 이점이 있다.

    +
      +
    • 다른 구성 요소의 변화에 영향을 받지 않는다.
    • +
    • 재사용이 편리해진다.
    • +
    • 해당 클래스에 대한 이해가 쉬워진다. (의존하는 클래스가 적기 때문에)
    • +
    +

    높은 응집도 패턴(High Cohesion)

    +

    Q. 객체를 관리하기 쉽게 하려면 어떻게 해야 할까?

    +

    A. 높은 응집도를 유지할 수 있게 책임을 할당해야 한다.

    +
    +

    응집도(Cohesion) +연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도가 높다고 말한다.

    +
    +
      +
    • 오브젝트 p.26
    • +
    +
    +
    +

    변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

    +
      +
    • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
    • +
    • 유지보수가 쉬워진다.
    • +
    • 낮은 결합도 또한 지원한다.
    • +
    • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.
    • +
    +

    컨트롤러 패턴(Controller)

    +

    Q. 사용자의 요청을 처리하는 것은 누가 담당해야 하는가?

    +

    A. 사용자의 요청을 처리하는 Controller 객체를 만들어서 사용해야 한다.

    +

    어떤 서브시스템이 존재한다고 가정할 때

    +
      +
    • 직접적으로 객체에 접근하여 프로그램을 사용한다면 결합도가 상승한다.
    • +
    • 서브 시스템에 들어오는 요청을 처리해주는 컨트롤러가 있다면 사용하는 입장에서는 해당 컨트롤러만 알면 된다.
    • +
    • 만약 서브 시스템의 변경이 생겼을 때 외부에 미치는 영향도 줄어든다.
    • +
    +

    다형성 패턴(Polymorphism)

    +

    Q. 객체의 타입에 따라 행동이 바뀐다면 책임을 어떻게 할당해야 할까?

    +

    A. OOP가 지원하는 다형성을 적극적으로 활용한다. (인터페이스를 두고 행동에 대한 부분을 구현)

    +

    객체의 종류에 따라 분기하는 조건문이 아닌 다형성을 사용하는 것이 좋은 방법이다.

    +

    새로운 타입이 추가되었을 때 조건문을 사용한다면 기존의 조건문을 수정해야 하지만 다형성을 활용하면 쉽게 확장할 수 있다.

    +

    변경 보호 패턴(Protected Variations)

    +

    Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

    +

    A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

    +

    간접 참조 패턴(Indirection)

    +

    Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

    +

    A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

    +

    중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

    +

    중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

    +

    순수한 가공물 패턴(Pure Fabrication)

    +

    Q. 책임을 할당한 도메인 객체가 Low Coupling, High Cohesion, 재사용성 등의 목적을 위반한다면 어떻게 해야 할까?

    +

    A. 도메인 개념을 포함하지 않는 클래스를 하나 만들고 매우 응집된 책임을 할당할 수 있다.

    +

    행동을 추가할 때, 해당 책임을 수행할 도메인 개념이 존재하지 않는다면 도메인과 무관한 인공적인 객체를 만든다음 해당 객체에게 책임을 할당한다.

    +

    객체가 데이터베이스에 저장해야 할 값을 가지고 있다고, 정보 전문가 패턴을 적용하여 데이터베이스에 저장하라는 책임을 가지라고 하지 않는다.

    +

    예) 상점과 고객 클래스가 있고 서로 다른 통화를 사용하고 있다고 가정

    +
      +
    • 서로 다른 통화를 사용하고 있기 때문에 거래를 하려면 환전을 해야한다.
    • +
    • 두 클래스 다 환전에 대한 책임을 부여하기 애매하다면 환전을 책임하는 클래스를 추가하고 사용할 수 있다.
    • +
    +

    참고 자료

    +

    오브젝트 5장. 책임 할당하기, 조영호

    +

    Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman

    +

    GRASP, 한빛 네트워크

    \ No newline at end of file diff --git a/page/12.html b/page/12.html index 4e17761f0..48c960a3a 100644 --- a/page/12.html +++ b/page/12.html @@ -13,216 +13,83 @@ - - + + -

    · 약 12분

    이전 글

    -

    경로 이미지 생성하기 - 기술 선택
    -경로 이미지 생성하기 - 구현

    -

    개요

    -

    현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
    -경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
    -따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.

    -

    주기능의 응답속도 개선

    -

    여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
    -하지만 현재 여행 종료와 감상 생성의 응답 속도가 경로 이미지 생성 시간에 영향을 받고 있다.
    -경로 이미지 생성은 비동기 처리하여도 애플리케이션 사용에 문제가 되지 않는다.
    -소요 시간이 1초 이상 걸리는 경우가 존재하기에 이미지 생성을 비동기 처리하고 여행 종료와 감상 생성 기능의 응답 시간을 개선하는 것이 더 중요하다.

    -

    확장성 대비

    -

    현재 10분 간격으로 위치 정보를 서버에 저장하고 있다.
    -조금 더 짧은 간격으로 위치 정보를 그리는 경우 하나의 여행에 많은 위치 정보가 저장될 수밖에 없고 따라서 경로 이미지 생성에 걸리는 시간이 더 길어질 수 있다.
    -따라서 추후에 더 짧은 간격으로 위치 정보를 저장하는 경우를 대비하여 이미지 생성은 비동기로 처리하는 것이 합당하다.

    -

    비동기 처리

    -

    @Async를 사용하면 간단하게 메서드를 비동기로 동작하도록 만들 수 있다.

    -

    비동기 설정

    -

    사용하기 전에 설정 파일을 하나 만들어서 EnableAsync 설정을 해야한다.
    -해당 설정을 적용하면 비동기적으로 실행하려는 메서드에 @Async 애너테이션을 붙여주기만 하면 비동기로 동작한다.

    -
    @EnableAsync
    -@Configuration
    -public class AsyncConfig {
    -}
    -
    -

    스프링 부트를 사용하지 않는 경우 기본적으로 비동기 처리를 할 때 매번 새로운 스레드를 생성하기 때문에 스레드 풀 설정을 따로 해줘야 한다. 하지만 스프링 부트를 사용하는 경우 ThreadPoolTaskExecutor를 따로 설정하지 않아도 기본적으로 스프링 부트가 생성을 도와준다.

    -
    -

    In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing. -7.7. Task Execution and Scheduling, Spring Boot Docs

    -
    -

    @Async 적용

    -

    이미지 생성기에 Async 애너테이션을 붙여 비동기로 동작하도록 한다.

    -
    @Async
    -public void generate(
    -        List<Double> latitudes,
    -        List<Double> longitudes,
    -        List<Double> pointedLatitudes,
    -        List<Double> pointedLongitudes,
    -        Long tripId
    -) {
    -    // 이미지 생성
    -    RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);
    -    Coordinates coordinates = Coordinates.of(latitudes, longitudes);
    -    Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);
    -    drawImage(coordinates, routeImageDrawer, pointedCoordinates);
    -
    -    // 이미지 저장
    -    String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());
    -
    -    // 자원 할당 해제
    -    routeImageDrawer.dispose();
    -
    -    // 데이터베이스 값 변경
    -    Trip trip = tripRepository.findById(tripId)
    -        .orElseThrow();
    -    trip.changeRouteImageUrl(imageUrl);
    -    tripRepository.save(trip);
    -}
    -
    -

    비동기 처리시 문제점

    -

    현재 이미지 생성을 하고 저장 후, 저장 경로를 DB에 반영해야 한다.
    -따라서 패키지 간 순환 참조 형태가 되며 의존성 방향이 문제가 생긴다.

    - -

    이를 해결하기 위해서는 인터페이스를 사용하는 방법과 이벤트를 사용하는 방법이 있다.
    -인터페이스를 사용한다면 다음과 같은 구조가 된다.

    - -

    패키지 간 의존성은 해결되었지만, 이미지 경로 저장을 위해 tripId를 받아야하는 등의 논리적인 의존성은 아직 해결되지 않았다.
    -따라서 이벤트를 사용하기로 했다.

    -

    이벤트 사용

    -

    스프링의 애플리케이션 이벤트를 사용하면 비즈니스 로직의 비관심사(ex. 경로 이미지 생성)을 효율적인 방법으로 처리할 수 있다.

    -

    이벤트 발행

    -

    이벤트를 사용하려면 먼저 이벤트를 발행해야 한다.
    -스프링에서는 ApplicationEventPublisher 인터페이스를 사용하여 이벤트를 발행할 수 있다.
    -해당 인터페이스는 내부적으로 ApplicationContext가 구현하여 이벤트를 발행한다.

    -
    public void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {
    -    ...
    -
    -    // 이벤트 발행
    -    applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));
    -}
    -
    -public record TripUpdateEvent(Long tripId) {
    -}
    -
    -

    이벤트를 발행할 때 발행하는 이벤트명이 중요하다.
    -이벤트를 구독하는 도메인의 행위를 담고 있는 이벤트를 발행(ex. RouteImageGenerateEvent)한다면 논리적인 의존 관계가 남아있기에 이벤트를 적절히 사용했다고 보기 어렵다.
    -발행하는 이벤트명은 주기능이 어떤 행위(ex. TripUpdateEvent)를 했는지에 대한 정보가 담겨있는 이벤트명으로 발행하는 것이 중요하다.

    -

    이벤트 구독

    -

    이벤트를 구독하여 실행하는 메서드는 비동기로 처리하기 위하여 @Async 애너테이션을 적용했다.
    -이벤트의 구독은 여행이 정상적으로 종료될 때 여행에 대한 정보를 가지고 경로 이미지를 생성하기 위해 @TransactionalEventListener를 사용했다.

    -

    TransactionPhase을 사용하여 트랜잭션 이벤트를 어떤 단계에서 수신하고 처리할지를 지정할 수 있다.

    AFTER_COMMIT(기본값): 트랜잭션이 정상적으로 커밋 되는 경우 이벤트 실행
    -AFTER_ROLLBACK: 트랜잭션이 롤백되는 경우 이벤트 실행
    -AFTER_COMPLETION: 트랜잭션이 커밋 또는 롤백 되었을 경우 이벤트 실행
    -BEFORE_COMMIT: 트랜잭션이 커밋 되기 전 이벤트 실행

    -

    이미지 생성의 경우 트랜잭션에서 제외하기 위해 @Transactional 애너테이션을 사용하지 않았다.

    -
    @Component
    -public class TripUpdateEventHandler {
    -
    -    private final RouteImageGenerator routeImageGenerator;
    -    private final TripRepository tripRepository;
    -
    -    public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {
    -        this.routeImageGenerator = routeImageGenerator;
    -        this.tripRepository = tripRepository;
    -    }
    -
    -    @Async
    -    @TransactionalEventListener(phase = AFTER_COMMIT)
    -    public void handle(TripUpdateEvent tripUpdateEvent) {
    -        Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());
    -
    -        String imageUrl = routeImageGenerator.generate(
    -                trip.getLatitudes(),
    -                trip.getLongitudes(),
    -                trip.getPointedLatitudes(),
    -                trip.getPointedLongitudes()
    -        );
    -
    -        trip.changeRouteImageUrl(imageUrl);
    -        tripRepository.save(trip);
    -    }
    -}
    -
    -

    이벤트를 사용함으로써 패키지 간 순환 참조 문제가 다음과 같이 해결되었다.
    -또한 주기능과 부기능을 분리함으로써 경로 이미지 생성 기능에 대한 전체적인 결합도를 낮추었다.

    - -

    테스트

    -

    비동기로 동작하는 메서드를 테스트하기 위해서는 아래와 같은 방법이 있다.

    - - -
    @ContextConfiguration(classes = TestSyncConfig.class)
    -@SpringBootTest
    -public class TripUpdateEventHandlerIntegrationTest {
    -
    -    ...
    -
    -    @Test
    -    void 여행수정_이벤트를_발생시키면_이미지를_생성_요청을_한다() {
    -        // given
    -        TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);
    -        given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))
    -                .willReturn(여행());
    -
    -        // when
    -        transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));
    -
    -        // then
    -        then(routeImageGenerator)
    -                .should(times(1))
    -                .generate(any(), any(), any(), any());
    -    }
    -}
    -
    -

    처음에는 테스트에서만 동기로 설정 후 검증하려고 했다.
    -통합 테스트에선 트랜잭션이 정상 종료되었을 때 비동기로 이벤트를 구독하여 이미지 생성 메서드를 호출하는지 검증이 필요했기 때문에 최종적으로 Mockito.timeout 메서드를 사용하여 비동기 메서드가 통과될 때까지 대기하는 방향으로 변경했다.

    -

    결과

    -

    ./time.png

    -

    위 응답 시간은 위치 정보 1000개를 기준으로 테스트한 값이다.
    -응답 시간에 이미지 생성 시간이 포함되지 않아서 성능이 개선된 것을 볼 수 있다.

    -

    참고 자료

    -

    7.7. Task Execution and Scheduling, Spring Boot Docs
    -Spring Events, Baeldung
    -회원시스템 이벤트기반 아키텍처 구축하기

    +

    · 약 8분

    1, 2단계: https://github.com/woowacourse/java-chess/pull/441
    +3, 4단계: https://github.com/woowacourse/java-chess/pull/529

    +

    체스

    +

    체스 미션에는 가비와 페어가 매칭되었다!
    +체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
    +하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
    +미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

    +

    가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
    +최종적으로 결정한 부분은 다음과 같다.

    +

    각 기물의 이동 가능여부
    +Rank와 File은 각각 위치값을 가지고 있고, 값의 차이를 이용해서 각 기물의 이동 가능 여부를 계산했다.
    +직선 → Rank와 File 차이 중 하나가 0이어야 한다.
    +대각선 → Rank와 File 차이의 절대값이 같아야 한다. ex) abs(-2) == abs(2)
    +나이트 → 차이의 절대값이 하나는 2 나머지 하나는 1이어야 한다.

    +

    도착 칸의 기물 여부
    +아군 → 이동이 불가능하다.
    +적군 → 이동이 가능하다. 적군을 잡는다.

    +

    중간에 기물 존재 여부
    +이동 경로에 기물이 존재하면 안된다.

    +

    데이터베이스 사용
    +체스 미션은 특별하게 데이터베이스와 연결하는 부분이 있었다.
    +체스 게임의 상태를 다음의 두가지 방법으로 정할 수 있다고 생각했다.

    +
      +
    • 기물 전체를 저장하는 방법
    • +
    • 기보를 저장하고 게임을 불러와 기보대로 이동시키는 방법
    • +
    +

    기물이 이동할 때마다 값을 저장하고 싶었고, 기보를 저장하는 방법을 선택했다.
    +기물 전체를 저장하지 않은 이유는 다음과 같다.

    +
      +
    • 턴과 같은 부가적인 요소를 저장해야 한다.
    • +
    • 이동을 할 때 기물이 잡히는 경우 update 쿼리(이동 기물)와 delete(잡힌 기물) 2개의 쿼리를 날려야 한다.
    • +
    • 현재 구조에서 도메인의 변경이 크게(초기 상태를 구성하는 부분) 일어나야 한다.
    • +
    +

    정리하자면 기물 전체 저장과 기보 저장은 다음과 차이가 있다.
    +보드저장: 초기상태에서 32개의 Insert 쿼리(기물의 위치) + 기물 이동 시 움직임 변경(잡히는 경우 2개의 쿼리)
    +기보저장: 초기상태 애플리케이션에서 구성 + 저장된 기보를 select 쿼리로 조회해서 사용(1회) + insert 쿼리(이동 당 1회)

    +

    추가로 기보저장이 구현도 더욱 간단하다. 👍

    +

    부가적인 부분

    +

    리뷰어인 찰리🍫가 동시에 여러 게임이 진행된다면 어떨지? 에 대한 코멘트를 남겨주셔서 다양한 시도를 해봤다.

    +
      +
    • 누누의 도움으로 ConnectionPool 구현
    • +
    • ThreadLocal 사용해서 쓰레드 별 세션 관리
    • +
    • 실제로 애플리케이션 내에서 체스 게임이 진행되는 Board를 ConcurrentHashMap으로 저장(사실 이 부분은 현재 구조에서 필요없지만 2명이 서로 게임하는 경우를 생각해서 넣어보았다.)
    • +
    +

    두 명이 서로 같은 방에 입장하여 게임을 진행한다면 출력하는 부분이 까다로워질 것 같다고 예상되어(Board에 옵저버 패턴을 사용해야되나?) 해볼 엄두가 나지 않았다.

    +

    부족했던 부분

    +

    꼼꼼하게 코드를 작성하지 못한 부분
    +DB 관련 부분을 꼼꼼하게 코딩을 하지 못했다.
    +도메인 로직에만 집중하다보니 정적 중요한 DB의 코드의 예외처리, 빈 값을 반환 하는 부분을 꼼꼼하게 처리하지 못했다.
    +하지만 찰리의 꼼꼼한 리뷰로 DB부분과 나만의 JdbcTemplate을 깔끔하게 구현할 수 있었다.

    +

    시간에 대한 부담감
    +초반에는 여유롭지만 제출 마감에 가까워질 수록 사람이 급해지는 것 같다.
    +다음 페어프로그래밍할 땐 속도를 조절하고, 마음에 여유를 가져야겠다.

    +

    새로 학습한 부분

    +

    DAO 중복 제거

    +

    프롤로그에 을 작성했다.
    +DAO를 작성하는데 try-catch-resources와 여러 코드가 중복되서 제거하고싶었다.
    +템플릿 콜백 패턴으로 깔끔하게 중복을 제거할 수 있었다.👍

    +

    페어에게 배울 부분

    +

    페어 생각하기
    +가비는 누구보다 페어를 생각하고, 배려해주는 페어였다.
    +중간 중간 당 떨어질까봐 걱정도 해주고, 나의 컨디션도 확인해줬다!

    +

    미션 몰입하기
    +최근에 미션에 잘 몰입하지 못했다.
    +가비는 페어를 진행할 때 미션에 대한 몰입도가 매우 좋았다.
    +집에가서도 체스 이동에 대한 로직을 어떻게 구현할 지 생각한 뒤 꼼꼼해서 정리해서 나에게 보내주었다.
    +덕분에 나도 가비의 생각을 알 수 있어서 미션을 진행하는데 가속도가 붙은 것 같다.
    +또한 미션을 잘 마무리하고 싶은 마음이 전달되서 그런지 나도 덩달아 열심히 미션을 할 수 있었다.😄

    +

    솔직함
    +먼저 회고하자고 말 걸어줘서 정말 고마웠다고 표현해주는 부분
    +모르는게 있으면 솔직하게 말해주는 부분
    +나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
    +솔직함은 페어할 때 중요한 부분인 것 같다.

    +

    마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

    \ No newline at end of file diff --git a/page/13.html b/page/13.html index b2e838115..bc31aa89b 100644 --- a/page/13.html +++ b/page/13.html @@ -13,201 +13,77 @@ - - + + -

    · 약 12분

    개요

    -

    여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
    -경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

    -

    구현 결과

    -

    ./result.png

    -

    예시 데이터는 다음과 같다.
    -서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

    -
    List<Double> x = List.of(
    -        126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
    -        126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
    -);
    -List<Double> y = List.of(
    -        37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
    -        37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
    -);
    -List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
    -List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);
    -
    -

    IMAGE_SIZE & ROUTE_SIZE

    -
    private static final int IMAGE_SIZE = 800;
    -private static final int ROUTE_SIZE = 600;
    -
    -

    코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
    -IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
    -ROUTE_SIZE의 경우 상하좌우 100px 만큼의 간격을 위해 존재한다.
    -따라서 실제 경로 이미지의 크기는 600 * 600 사이즈로 생성된다.

    -

    ./600.png

    -

    사이즈 변경의 이유

    -

    255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

    -

    주요 클래스

    -

    요약

    -
    클래스명설명특이사항
    Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
    CoordinatesCoordinate의 일급 컬렉션-
    Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
    PositionsPositions의 일급 컬렉션-
    RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
    RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
    RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
    BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
    Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
    -

    의존관계

    - -

    Coordinates(위도, 경도의 일급 컬렉션)

    -

    List<Double> 2개(위도, 경도)인 형태로 관리하는 방법이 있었지만, 위치 점을 여러개 찍는 부분에서 로직이 복잡해 질 것 같아서 Coordinate(x, y)와 일급 컬렉션인 Coordinates로 관리하기로 했다.
    -Coordinates 클래스에는 다음 두 개의 인터페이스가 존재한다.

    -
      -
    • calculatePositions: 경로 이미지의 크기를 받아 실제 이미지 생성시 사용될 Positions를 반환
    • -
    • indexOf: 다른 Coordinates를 받아 동일한 위치점에 해당하는 인덱스를 반환하는
    • -
    -

    Positions 계산 로직은 다음과 같다.
    -위도, 경도 각각에 대한 부분을 이미지 생성시 필요한 값으로 변환한다.

    -
    // 호출
    -// List<Integer> xPositions = toPositions(xValues, maxDifference, routeImageSize);
    -// List<Integer> yPositions = toPositions(yValues, maxDifference, routeImageSize);
    -
    -private List<Integer> toPositions(List<Double> values, Double maxDifference, Integer routeImageSize) {
    -    Double minValue = Collections.min(values);
    -    return values.stream()
    -            .map(value -> normalizeCoordinate(value, maxDifference, minValue))
    -            .map(value -> mapToPosition(value, routeImageSize))
    -            .toList();
    -}
    -
    -private double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {
    -    return (coordinate - minValue) / maxDifference;
    -}
    -
    -private int mapToPosition(Double coordinate, Integer routeImageSize) {
    -    return (int) (coordinate * routeImageSize);
    -}
    -
    -

    위도로 예시든 내용이다.

    -
      -
    1. Collections.min(values) → 위도 리스트의 최소값을 구한다.
    2. -
    3. normalizeCoordinate → 각각의 위도 값에서 최소값을 빼고 0 ~ 1 사이 값으로 변환 후 위경도의 최대 차이로 나눈다.
    4. -
    5. mapToPosition → 그래프 크기를 받아 0 ~ 1 사이 값을 실제 이미지를 위한 위치값으로 변환한다.
    6. -
    -

    Positions(실제 이미지 생성에 사용할 위치)

    -

    Positions 클래스에는 다음 다섯 개의 인터페이스가 존재한다.

    +

    · 약 8분

    레벨 1이 끝났다.
    +우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
    +혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
    +하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

    +

    Keep

    +

    나만의 루틴 만들기

    +

    스스로가 외부의 영향을 많이 받는다고 생각한다.
    +최대한 꾸준히 할 수 있는 시간을 만드는 것이 중요하다고 생각한다.

    +

    매일 8시에 도착하여 아침에 해야 할 일을 정리하거나, 우선순위에 따라 처리하고
    +소화능력이 부족하기 때문에 점심은 도시락(그래봤자 계란2개)을 준비하고
    +항상 똑같은 컨디션을 유지하기 위해 항상 6시에 집에 간다.
    +이제 바빠질 테니 일찍 집에 가는 일은 어쩔 수 없이 줄어들겠지만😢

    +

    선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

    +

    크루들과 친하게 지내기

    +

    10명 정도의 크루의 닉네임을 외우고 친하게 지낸다면 성공적이라고 생각했었다.
    +하다 보니 더 많은 크루들의 닉네임을 외운 것 같다.
    +앞으로도 크루들과 친하게 지내고 아무 때나 말을 걸 수 있는 크루가 늘어나길 :)

    +

    글쓰기

    +

    글을 잘 쓰는 편은 아니지만 꾸준히 작성하려고 노력했다.
    +매 미션마다 회고를 작성하니 생각도 정리되고 개선점도 찾을 수 있어서 좋았다.

    +

    우아한테크코스에는 레벨마다 글쓰기를 진행하는데, 운이 좋게 글쓰기 상을 받았다.
    +사실 겉으로 드러내지 않았지만 꼭 받아보고 싶었다.
    +글쓰기 조원, 투표해 준 크루들에게 너무 감사하다.

    +

    코드 리뷰 스터디

    +

    누누, 주노, 다즐, 말랑, 박스터, 오잉, 깃짱와 코드 리뷰 스터디를 진행했다.
    +과연 도움이 될까 생각했지만 결과적으로는 코드 리뷰를 하면서 성장을 많이 한 것 같다.
    +투자한 시간 대비 가성비가 좋은 활동이었다.
    +누누가 스터디장인데 과연 꾸준히 이어나가려나?

    +

    레벨 인터뷰

    +

    인터뷰할 때 많이 떨지 않아서 좋았다.
    +남들 앞에서 이야기를 하거나, 면접을 보면 항상 엄청 떨어서 걱정했는데
    +기술적인 질문을 받았을 때 떨지 않고 잘 대답할 수 있었다.
    +우아한테크코스 생활을 하면서 다른 크루가 질문했을 때, 최대한 이해하기 쉽게 설명하려고 했던 경험이 도움이 된 것 같다.
    +이후 레벨 인터뷰를 진행할 때 다음과 같은 부분을 고려하면 더 좋을 것 같다.

      -
    • align: 이미지 사이즈와 경로 이미지 사이즈를 받아 Position 값들을 중앙 정렬한다.
    • -
    • getPositionsByIndexes: 인덱스 리스트를 받아 입력받은 인덱스에 해당하는 값들을 반환한다.
    • -
    • size: 크기를 반환한다.
    • -
    • xPositions: x 값들을 반환한다.
    • -
    • yPositions: y 값들을 반환한다.
    • +
    • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
    • +
    • 두괄식 표현
    • +
    • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
    • +
    • 설명할 수 있을만큼 시간 충분히 가지기
    • +
    • 인터뷰어의 질문 의도를 명확히 이해하지 못했다면 의도 다시 물어보기
    • +
    • 끝맺는 부분 연습하기(자신감 있게)
    • +
    • 기술적인 집착가지기
    • +
    • 기술적인 부분을 꼼꼼히 준비했으면 협업 관련 질문도 준비하기
    -

    중앙 정렬 로직은 다음과 같다.

    -
    public Positions align(int imageSize, int routeSize) {
    -    int xOffset = calculateOffset(Position::x, imageSize);
    -    int yOffset = calculateOffset(Position::y, imageSize);
    -
    -    return items.stream()
    -            .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))
    -            .collect(collectingAndThen(toList(), Positions::new));
    -}
    -
    -private int calculateOffset(ToIntFunction<Position> positionToInteger, int imageSize) {
    -    List<Integer> positions = items.stream()
    -            .mapToInt(positionToInteger)
    -            .boxed()
    -            .toList();
    -
    -    int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;
    -    return imageSize / 2 - midValue;
    -}
    -
    -

    상하좌우 여백을 동일하게 주기 위해서 offset 값을 구해서 x, y 값에 각각 더하는 형태로 중앙 정렬을 수행했다.
    -BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

    -

    ./800.png

    -

    따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

    -

    x 값 → 계산한 offset 그대로 더한다.
    -y 값 → imageSize(800)에서 y + offset 값을 뺀다.

    -

    RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

    -

    BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
    -그림을 그리기 위해 설정한 상수들이 존재한다.

    -
    // RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
    -// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
    -// 이를 RGBA라고 부른다.
    -private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
    -// 배경 투명색
    -private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
    -// 경로를 위한 STROKE
    -private static final int LINE_STROKE_WIDTH = 7;
    -private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    -// 위치 점을 위한 STROKE
    -private static final int POINT_STROKE_WIDTH = 20;
    -private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    -// 안티앨리어싱 등 화질 개선을 위한 설정
    -private static final Map<Object, Object> renderingHints = Map.of(
    -        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
    -        RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
    -        RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
    -);
    -
    -

    RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

    -
      -
    • drawLine: 선을 그린다.
    • -
    • drawPoint: 점을 찍는다.
    • -
    • dispose: 자원 할당을 해제한다.
    • -
    -

    dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

    -

    이미지 생성 Flow

    -

    1. 이미지 생성 준비

    - -

    2. 선 그리기 요청

    - -

    3. 위치 점 그리기 요청

    - -

    4. 업로드 요청

    - -

    전체 Flow

    -
    +

    Problem

    +

    페어프로그래밍

    +

    우아한테크코스를 진행하면서 가장 어려운 활동 중 하나라고 생각한다.
    +페어는 매번 바뀌고, 미션의 복잡도도 증가하기 때문인 것 같다.
    +소통 능력, 시간관리가 부족했고, 만족스럽지 않았다.
    +하지만 페어를 진행하고, 회고를 하다 보니 나만의 노하우가 쌓이는 느낌이다.
    +레벨 2에서는 부족했던 부분을 개선하여 함께하고 싶은 페어가 되고 싶다.

    +

    집중하는 시간⏱️ 부족

    +

    레벨 1을 진행하면서 집중하는 시간이 많이 부족했다.
    +이른 아침과 오후에 개인적으로 집중할 수 있는 공간을 예약해서 온전히 나만의 시간을 가져야겠다.

    +

    Try

    +

    허브🌿와의 티타임?

    +

    소프트 스킬을 늘릴 방법을 생각하다가 대화를 나누지 못한 다른 크루들과 깜짝 커피챗을 하면 어떨까 생각했다.
    +예를 들어 잡담방에 저와 커피챗 하실 분 :) 하면서 올릴 수 있을 것 같다.
    +참여하는 사람이 있을지, 안 좋게 보는 게 아닐지 걱정되지만 그래도 재밌을 것 같다.
    +저랑 허브티 한잔 하실래요?

    +

    기술적인 부분

    +

    우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
    +시간의 여유가 될 때 책을 조금씩 읽어야겠다.
    +블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

    +

    레벨 1을 마무리하며

    +

    시간이 빠르게 흘러갔다.
    +타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
    +또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

    \ No newline at end of file diff --git a/page/14.html b/page/14.html index 0bcfb7614..11d528041 100644 --- a/page/14.html +++ b/page/14.html @@ -13,181 +13,355 @@ - - + + -

    · 약 7분

    개요

    -

    이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

    -

    사용 기술

    -

    언어: Python 3.10
    -이미지 생성: matplotlib
    -서비스: AWS Lambda, AWS API Gateway
    -이미지 저장 및 URL: AWS S3, AWS CloudFront

    -

    플로우는 다음과 같다.

    - -

    요구사항

    -

    ./route.png

    -

    우측 상단의 경로 이미지를 생성하려고 한다.
    -경로 이미지 생성에 대한 요구사항은 다음과 같다.

    -
      -
    • 위도, 경도로 이루어진 배열을 입력받는다.
    • -
    • 이미지 생성
    • -
    • 선과 점 표현
    • -
    • 투명한 배경색
    • -
    • 위경도 차이가 크든 작든 제공하는 이미지 내에 경로가 다 포함되어 있어야 한다.
    • -
    -

    이미지 출력 방식

    -
      -
    1. 위경도를 처리한 값으로 직접 경로를 그린 다음 이미지 형태로 저장
    2. -
    3. 플롯을 그려주는 라이브러리 사용하여 이미지 형태로 저장
    4. -
    -

    이미지 출력 방식의 경우 1번과 2번을 고민했었다.
    -파이썬으로는 플롯을 그려주는 라이브러리인 matplotlib을 사용했다.

    -

    로컬에서 기능 구현

    -
    import time
    -
    -import matplotlib.pyplot as plt
    -
    -
    -def draw(point):
    -    start = time.time()
    -    x, y = zip(*point)
    -    pixel_x, pixel_y = convert_to_pixel_values(x, y)
    -    draw_lines(pixel_x, pixel_y)
    -    end = time.time()
    -    print(end - start)
    -    
    -def convert_to_pixel_values(x, y):
    -    max_diff = max(max(x) - min(x), max(y) - min(y))
    -    return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)
    -
    -
    -def scale_to_pixel_values(points, max_diff):
    -    min_value = min(points)
    -    scaled_coordinates = [(p - min_value) / max_diff for p in points]
    -    return scaled_coordinates
    -
    -
    -def draw_lines(x, y):
    -    figure = plt.gcf()
    -    figure.set_size_inches(5, 5)
    -    plt.plot(x, y, c = 'w',linewidth=5)
    -    plt.scatter(x[3],y[3], c = 'w', s = 125)
    -    plt.axis('off')
    -    plt.savefig('name.png', transparent=True, format='png')
    -
    -point = [
    -    [126.96352960597338, 37.590841000217125],
    -    [126.96987292787792, 37.58435564234159],
    -    [126.98128481452298, 37.58594375113966],
    -    [126.99360339342958, 37.58248524741927],
    -    [126.99867565340067, 37.56778118088622],
    -    [127.001935378366117, 37.55985240444085],
    -    [126.9831048919687, 37.548030119488665],
    -    [126.97189273528845, 37.5119879225856],
    -    [127.02689859997221, 37.48488593333883]
    -]
    -
    -draw(point)
    +

    · 약 10분

    체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
    +이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
    +템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

    +

    기존 코드

    +
    public class User {
    +    private final int id;
    +    private final String name;
    +
    +    public User(final int id, final String name) {
    +        this.id = id;
    +        this.name = name;
    +    }
    +
    +    public int getId() {
    +        return id;
    +    }
    +
    +    public String getName() {
    +        return name;
    +    }
    +}
    +
    +

    SELECT, DELETE 중복 제거

    +

    변하지 않는 부분: try-with-resource, preparedStatement를 사용하는 부분, executeUpdate로 실행 등등
    +변하는 부분: SQL Query, 매개변수

    +

    다음과 같이 쿼리를 실행하는 부분을 분리하고 가변인수를 사용한다면 SELECT와 DELETE의 중복을 제거할 수 있다.

    +
    public void insert(final String name) {
    +    final String query = "INSERT INTO User (name) VALUES (?)";
    +    executeUpdate(query, name);
    +}
    +
    +public void delete(final int userId) {
    +    final String query = "DELETE FROM user WHERE user_id = ?";
    +    executeUpdate(query, userId);
    +}
    +
    +private void executeUpdate(final String query, final Object... parameters) {
    +    final Connection connection = connectionPool.getConnection();
    +    try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
    +        for (int i = 1; i <= parameters.length; i++) {
    +            preparedStatement.setObject(i, parameters[i - 1]);
    +        }
    +        preparedStatement.executeUpdate();
    +    } catch (final SQLException e) {
    +        throw new IllegalArgumentException(e.getMessage());
    +    }
    +}
    +
    +

    조회 분리하기 - 1. 콜백을 위한 인터페이스 정의

    +

    조회는 INSERT, DELETE와 달리 값을 반환받아야 하기 때문에 다른 방법을 사용해야 한다.
    +이 때 콜백이라는 것을 사용하여 중복을 제거할 수 있다.

    +

    프로그래밍에서 콜백은 다른 코드의 인수로 넘겨주는 실행 가능한 코드를 뜻한다.
    +자바에서는 람다나 익명 클래스를 넘겨서 사용할 수 있다.

    +

    데이터베이스에서 값을 조회하고, 해당 값을 객체로 매핑하여 값을 반환해야 한다.
    +executeQuery로 조회한 값은 ResultSet 안에 들어가있다.
    +이를 원하는 타입의 값으로 변환해야하니 일단 콜백을 위한 인터페이스를 만들어야 한다.

    +
    @FunctionalInterface
    +public interface RowMapper {
    +    User mapRow(final ResultSet resultSet) throws SQLException;
    +}
     
    -

    생성 결과는 아래와 같다. (예시를 위해 검은색으로 출력)

    -

    ./routeImage.png

    -

    AWS Lambda

    -

    썸네일 생성 서버를 따로 두기는 기능 대비 비용이 너무 클 것이라고 생각했다.
    -따라서 서버리스로 파일을 처리했다.
    -추가로 s3 접근은 boto3를 사용했다.

    -

    람다 S3 접근을 위한 IAM 생성

    -

    AmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy 두가지를 추가해서 Lambda 전용 역할을 만들어 사용했다.

    -

    람다 배포용 코드

    -

    기술 구현 가능 여부를 확인할 땐 위치 점을 찍는 기능을 람다에 배포하지 않았다.

    -
    
    -import io
    -import uuid
    -
    -import boto3
    -import matplotlib.pyplot as plt
    -
    -PIXEL = 255
    -BUCKET_NAME = 'image-plot'
    -S3 = 's3'
    -
    -def lambda_handler(event, context):
    -    x = event['x']
    -    y = event['y']
    -    image_name = str(uuid.uuid4())
    -
    -    img_data = draw(x, y)
    -    s3 = boto3.client(S3)
    -    s3.put_object(Body=img_data.getvalue(), ContentType='image/png', Bucket=BUCKET_NAME, Key=image_name)
    -    url = f'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}'
    -
    -    return {
    -        'statusCode': 200,
    -        'body': url
    -    }
    -
    -def draw(x, y):
    -    pixel_x, pixel_y = convert_to_pixel_values(x, y)
    -    img_data = draw_lines(pixel_x, pixel_y)
    -    plt.close()
    -    return img_data
    -
    -def convert_to_pixel_values(x, y):
    -    max_diff = max(max(x) - min(x), max(y) - min(y))
    -    return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)
    -
    -def scale_to_pixel_values(points, max_diff):
    -    min_value = min(points)
    -    scaled_coordinates = [(p - min_value) / max_diff for p in points]
    -    pixel_values = [int(p * PIXEL) for p in scaled_coordinates]
    -    return pixel_values
    -
    -def draw_lines(x, y):
    -    plt.plot(x, y, 'k-', linewidth=10)
    -    plt.axis('off')
    -    img_data = io.BytesIO()
    -    plt.savefig(img_data, transparent=True, format='png')
    -    img_data.seek(0)
    -    return img_data
    +

    조회 분리하기 - 2. 단건 조회

    +

    위에서 정의한 RowMapper를 메서드에서 어떻게 사용해야 할까?
    +아래와 같이 SQL 쿼리, RowMapper, 파라미터를 분리한 메서드에 넘겨주고 쿼리 실행 후 매핑한 값을 반환하도록 한다.

    +
    public User findById(final int userId) {
    +    final String query = "SELECT * FROM user WHERE id = ?";
    +    return queryForSingleResult(query, resultSet -> {
    +        final int id = resultSet.getInt("id");
    +        final String name = resultSet.getString("name");
    +        return new User(id, name);
    +    }, userId);
    +}
     
    +private User queryForSingleResult(
    +        final String query,
    +        final RowMapper rowMapper,
    +        final Object... parameters
    +) {
    +    final Connection connection = connectionPool.getConnection();
    +    try (final PreparedStatement preparedStatement = connection.prepareStatement(query);
    +         final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {
    +        if (resultSet.next()) {
    +            return rowMapper.mapRow(resultSet);
    +        }
    +        return null;
    +    } catch (SQLException e) {
    +        throw new IllegalArgumentException(e.getMessage());
    +    }
    +}
    +
    +private ResultSet executeQuery(
    +        final PreparedStatement preparedStatement,
    +        final Object[] parameters) throws SQLException {
    +    for (int i = 1; i <= parameters.length; i++) {
    +        preparedStatement.setObject(i, parameters[i - 1]);
    +    }
    +    return preparedStatement.executeQuery();
    +}
     
    -

    Layer 추가를 위한 zip 파일 생성

    -

    matplotlib의 경우 외부 라이브러리기 때문에 따로 Layer를 추가해야 한다.
    -zip 파일을 만들어서 업로드해야한다.
    -이때 python의 Lambda 런타임에 대한 계층 경로는 python이다.
    -따라서 압축한 zip 파일은 다음과 같은 구조를 띄어야 한다.

    -
    pillow.zip
    -│ python/PIL
    -└ python/Pillow-5.3.0.dist-info
    +

    조회 분리하기 - 3. 다건 조회

    +

    단건 조회와 유사하다.

    +
    public List<User> findAll() {
    +    final String query = "SELECT * FROM user";
    +    return query(query, resultSet -> {
    +        final int id = resultSet.getInt("id");
    +        final String name = resultSet.getString("name");
    +        return new User(id, name);
    +    });
    +}
    +
    +private List<User> query(final String query, final RowMapper rowMapper, final Object... parameters) {
    +    final Connection connection = connectionPool.getConnection();
    +    try (final PreparedStatement preparedStatement = connection.prepareStatement(query);
    +         final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {
    +        final List<User> result = new ArrayList<>();
    +        while (resultSet.next()) {
    +            result.add(rowMapper.mapRow(resultSet));
    +        }
    +        return result;
    +    } catch (SQLException e) {
    +        throw new IllegalArgumentException(e.getMessage());
    +    }
    +}
    +
    +private ResultSet executeQuery(
    +        final PreparedStatement preparedStatement,
    +        final Object[] parameters) throws SQLException {
    +    for (int i = 1; i <= parameters.length; i++) {
    +        preparedStatement.setObject(i, parameters[i - 1]);
    +    }
    +    return preparedStatement.executeQuery();
    +}
     
    -

    Ubuntu 기준 다음 명령어를 입력하여 생성을 진행했다.

    -
    sudo apt update
    -sudo apt install zip
    -sudo apt install python3-pip
    -
    -mkdir python
    -pip3 install matplotlib -t python # pip3 install 설치할_패키지 -t 설치_경로
    -zip -r my_layer.zip python # zip -r 압축_파일명 압축_파일이_존재하는_경로
    +

    제네릭 사용하기

    +

    위의 코드는 User를 조회할 때만 사용할 수 있다.
    +아래와 같이 제네릭을 적용하여 다른 Dao에서도 사용 가능하도록 변경할 수 있다.

    +
    @FunctionalInterface
    +public interface RowMapper<T> {
    +    T mapRow(final ResultSet resultSet) throws SQLException;
    +}
    +
    +private <T> List<T> query(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}
    +private <T> T queryForSingleResult(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}
     
    -

    No module named 'numpy.core._multiarray_umath' 에러

    -

    Layer 추가 후 람다 실행 시 발생한 에러였다.
    -처음에 mac에서 zip 파일을 생성해서 업로드했는데 해당 문제가 발생했다.
    -이는 lambda가 돌아가는 동일한 환경에서 layer를 위한 zip 파일을 만들지 않아서 발생하는 문제다.
    -간단하게 ec2 인스턴스를 하나 만들어서 따로 Layer를 생성하면 문제가 발생하지 않는다.

    -

    적정기술에 대한 생각

    -

    프로젝트에 Lambda와 Python을 사용하려고 했지만 아쉽게도 반려당했다.
    -AWS Lambda를 사용하는 것은 인스턴스에 해당 코드를 배포하는 것보다 더 효율적인 방법일 수 있다.
    -하지만 현재 프로젝트에서 가용 가능한 자원, 기술의 난이도, 사용하는 팀원을 고려한다면 Lambda는 적정기술이 아닐 수 있다.
    -따라서 해당 이미지 생성기를 어떻게 적용할지 조금 더 고려를 해야 될 것으로 보인다.

    -

    최종적으로 Java AWT를 사용하기로 결정했다.

    -

    참고 자료

    -

    AWS Lambda
    -Lambda Layer
    -Python Lambda 함수에 대한 .zip 파일 아카이브 작업
    -No module named 'numpy.core._multiarray_umath'
    -사례별로 알아본 안전한 S3 사용 가이드

    +

    메서드 분리한 부분 클래스로 분리하기 + Optional 사용하기

    +

    메서드로 분리한 부분을 JdbcTemplate이라는 클래스를 만들어 옮긴다.
    +또한 null을 반환하기 보단 Optional로 감싸서 반환하도록 변경한다.
    +최종적으로 아래와 같은 코드가 완성된다.

    +
    public class UserDao {
    +    private final RowMapper<User> rowMapper = resultSet -> {
    +        final int id = resultSet.getInt("id");
    +        final String name = resultSet.getString("name");
    +        return new User(id, name);
    +    };
    +    private final JdbcTemplate jdbcTemplate;
    +
    +    public UserDao(final JdbcTemplate jdbcTemplate) {
    +        this.jdbcTemplate = jdbcTemplate;
    +    }
    +
    +    public void insert(final String name) {
    +        final String query = "INSERT INTO User (name) VALUES (?)";
    +        jdbcTemplate.executeUpdate(query, name);
    +    }
    +
    +    public void delete(final int userId) {
    +        final String query = "DELETE FROM user WHERE user_id = ?";
    +        jdbcTemplate.executeUpdate(query, userId);
    +    }
    +
    +    public Optional<User> findById(final int userId) {
    +        final String query = "SELECT * FROM user WHERE id = ?";
    +        return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);
    +    }
    +
    +    public List<User> findAll() {
    +        final String query = "SELECT * FROM user";
    +        return jdbcTemplate.query(query, rowMapper);
    +    }
    +}
    +
    \ No newline at end of file diff --git a/page/15.html b/page/15.html index c7bdce98b..da0566c5f 100644 --- a/page/15.html +++ b/page/15.html @@ -13,50 +13,83 @@ - - + + -

    · 약 3분

    개요

    -

    정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
    -하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

    -

    예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

    -

    프로젝트를 진행하며 ImageIo.write 메서드가 호출되는 지 검증이 필요했다.
    -해당 static 메서드를 호출하는 부분을 따로 RouteImageUploader 클래스로 최대한 분리했다.
    -이미지 저장 기능 자체가 외부로 나가는 상호작용이고, 호출 횟수를 검사하는데는 mock을 사용하는게 적절하다고 판단했다.

    -
    public void upload(BufferedImage bufferedImage) {
    -    File file = new File(파일경로);
    -    try {
    -        ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);
    -    } catch (IOException e) {
    -        throw new DrawException(IMAGE_SAVE_FAIL);
    -    }
    +

    · 약 6분

    클래스 파일

    +

    자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
    +컴파일된 클래스파일은 어떤 구조로 되어있을까?

    +

    클래스 파일의 데이터 형식

    +

    8비트 바이트의 스트림으로 구성된다.
    +16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
    +멀티바이트의 경우 항상 big endian 순서로 저장된다.

    +

    u1 → unsigned 1byte
    +u2 → unsigned 2byte
    +u4 → unsigned 4byte

    +

    클래스 파일 구조

    +
    ClassFile {
    +    u4             magic;
    +    u2             minor_version;
    +    u2             major_version;
    +    u2             constant_pool_count;
    +    cp_info        constant_pool[constant_pool_count-1];
    +    u2             access_flags;
    +    u2             this_class;
    +    u2             super_class;
    +    u2             interfaces_count;
    +    u2             interfaces[interfaces_count];
    +    u2             fields_count;
    +    field_info     fields[fields_count];
    +    u2             methods_count;
    +    method_info    methods[methods_count];
    +    u2             attributes_count;
    +    attribute_info attributes[attributes_count];
     }
     
    -

    Mocking static methods

    -

    Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
    -mockStatic을 사용하면 MockedStatic<T>이 반환되는데 사용 후 꼭 close를 해줘야 한다.

    -

    JUnit의 @BeforeAll로 설정하고 @AfterAll 메서드로 종료하는 방법도 있지만 MockedStatic<T>의 상위 인터페이스인 ScopedMock이 AutoCloseable을 구현하고 있기에 try-with-resources를 사용하는 방법이 더욱 좋은 것 같다.

    -
    // given
    -BufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);
    -RouteImageUploader routeImageUploader = new RouteImageUploader();
    -
    -// expect
    -try (MockedStatic<ImageIO> imageIO = Mockito.mockStatic(ImageIO.class)) {
    -    routeImageUploader.upload(bufferedImage);
    -    imageIO.verify(
    -            () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),
    -            times(1)
    -    );
    -}
    -
    -

    마치며

    -

    정적 메서드를 모킹하는 것은 안티패턴이으로 적절한 추상화를 이용해 테스트 하기 좋은 코드를 만드는 연습을 하자.
    -하지만 추상화를 하면 할 수록 코드의 복잡도는 증가한다.
    -항상 상황을 고려하고 간결함을 포기할 만큼 중요한 부분인지 적절한 트레이드오프를 고려하자.

    +

    매직넘버

    +

    모든 클래스 파일은 0xCAFEBABE라는 매직넘버로 시작한다.
    +보통 매직넘버는 파일 종류를 식별하는 용도로 사용된다.

    +

    클래스 파일 포맷 버전

    +

    클래스 파일 버전 값은 클래스로더의 호환성 보장을 위해 꼭 필요한 값이다.

    +
      +
    • Java 17 버전으로 빌드한다면 class version 61 ex) 00 00 00 3D
    • +
    +

    호환되지 않는 버전의 클래스 파일을 로딩하려고 하는 경우 런타임에 UnsupportedClassVersionError 예외가 발생한다.

    +

    class file format major versions

    +
    Java SEReleasedMajorSupported majors
    8March 20145245 .. 52
    9September 20175345 .. 53
    10March 20185445 .. 54
    11September 20185545 .. 55
    12March 20195645 .. 56
    13September 20195745 .. 57
    14March 20205845 .. 58
    15September 20205945 .. 59
    16March 20216045 .. 60
    17September 20216145 .. 61
    +

    상수 풀

    +

    2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
    +클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
    +JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

    +

    액세스 플래그

    +

    클래스, 인터페이스와 같은 파일의 속성을 표시한다.
    +예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.

    +
      +
    • 계산은 다음과 같이 이루어진다. ACC_PUBLIC xor ACC_INTERFACE xor ACC_ABSTRACT
    • +
    +

    공식문서에 들어가면 각 플래그에 대한 설명 + 플래그 설정시 동시에 설정되면 안되는 플래그와 같은 설명이 자세하게 나와있다.

    +

    Class access and property modifiers

    +
    Flag NameValueInterpretation
    ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
    ACC_FINAL0x0010Declared final; no subclasses allowed.
    ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
    ACC_INTERFACE0x0200Is an interface, not a class.
    ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
    ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
    ACC_ANNOTATION0x2000Declared as an annotation type.
    ACC_ENUM0x4000Declared as an enum type.
    ACC_MODULE0x8000Is a module, not a class or interface.
    +

    this_class

    +

    클래스명과 같은 이름을 표현하는 값으로, 상수 풀에서 클래스명과 일치하는 항목의 인덱스를 참조한다.
    +해당 인덱스의 항목은 CONSTANT_Class_infoclass 형식의 값이어야 한다.

    +

    super_class

    +

    상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
    +아무것도 상속하지 않는 클래스의 경우 java.lang.Object의 인덱스 값이 들어있다.

    +

    interface, field, method

    +

    각각의 개수와, 정보에 대한 값이 들어있다.
    +interface, field, method를 표시하는 방법이 각각 다르고, 접근자에 대한 플래그도 각각 다르다.

    +

    attributes

    +

    해당 클래스 파일에서 사용하는 추가 정보의 모음이다. 예) 소스파일명
    +정해진 클래스 파일의 구조를 확장하는 역할을 한다.

    +

    클래스 파일 확인하면서 사용한 툴

    +

    IntelliJ plugin - BinEd
    +IntelliJ plugin - jclasslib Bytecode Viewer

    참고 자료

    -

    Mocking static methods
    -Mockito mock static methods
    -Enable mocking static methods in Mockito

    +

    2장 JVM 이야기, 자바 최적화
    +Class file in Java, File Format
    +java se11 Class 파일 형식, Oracle
    +java se17 Class 파일 형식, Oracle

    \ No newline at end of file diff --git a/page/16.html b/page/16.html index 0eba9f0ac..0c0bb0359 100644 --- a/page/16.html +++ b/page/16.html @@ -13,60 +13,50 @@ - - + + -

    · 약 6분

    ./route.png

    -

    이미지 생성의 책임

    -

    위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
    -따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

    -

    해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

    -
      -
    • 이미지 생성
    • -
    • 선과 점 표현
    • -
    • 투명한 배경색
    • -
    -

    현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

    -

    고려한 기술

    -

    백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

    -
      -
    • Python의 Matplotlib
    • -
    • AWT(Abstract Window Toolkit) [최종 선택]
    • -
    • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
    • -
    • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)
    • -
    -

    Python & Matplotlib

    -

    데이터 시각화 라이브러리
    -이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

    -
      -
    • 코드가 간단해서 유지 보수성이 좋다.
    • -
    • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
    • -
    • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.
    • -
    -

    Java AWT 이외의 라이브러리

    -

    Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

    -
    라이브러리설명제외 이유
    SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
    JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
    simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
    matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
    -

    Java & AWT(Abstract Window Toolkit)

    -

    그래픽과 이미지를 그리기 위한 도구
    -이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

    -
      -
    • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
    • -
    • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
    • -
    • 추가적인 api 호출을 하지 않아도 된다.
    • -
    -

    기술 선택

    -

    AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
    -하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

    -

    유지 보수

    -

    AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
    -따라서 다음과 같은 방법으로 공유하기로 했다.

    -
      -
    1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
    2. -
    3. AWT를 사용한 부분을 문서화하여 공유한다.
    4. -
    -

    레벨 3를 마무리하며 내용 추가

    -

    기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
    -AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

    +

    · 약 5분

    테스트 대역이란?

    +

    모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
    +Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

    +

    테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
    +외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

    +

    테스트 대역의 타입 계층 구조

    + +

    더미(Dummy)

    +

    가장 단순하고, 원시적인 유형의 테스트 대역이다.
    +기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
    +만약 메서드가 무언가 반환을 해야하는 경우 0, null과 같은 값을 반환한다.

    +

    스텁(Stub)

    +

    시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
    +이를 통해 특정 조건에서 메서드가 예상한대로 동작하는지 확인할 수 있다.

    +

    스파이(Spy)

    +

    스텁과 유사하지만 호출 여부를 기록하거나 호출할 때 전달한 인자값을 기록할 수 있다.
    +예) 메일 전송 기능을 가진 객체를 테스트 대역으로 구현했을 때 메일 전송 횟수를 기록한다.

    +

    목, 모의 객체(Mock)

    +

    목은 더미, 스텁, 스파이를 포함한다.
    +호출 시 사전에 정의된 결과를 반환하고, 예상치 못한 호출이 있을 경우 예외를 던질 수 있다.
    +또한 호출에 대한 검증을 할 수 있다.

    +

    가짜(Fake)

    +

    DOC와 동일한 기능을 제공하지만, 더욱 간단한 방법으로 구현된 것이다.
    +예) 실제 데이터베이스와 유사하게 동작하는 가짜 객체를 만들어 테스트할 수 있다.

    +

    의존 구성 요소, DOC를 테스트 더블로 대체할 수 있다.
    +테스트 더블은 DOC와 동일한 API를 제공해야 한다.

    +

    상호작용에 따른 목과 스텁 구분

    +

    단위 테스트 p.149 에서는 테스트 대역을 크게 목과 스텁으로 구분한다.
    +목은 SUT와 관련된 상호작용을 모방하고 검사하는 반면, 스텁은 단순 모방만 한다.

    +
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색
    +

    테스트 대상 시스템
    +테스트를 하려는 대상

    +

    참고 자료

    +

    소프트웨어 장인 정신 이야기 - 3장 고급 테스트 주도 개발, 로버트 C. 마틴
    +단위 테스트 - 5장 목과 테스트 취약성, 블라디미르 코리코프
    +테스트 주도 개발 시작하기 - 7장 대역, 최범균
    +테스트 더블, Martin Fowler
    +테스트 관련 용어 정리, Johngrib
    +Test Double, Gerard Meszaros

    \ No newline at end of file diff --git a/page/17.html b/page/17.html index c92a7a7b8..59d5f766d 100644 --- a/page/17.html +++ b/page/17.html @@ -13,99 +13,138 @@ - - + + -

    · 약 5분

    자바 17, 스프링 6.0, 스프링 부트 3.1

    -

    팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
    -2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

    -

    자바 변경 사항

    -

    우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
    -따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

    -

    Switch Expressions(Java 14)

    -

    Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

    -
    enum RESULT {
    -    WIN, LOSE, DRAW
    -}
    -
    -RESULT result = RESULT.WIN;
    -
    -int prize = switch (result) {
    -    case WIN -> 10_000_000;
    -    case LOSE, DRAW -> 5_000_000;
    -	default -> 0;
    -};
    -
    -

    주요 특징은 다음과 같다.

    +

    · 약 10분

    트랜잭션(Transaction)

    +

    데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
    +트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
    +논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

    +

    트랜잭션의 속성(ACID)

    +

    원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
    +일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
    +격리성(Isolation): 각각의 트랜잭션은 독립적이라 서로에게 영향을 주지 않아야 한다.
    +지속성(Durability): 트랜잭션이 성공적으로 완료된다면 영구적으로 결과에 반영되어야 한다.

    +

    트랜잭션 주의사항

    +

    트랜잭션은 꼭 필요한 최소의 코드에만 적용하는 것이 좋다.(트랜잭션의 범위를 최소화하라)
    +구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

    +

    데이터의 일관성과 안전성을 보장하기 위해 배제해야 한다.
    +네트워크 작업을 트랜잭션 내부에 포함한다면 다음과 같은 문제가 발생할 수 있다.

      +
    • 네트워크 작업이 중간에 실패할 가능성(안전성 X)
    • +
    • 통신으로 인해 데이터가 변경될 수 있는 부분(일관성 X)
    • +
    +

    격리 수준(Isolation level)

    +

    여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 데이터의 조회 및 변경을 허용할지 결정하는 것을 말한다.
    +격리 수준이 높아질 수록 동시 처리 성능이 떨어지는 것이 일반적이지만, SERIALIZABLE이 아니라면 크게 성능의 저하가 발생하지 않는다.

    +

    READ UNCOMMITTED

    +

    각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다.
    +더티 리드 현상이 발생하기 때문에 정합성의 문제가 많은 격리 수준이다.
    +MySQL 사용시 최소 READ COMMITTED 이상의 격리 수준 사용을 권장한다.

    + +

    READ COMMITTED

    +

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    +오라클 DBMS에서 기본으로 사용되는 격리 수준이다.
    +REPEATABLE READ가 보장되지 않기 때문에 NON-REPEATABLE READ 문제가 발생한다.

    + +

    REPEATABLE READ

    +

    트랜잭션이 시작되기 전에 COMMIT이 완료된 내용에 대해서만 조회할 수 있다.
    +MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준이다.
    +MVCC를 이용해 언두(Undo) 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장한다.
    +동일한 결과를 보장하는 방법은 다음과 같다.

      -
    • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
    • -
    • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
    • -
    • break 문이 필요 없다.
    • -
    • default 블록을 통해 기본 값을 지정할 수 있다.
    • +
    • 모든 InnoDB 트랜잭션은 순차적으로 증가하는 고유한 트랜잭션 번호를 가진다.
    • +
    • Undo 영역에 백업된 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함되어있다.
    • +
    • Undo 영역의 백업된 데이터는 스토리지 엔진이 불필요하다고 판단하는 경우 삭제된다.
    • +
    • REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 가장 오래된 트랜잭션 번호보다 앞선 Undo 영역의 데이터는 삭제하지 않는다.
    -

    Text Block(Java 15)

    -

    Java 15에는 새로운 문자열 표현방식이 추가되었다.
    -긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

    -
    @Repository
    -public interface PostRepository extends JpaRepository<Post, Long> {
    -    @Query("""
    -        SELECT p FROM Post p
    -        WHERE p.title LIKE %:keyword%
    -        OR p.content LIKE %:keyword%
    -        """)
    -    List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
    -}
    -
    -

    NPE 메시지(Java 15)

    -
    String name = null;
    -name.chars();
    -
    -/** 
    -# before
    -java.lang.NullPointerException
    -	at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)
    -
    -# after
    -Cannot invoke "String.chars()" because "name" is null
    -java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
    -*/
    -
    -

    Record(Java 16)

    -

    Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
    -Record를 선언하는 경우 접근자, 생성자, equals & hashcode, toString이 제공된다.
    -데이터 전송 용도로 적합해 보인다.

    -
    public record PostDto(String title, String content) {
    -}
    -
    -

    추가적인 변경사항

    -

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    -

    스프링, 스프링 부트 변경 사항

    -

    스프링과 스프링 부트에도 많은 변경 사항이 있었다.
    -따라서 필요해보이는 몇개 정도만 정리했다.

    -

    스프링 요구사항

    -

    Java 17, Jakarta EE 9 이상이어야 한다.

    -

    네임스페이스 변경

    -

    Jakarta EE 9가 적용되면서 네임스페이스도 전반적으로 javax -> jakarta로 변경되었다.

    -

    PathPatternParser - trailing slash 허용하지 않음

    -

    6.0 이전의 경우 기본 설정 기준으로 @GetMapping("/hello")@GetMapping("/hello/")가 동일했다.
    -6.0 이후의 PathPatternParser가 기본으로 사용되고, /hello/hello/는 서로 다른 URL로 매칭된다.

    -
    -

    PathPatternParser used by default (with the ability to opt into PathMatcher).

    -
    -

    HTTP interface client

    -

    자바 인터페이스와 어노테이션을 이용하여 HTTP 요청을 위한 서비스를 정의할 수 있는 방법이 추가되었다.
    -자세한 내용은 토비님의 강의를 참고하면 좋을 것 같다.

    -

    스프링 부트 최소 요구사항

    -

    Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6
    -이외에도 서드파티들의 최신 릴리즈 버전을 사용함으로, 문제가 발생하는 경우 해당 버전에 맞는 릴리즈 노트를 참고할 수 있을 것 같다.

    +

    InnoDB에서는 갭 락과 넥스트 키 락을 이용하여 팬텀 리드 현상을 방지한다.

    + +

    갭 락: 레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    +넥스트 키 락: 레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.

    +

    동시성을 제어하는 방법 중 하나로 하나의 레코드에 대해 여러 개의 버전이 동시에 관리되는 것이다.

      +
    • PostgreSQL은 다중 버전의 데이터를 저장하는 것으로 MVCC를 구현한다.
    • +
    • Oracle, InnoDB는 Undo log를 이용해 이 기능을 구현한다.(최신 버전의 데이터만 DB에 저장)
    • +

    잠금을 사용하지 않는 읽관된 읽기를 제공하는 것이 목적이다.

    +

    SERIALIZABLE

    +

    트랜잭션을 순차적으로 진행시키는 격리 수준이고 따라서 동시 처리 성능도 다른 격리 수준보다 떨어진다.
    +트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 접근할 수 없고 단순한 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야만 한다.
    +InnoDB에서는 팬텀 리드 현상이 REPEATABLE READ 격리 수준에서 발생하지 않기 때문에 굳이 사용할 필요는 없다.

    +

    격리 수준에 따른 부정합 문제

    +

    격리 수준에 따라 더티 리드, 반복 가능하지 않은 조회, 팬텀 리드 문제가 발생한다.

    +
    격리 수준 / 부정합 문제더티 리드반복 가능하지 않은 조회팬텀 리드
    READ UNCOMMITTEDOOO
    READ COMMITTEDXOO
    REPEATABLE READXXO(InnoDB는 X)
    SERIALIZABLEXXX
    +

    더티 리드(Dirty read)

    +

    어떤 트랜잭션에서 처리한 작업이 완료되지 않았어도 다른 트랜잭션에서 볼 수 있는 현상
    +트랜잭션 격리 수준이 READ UNCOMMITTED일 때 발생한다.
    +예) B가 레코드를 추가하고 커밋을 하지 않았지만, A가 해당 레코드를 조회할 수 있는 경우

    +

    반복 가능하지 않은 조회(Non-repeatable read)

    +

    한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 그 값이 다른 현상
    +예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

    + +

    팬텀 리드(Phantom read, Phantom row)

    +

    한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
    +예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

    +

    참고 자료

    -

    어느 월급쟁이개발자 의 스프링 부트 따라잡기
    -자바 9-16 주요 특징 복습하기
    -Java EE에서 Jakarta EE로의 전환
    -Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩
    -What's New in Spring Framework 6.x
    -Spring Boot 3.0 Release Notes
    -Spring Boot 3.1 Release Notes

    +

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    +Isolation Level, MySQL

    \ No newline at end of file diff --git a/page/18.html b/page/18.html index 69bc3e615..0540de94a 100644 --- a/page/18.html +++ b/page/18.html @@ -13,70 +13,74 @@ - - + + -

    · 약 5분

    웹소켓

    -

    단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
    -웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

    -

    웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

    -

    웹소켓 등장 배경

    -

    웹소켓이 등장하기 이전, 실시간성을 보장하기 위해 Polling, Long polling, Streaming 같은 기술을 사용했어야 했다.
    -이는 실시간성이나 양방향성을 만족시키지 못했고, HTTP를 이용하기 때문에 과도한 오버헤드가 발생했다.

    -

    Polling: 주기적으로 서버에 요청을 보내 수신할 정보가 있는지 확인하는 방법

      -
    • 서버에서 보낼 내용이 없어도 클라이언트는 알 수 없다.
    • -
    • 계속해서 요청을 보내 확인을 해야하기 때문에 서버에 불필요한 부하를 주어야 한다.
    • -

    Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

      -
    • 폴링 방식보다 서버에 적은 부하를 줄 수 있지만, 요청의 주기가 짧으면 폴링과 차이가 없어진다.
    • -

    Streaming: 클라이언트가 request를 보내면 커넥션을 맺고, 이 커넥션을 유지하면서 서버가 계속 데이터를 보내는 방법

      -
    • 클라이언트가 서버에 요청을 하고 싶다면 새로운 커넥션을 맺어야 한다.
    • -
    -

    웹소켓의 동작

    -

    · 약 5분

    MySQL 엔진의 잠금

    +

    MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
    +MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

    +

    글로벌 락(Global lock)

    +

    MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

    +
      +
    • 영향을 미치는 범위는 해당 서버 전체이다.
    • +
    • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.
    • +
    +

    한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
    +데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
    +InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

    +
    -- GLOBAL LOCK
    +FLUSH TABLES WITH READ LOCK;
    +-- UNLOCK
    +UNLOCK TABLES;
     
    -    Client->>Server: 양방향 통신
    -    Server->>Client: 
    +-- BACKUP LOCK
    +LOCK INSTANCE FOR BACKUP;
    +-- UNLOCK
    +UNLOCK INSTANCE;
    +
    +

    MySQL 5.5 버전 이전의 기본 스토리지 엔진이다.
    +트랜잭션을 지원하지 않고, SELECT 작업 속도가 빠르다.

    +

    테이블 락(Table lock)

    +

    개별 테이블 단위로 설정되는 잠금이다.
    +명시적 또는 묵시적으로 특정 테이블의 락을 획득할 수 있다.
    +묵시적 락은 MyISAM이나 MEMORY 테이블에 데이터를 변경하는 쿼리를 실행하면 발생한다.
    +InnoDB 테이블에는 DML 쿼리는 무시되고 DDL 일 경우에만 묵시적으로 락을 획득한다.

    +
    -- TABLE LOCK
    +LOCK TABLES table_name [ READ | WRITE ]
    +
    +-- UNLOCK
    +UNLOCK TABLES;
    +
    +

    네임드 락(Named lock)

    +

    임의의 문자열에 대한 잠금을 설정할 수 있는 잠금으로 유저 레벨 락으로도 불린다.
    +여러 스레드나 프로세스가 동일한 데이터를 수정하려는 경우, 동시에 수정하지 못하도록 보호할 수 있다.

    +
    -- aGVyYg== 라는 문자열에 대한 잠금 획득, 이미 잠금을 사용중인 경우 1초 동안만 대기
    +SELECT GET_LOCK('aGVyYg==', 1);
    +
    +-- 문자열에 대한 잠금이 설정되어 있는지 확인한다.
    +SELECT IS_FREE_LOCK('aGVyYg==');
    +
    +-- 문자열에 대한 잠금을 해제한다.
    +SELECT RELEASE_LOCK('aGVyYg==');
    +
    +-- 위 3개 함수 모두 정상적으로 락을 획득하거나 해제한 경우에 1을, 아니면 0을 반환한다.
     
    -    Client->>Server: 종료
    -    Server->>Client: ">
    -

    1. Upgrade 요청

    -

    WebSocket 프로토콜로 전환하는 HTTP 요청을 보낸다.
    -이는 HTTP와 같이 80, 443 포트를 사용한다.
    -웹소켓으로 전환하기 위해서는 Upgrade: websocket, Connection: Upgrade 헤더가 필요하다.
    -Sec-WebSocket-Key는 서버에서 Sec-WebSocket-Accept를 계산하여 응답하고 이 값이 예상한 값과 다르면 연결이 수립되지 않는다.
    -Sec-WebSocket-Protocol의 경우 서브프로토콜의 목록으로 서버 측에서는 해당 목록 중 하나를 선택하여 반환해야 한다.
    -만약 서버측에서 여러 개 지원이 가능한 경우 지원 가능한 프로토콜 중 첫번째 프로토콜을 클라이언트측으로 보낸다.

    -
    GET /chats HTTP/1.1
    -Host: localhost:8080
    -Upgrade: websocket
    -Connection: Upgrade
    -Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
    -Sec-WebSocket-Protocol: v10.stomp, v11.stomp
    -Sec-WebSocket-Version: 13
    -Origin: http://localhost:8080
    +-- 모든 문자열에 대한 잠금을 해제한다. 해제된 잠금의 개수를 반환한다.
    +SELECT RELEASE_ALL_LOCKS();
     
    -

    2. Switching Protocols

    -

    서버는 101 Switching Protocols 응답을 반환한다.
    -Sec-WebSocket-Accept은 Sec-WebSocket-Key 뒤에 258EAFA5-E914-47DA-95CA-C5AB0DC85B11를 붙이고 SHA1로 해싱 후 Base64로 인코딩하여 반환한다.
    -이는 서버 웹소켓 프로토콜의 지원 여부를 클라이언트에게 명확히 알리기 위해 존재한다.

    -
    HTTP/1.1 101 Switching Protocols 
    -Upgrade: websocket
    -Connection: Upgrade
    -Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
    -Sec-WebSocket-Protocol: v10.stomp
    +

    메타데이터 락(Metadata lock)

    +

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    +명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    +보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    +
    -- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
    +-- 아래 구문 실행 시 메타데이터 락을 자동으로 획득한다.
    +RENAME TABLE rank TO rank_backup, rank_new TO rank;
     
    -

    3. 통신 후 종료

    -

    연결이 수립되면 웹소켓 프레임 단위로 양방향 통신을 한다.
    -연결 종료를 원하는 경우 클라이언트, 서버 모두 연결 종료를 요청할 수 있다.

    -

    참고 자료

    -

    https://datatracker.ietf.org/doc/html/rfc6455
    -https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
    -https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
    -https://docs.spring.io/spring-framework/reference/web/websocket.html

    +

    참고 자료

    +

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    +MySQL의 User Level Lock를 활용한다면?, gywndi
    +Locking Functions, MySQL 5.7 Reference
    +Locking Functions, MySQL 8.0 Reference

    \ No newline at end of file diff --git a/page/19.html b/page/19.html index 30a8f04ff..fb0765ece 100644 --- a/page/19.html +++ b/page/19.html @@ -13,358 +13,68 @@ - - + + -

    · 약 11분

    팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

    -

    설치

    -

    공식 홈페이지에 들어가서 최신 버전을 설치한다.

    -
    yarn create docusaurus
    -
    -

    배포

    -

    배포 안내 문서
    -netlify나 vercel 같은 서버리스 플랫폼을 추천하고 있고, 간단하고, 빠른 시간 안에 배포를 할 수 있다.
    -이 글에서는 github pages를 이용해서 배포하는 방법을 설명한다.

    -

    레포지토리 생성

    -

    github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
    -이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

    -

    설정 파일 수정

    -
    module.exports = {
    -  // ...
    -  url: 'https://greeng00se.github.io',
    -  baseUrl: '/',
    -  projectName: 'greeng00se.github.io',
    -  organizationName: 'greeng00se',
    -  trailingSlash: false,
    -  // ...
    -};
    -
    -

    토큰 설정

    -

    github action을 위해 배포용 토큰을 하나 생성하여 생성한 레포지토리에 Repository secrets으로 설정한다.
    -이 글에서는 토큰을 클래식 방식으로 생성했고 스코프는 [repo, user, workflow] 을 설정했다.

    -

    github

    -

    브랜치 생성

    -

    github에서 gh-pages 브랜치를 하나 생성한다.
    -repository -> settings -> pages -> branch에서 생성한 gh-pages로 브랜치를 변경한다.
    -설정한 브랜치가 배포 브랜치가 되며, 해당 브랜치에 있는 파일들을 이용해서 정적 웹사이트를 제공한다.

    -

    워크플로 작성

    -

    Docusaurus 2.0 기준 Node.js 16.14 이상의 버전을 사용해야 합니다.
    -배포시에는 Repository secrets으로 설정한 DEPLOY_TOKEN 을 이용합니다.

    -
    name: blog
    -
    -on:
    -  push:
    -    branches: [main]
    -
    -jobs:
    -  deploy:
    -    name: Deploy to GitHub Pages
    -    runs-on: ubuntu-latest
    -    steps:
    -      - uses: actions/checkout@v2
    -      - uses: actions/setup-node@v3
    -        with:
    -          node-version: 18
    -          cache: yarn
    -
    -      - name: Install dependencies
    -        run: yarn install --frozen-lockfile
    -      - name: Build website
    -        run: yarn build
    -
    -      - name: Deploy to GitHub Pages
    -        uses: peaceiris/actions-gh-pages@v3
    -        with:
    -          github_token: ${{ secrets.DEPLOY_TOKEN }}
    -          publish_dir: ./build
    -          user_name: github-actions[bot]
    -          user_email: 41898282+github-actions[bot]@users.noreply.github.com
    -
    -

    댓글 기능

    -

    giscus를 이용하여 댓글 기능을 추가한다.

    -

    giscus 설정

    -
      -
    1. 공개 저장소여야 한다.
    2. -
    3. giscus 앱이 설치되어 있어야 한다.
    4. -
    5. Discussions 기능이 해당 저장소에서 활성화되어 있어야 한다.
    6. -
    -

    자세한 내용은 giscus를 확인하자.

    -

    docusaurus 설정

    -

    swizzling을 이용하여 컴포넌트를 감싼다.
    -기존에 게시물을 giscus가 포함된 리액트 컴포넌트로 감싸는 형태가 된다.
    -아래 명령어를 이용하여 BlogPostItem을 추출할 수 있다.

    -
    yarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap
    -
    -

    명령어를 입력하면 /src/theme/BlogPostItem/index.js 위치에 파일이 생성된다.
    -파일의 내용을 아래와 같이 수정하고, 이때 setAttribute 부분은 적절하게 자신의 giscus 설정을 이용한다.

    -
    import OriginalBlogPostItem from "@theme-original/BlogPostItem";
    -import React, { useEffect, useRef } from "react";
    -// @ts-expect-error internal code
    -import { useColorMode } from "@docusaurus/theme-common";
    -import { useBlogPost } from "@docusaurus/theme-common/internal";
    -
    -const giscusSelector = "iframe.giscus-frame";
    -
    -function BlogPostItem(props) {
    -  const { colorMode } = useColorMode();
    -  const { isBlogPostPage } = useBlogPost();
    -  const giscusTheme = colorMode === "dark" ? "dark" : "light";
    -  const containerRef = useRef(null);
    -
    -  useEffect(() => {
    -    if (!isBlogPostPage) return;
    -
    -    const giscusEl = containerRef.current.querySelector(giscusSelector);
    -
    -    const createGiscusEl = () => {
    -      const script = document.createElement("script");
    -
    -      script.src = "https://giscus.app/client.js";
    -      script.setAttribute("data-repo", "teco-chat/teco-chat.github.io");
    -      script.setAttribute("data-repo-id", "R_kgDOJZ5j0Q");
    -      script.setAttribute("data-category", "Announcements");
    -      script.setAttribute("data-category-id", "DIC_kwDOJZ5j0c4CXS_Q");
    -      script.setAttribute("data-mapping", "pathname");
    -      script.setAttribute("data-strict", "0");
    -      script.setAttribute("data-reactions-enabled", "1");
    -      script.setAttribute("data-emit-metadata", "0");
    -      script.setAttribute("data-input-position", "bottom");
    -      script.setAttribute("data-theme", giscusTheme);
    -      script.setAttribute("data-lang", "ko");
    -      script.crossOrigin = "anonymous";
    -      script.async = true;
    -      
    -      containerRef.current.appendChild(script);
    -    };
    -
    -    const postThemeMessage = () => {
    -      const message = {
    -        setConfig: {
    -          theme: giscusTheme,
    -        }
    -      };
    -
    -      giscusEl.contentWindow.postMessage({ giscus: message }, "https://giscus.app");
    -    };
    -
    -    giscusEl ? postThemeMessage() : createGiscusEl();
    -  }, [giscusTheme]);
    -
    -  return (
    -    <>
    -      <OriginalBlogPostItem {...props} />
    -      {isBlogPostPage && <div ref={containerRef} />}
    -    </>
    -  );
    -}
    -
    -export default BlogPostItem;
    -
    -

    알고리아 설정 및 직접 관리하기

    -

    알고리아를 사용하면 검색 기능을 추가할 수 있다.
    -유료 플랜이나 netlify를 사용하는 경우 크롤러를 따로 제공해 주는 것 같다.

    -

    무료 플랜은 직접 인덱스를 수집하는 방법과, docsearch를 이용하는 방법이 있다.
    -docsearch에 등록한다면 일주일에 한 번씩 크롤링이 진행된다.
    -이 글에서는 직접 인덱스를 수집하는 방법을 사용한다.

    - -

    알고리아 애플리케이션 생성 및 키 확인

    -

    회원가입을 하고 새로운 애플리케이션 생성을 누른다.
    -생성을 다 마치면 다음과 같이 api 키를 확인할 수 있다.

    -

    algolia

    -

    키 생성

    -

    직접 인덱스를 수집하기 위한 키를 생성한다.
    -addObject, editSettings, deleteIndex acl(접근 제어 목록)이 있으면 된다.

    -

    key

    -

    .env 파일 생성

    -

    프로젝트 폴더 상단에 .env 파일을 생성한다.

    -
    APPLICATION_ID=MVIU5UEMOM
    -API_KEY=인덱스_생성용_키
    -
    -

    config 파일 생성

    -

    마찬가지로 최상단에 config.json 파일을 생성한다. -설정 파일은 해당 링크를 참고한다.
    -또는 Docusaurus의 설정 파일을 참고한다.

    -
    {
    -  "index_name": "teco",
    -  "start_urls": [
    -    "https://teco-chat.github.io/"
    -  ],
    -  "sitemap_urls": [
    -    "https://teco-chat.github.io/sitemap.xml"
    -  ],
    -  "sitemap_alternate_links": true,
    -  "stop_urls": [
    -    "/tests"
    -  ],
    -  "selectors": {
    -    "lvl0": {
    -      "selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",
    -      "type": "xpath",
    -      "global": true,
    -      "default_value": "Documentation"
    -    },
    -    "lvl1": "header h1",
    -    "lvl2": "article h2",
    -    "lvl3": "article h3",
    -    "lvl4": "article h4",
    -    "lvl5": "article h5, article td:first-child",
    -    "lvl6": "article h6",
    -    "text": "article p, article li, article td:last-child"
    -  },
    -  "strip_chars": " .,;:#",
    -  "custom_settings": {
    -    "separatorsToIndex": "_",
    -    "attributesForFaceting": [
    -      "language",
    -      "version",
    -      "type",
    -      "docusaurus_tag"
    -    ],
    -    "attributesToRetrieve": [
    -      "hierarchy",
    -      "content",
    -      "anchor",
    -      "url",
    -      "url_without_anchor",
    -      "type"
    -    ]
    -  },
    -  "conversation_id": [
    -    "833762294"
    -  ],
    -  "nb_hits": 46250
    -}
    -
    -

    docker 이용하여 크롤링

    -

    docker와 jq가 필요하다.
    -jq가 설치되어 있지 않으면 mac 기준 brew를 이용해서 설치할 수 있다.

    -
    brew install jq
    -
    -

    다음 명령어를 이용하여 .env와 config.json을 이용하여 크롤링을 한다.

    -
    docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper
    -
    -

    docusaurus 설정

    -

    전에 확인한 APP ID, Search-Only API KEY, IndexName을 이용하여 docusaurus.config 파일에 설정한다.

    -
    themeConfig:
    -  /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    -  ({
    -    ...
    -    algolia: {
    -      appId: 'MVIU5UEMOM', // Application ID
    -      apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key
    -      indexName: 'teco', // config.json에 설정한 인덱스명
    -      contextualSearch: true,
    -    },
    -  })
    -
    -

    부가 설정

    -

    화면 상단 Github Icon

    -

    파일 최하단에 아래 css 구문을 추가한다.

    -
    .header-github-link:hover {
    -  opacity: 0.6;
    -}
    -
    -.header-github-link:before {
    -  content: '';
    -  width: 24px;
    -  height: 24px;
    -  display: flex;
    -  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
    -    no-repeat;
    -}
    -
    -html[data-theme='dark'] .header-github-link:before {
    -  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
    -    no-repeat;
    -}
    -
    -

    themeconfig -> navbar에 github link를 설정한다.

    -
    navbar: {
    -  title: 'HELLO',
    -  items: [
    -    {
    -        href: 'https://github.com/greeng00se',
    -        position: 'right',
    -        className: 'header-github-link',
    -        'aria-label': 'GitHub repository',
    -    },
    -  ],
    -},
    -
    -

    코드블럭

    -

    java나 kotlin의 경우 기본적으로 하이라이팅을 지원해 주지 않는다.
    -prism 설정을 아래와 같이 변경해 준다.

    -
    prism: {
    -  theme: lightCodeTheme,
    -  darkTheme: darkCodeTheme,
    -  additionalLanguages: ['java', 'kotlin'],
    -}
    -
    -

    mermaid

    -

    mermaid를 사용하려면 @docusaurus/theme-mermaid 를 설치해야 한다.

    -
    yarn add @docusaurus/theme-mermaid
    -
    -

    설치 후 아래와 같이 설정을 추가한다.

    -
    const config = {
    -  ...
    -  markdown: {
    -    mermaid: true,
    -  },
    -  themes: [
    -    '@docusaurus/theme-mermaid'
    -  ],
    -};
    -
    -

    themeConfig에서 mermaid의 테마를 지정할 수 있다.

    -
    themeConfig:
    -    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    -    ({
    -      ...
    -      mermaid: {
    -        theme: {
    -          light: 'neutral', 
    -          dark: 'dark'
    -        },
    -      },
    -    }),
    -
    -

    국제화 설정

    -

    국제화 설정을 한다면 Older Entries 형태의 설명이 다음 페이지 로 변경된다.
    -설정파일에서 i18n에 있는 로케일 설정을 ko로 변경하면 된다.

    -
    i18n: {
    -  defaultLocale: "ko",
    -  locales: ["ko"],
    -},
    -
    -

    블로그 글 author

    -

    팀원 별로 문서를 관리한다면 다음과 같이 어떤 팀원이 글을 작성했는지 설정해야 한다.

    -

    author

    -

    authors.yml 파일을 이용하여 사용자에 대한 기본 설정을 할 수 있다.

    -
    herb:
    -  name: 허브
    -  title: Backend
    -  url: https://github.com/greeng00se
    -  image_url: https://github.com/greeng00se.png
    -
    -mallang:
    -  name: 말랑
    -  title: Backend
    -  url: https://github.com/shin-mallang
    -  image_url: https://github.com/shin-mallang.png
    -
    -

    블로그 글을 작성할 때 다음과 같이 authors에 넣어주기만 하면 된다.

    -
    ---
    -slug: 1
    -title: Hello World
    -authors: [herb, mallang]
    -tags: [hello, docusaurus]
    ----
    -
    -첫 번째 문서 내용
    -
    +

    · 약 6분

    InnoDB 스토리지 엔진의 잠금

    +

    MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
    +보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

    +

    동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
    +InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

    +

    트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

    +

    트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
    +일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

    +

    Shared & Exclusive Locks

    +

    InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

    +

    공유 잠금(S, shared lock)

    +

    데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
    +다른 트랜잭션에서 읽기가 가능하지만, 쓰기는 불가능하다.
    +예) SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;

    +

    배타적 잠금(X, exclusive lock)

    +

    데이터 변경을 위한 락, 쓰기 잠금(write lock)으로도 불린다.
    +락을 건 트랜잭션만이 해당 데이터에 접근 가능하다. 다른 트랜잭션의 경우 읽기, 쓰기가 불가능하다.
    +예) SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

    +

    Intention Locks

    +

    InnoDB는 로우 단위 잠금과 테이블 잠금의 공존을 위해 인텍션 잠금을 지원한다.
    +테이블에 있는 로우에 대해서 나중에 요청되는 것이 어떤 형태의 잠금인지 가리키기 위해 사용된다.
    +기본적으로 로우 단위 잠금을 수행하기 전에 인텐션 잠금을 먼저 획득한다.
    +인텐션 락은 기본적으로 충돌을 방지하고 데드락을 방지하는 역할을 한다.

    +

    인텐션 공유 잠금(IS, intention shared lock)

    +

    트랜잭션이 테이블의 개별 로우에 대한 공유 잠금을 수행하는 것을 의미한다.

    +

    인텐션 배타적 잠금(IX, intention exclusive lock)

    +

    트랜잭션이 테이블의 개별 로우에 대한 배타적 잠금을 수행하는 것을 의미한다.

    +

    ** 잠금간의 호환성 **

    +
    XIXSIS
    XConflictConflictConflictConflict
    IXConflictCompatibleConflictCompatible
    SConflictConflictCompatibleCompatible
    ISConflictCompatibleCompatibleCompatible
    +

    Record Locks

    +

    레코드 자체만을 잠그는 락이다.
    +InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다.

    +

    Gap Locks

    +

    레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    +레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하고, 넥스트 키 락의 일부로 사용된다.

    +

    Next-Key Locks

    +

    레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.
    +REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하기 위한 잠금이다.

    +

    AUTO-INC Locks

    +

    AUTO_INCREMENT 칼림이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 한다.
    +InnoDB 는 내부적으로 AUTO-INC 락이라고 하는 테이블 수준의 잠금을 사용한다.
    +트랜잭션과 관계 없이 INSERTREPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 해제된다.

    +

    잠금 예시

    +
    -- 레코드는 id 기준 10, 20, 30, 40, 50이 있다고 가정
    +-- Record Locks: 10에 대해 락이 걸린다.
    +SELECT * FROM table_name where id = 10 for update;
    +
    +-- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다.
    +SELECT * FROM table_name where id > 100 for update;
    +
    +-- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다.
    +SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;
    +
    +

    참고 자료

    +

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    +Optimistic and Pessimistic record locking, IBM
    +MySQL Innodb Locks, cecil1018
    +MySQL 8.0 InnoDB Locks, MySQL
    +Locks Set by Different SQL Statements in InnoDB, MySQL

    \ No newline at end of file diff --git a/page/2.html b/page/2.html index c5838c58d..2d0bebdb2 100644 --- a/page/2.html +++ b/page/2.html @@ -13,93 +13,37 @@ - - + + -

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
    -2단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358
    -3단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448
    -4단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515

    -

    Jdbc 구현

    -

    이번 미션은 Jdbc 라이브러리를 구현하고, Transaction 경계 설정과 동기화하는 부분을 구현해 보는 미션이었다.
    -미션 목표는 다음과 같다.

    -
      -
    • JDBC 라이브러리를 구현하면서 중복을 제거하는 연습을 한다.
    • -
    • 데이터베이스에 대한 이해도를 높인다.
    • -
    -

    최대한 Java가 제공하는 기능을 사용하여 리팩터링 하는 방향으로 코드를 작성했다.

    -

    JdbcTemplate

    -

    JdbcTemplate은 Connection을 이용하여 PreparedStatement를 생성하는 부분, 그리고 PreparedStatement가 어떻게 동작하는지에 대한 부분을 분리했다.
    -템플릿 콜백 패턴을 적절하게 적용하여 중복을 비교적 간단하게 제거할 수 있었다.
    -예전에도 미션을 진행하면서 JdbcTemplate을 구현한 적이 있었는데, 이번에는 자원 할당과 해제 부분에 대한 중복도 제거했다.

    -
    public class JdbcTemplate {
    -
    -    private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);
    -
    -    private final DataSource dataSource;
    -    private final StatementCreator statementCreator;
    -    private final StatementExecutor statementExecutor;
    -
    -    public JdbcTemplate(final DataSource dataSource) {
    -        this(dataSource, new StatementCreator(), new StatementExecutor());
    -    }
    -
    -    JdbcTemplate(
    -            final DataSource dataSource,
    -            final StatementCreator statementCreator,
    -            final StatementExecutor statementExecutor
    -    ) {
    -        this.dataSource = dataSource;
    -        this.statementCreator = statementCreator;
    -        this.statementExecutor = statementExecutor;
    -    }
    -
    -    private <T> T query(
    -            final String sql,
    -            final PreparedStatementCallback<T> preparedStatementCallback,
    -            final Object... parameters
    -    ) {
    -        final Connection connection = DataSourceUtils.getConnection(dataSource);
    -        try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {
    -            return preparedStatementCallback.execute(preparedStatement);
    -        } catch (final SQLException e) {
    -            log.error(e.getMessage(), e);
    -            throw new DataAccessException(e);
    -        } finally {
    -            DataSourceUtils.releaseConnection(connection, dataSource);
    -        }
    -    }
    -
    -    public void update(final String sql, final Object... parameters) {
    -        query(sql, PreparedStatement::executeUpdate, parameters);
    -    }
    -
    -    public <T> Optional<T> queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
    -        final List<T> results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
    -        if (results.size() > 1) {
    -            throw new DataAccessException("2개 이상의 결과를 반환할 수 없습니다.");
    -        }
    -        return results.stream().findAny();
    -    }
    -
    -    public <T> List<T> queryForList(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
    -        return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
    -    }
    -}
    -
    -

    트랜잭션 적용

    -

    3, 4단계는 기존의 코드에 트랜잭션을 시작하고 끝나는 부분인 트랜잭션 경계를 설정하고 ThreadLocal을 이용하여 트랜잭션 동기화(Transaction synchronization)를 적용하는 미션이었다.
    -트랜잭션 동기화란 트랜잭션을 시작하기 위한 Connection 객체를 ThreadLocal과 같은 공간에 따로 저장 후, 필요할 때 저장된 Connection을 가져다 사용하는 방식이다.
    -아래와 같은 구조로 미션을 진행했는데, ThreadLocal에 Connection 객체가 아닌, Connection 객체와 Transaction이 진행 중인지 확인할 수 있는 flag를 가지고 있는 클래스를 저장해서 사용하도록 했다.

    - -

    마무리

    -

    Jdbc 미션을 진행하면서 AOP나 Transactional에 대한 학습 테스트도 진행하고, 약간 알찬 미션이었던 것 같다.
    -꼼꼼히 코드를 봐준 리뷰어 호이 그리고 연휴 동안 계속 티키타카 하면서 재밌게 리뷰한 민트에게 감사하다.
    -회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

    +

    · 약 4분

    적당한 전환점, 2022년을 돌아보며

    +

    전역

    +

    약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
    +조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

    +

    조금 더 미래에 대한 생각을 해볼걸 그랬다.
    +전역을 했지만 뭐 하나 제대로 할 줄 아는 것도 없으니 넓은 바닷속에 덩그러니 놓아진 기분이 괜히 들었었다.
    +일찍 생각을 정리하여 방향을 잡지 못했기에 아쉬움이 많이 남았다.

    +

    자바

    +

    전역을 하고 진로를 고민하다 향로님의 자바 공화국 포스팅을 읽고 나서 자바 공부를 시작했다.
    +유명한 인프런의 김영한님의 스프링 강의도 있고, 좋은 자바 개발 서적이 많아서 독학하기로 결정했다.
    +하다 보니 자바와 스프링을 공부하면서 “왜 진작하지 않았지”라는 생각도 많이 들었다.
    +양질의 자료도 많았기 때문에, 예전에 노드로 개발했을 때 풀지 못했던 답답함을 많이 해소했던 것 같다.

    +

    23년에는 조금 더 깊게 자바를 공부해볼 생각이다.
    +언어를 하나 깊게 공부하는 건 많은 도움이 되는 것 같다.

    +

    스터디

    +

    김영한님의 강의를 거의 다 들었을 때쯤, 항상 강의에서 언급되는 토비의 스프링을 읽어보고 싶어졌고
    +혼자 공부하기에는 동기부여도 부족했기 때문에 스터디를 시작했다.
    +다른 사람에게 설명을 해야 했기 때문에 더욱 꼼꼼하게 공부를 할 수 있어서 좋았지만 나에게는 내용이 꽤나 어려워서 시간을 많이 소비했다.
    +같이 스터디하시는 분과 7개월 동안 스터디를 꾸준히 이어나가 총 3권의 책을 읽을 수 있었다.

    +

    우아한 테크코스

    +

    군 복무 중일 때 지원했다 떨어진 우아한 테크코스를 다시 지원했다.
    +이번 연도에 취업을 하는 게 목표였지만 내가 가지고 있는 특별한 무기가 없다는 걸 깨달았다.
    +적지 않은 시간을 투자해 준비를 했고, 감사하게도 이번에는 최종 합격을 했다.

    +

    난 사람들과 소통하고, 협업하는 능력이 부족하다고 생각을 많이 했다.
    +우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

    +

    2023년에는

    +

    마음의 여유가 없었던 2022년이었던 것 같다.
    +하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

    \ No newline at end of file diff --git a/page/20.html b/page/20.html index ce7f0043c..0bfe5ad37 100644 --- a/page/20.html +++ b/page/20.html @@ -13,31 +13,78 @@ - - + + -

    · 약 3분

    23년의 6월이 오고, 레벨 2가 끝났다.
    -빠르게 지나가서 조금 아쉽다.

    -

    학습

    -

    회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
    -항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
    -미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

    -

    고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
    -방학 그리고 레벨 3 때는 조금 더 이론적인 부분을 학습하는데 집중해야겠다.

    -

    점차 학습 범위가 넓어지면서 자연스럽게 모르는 내용이 쌓여간다.
    -필요한 내용은 앞으로 천천히 학습하면 되니까 조급해지지 말아야겠다.

    -

    수면

    -

    레벨 2를 진행하는 동안 수면이 많이 부족했었고, 결과적으로는 그날의 컨디션을 많이 좌우했던 것 같다.
    -앞으로 수면 시간을 늘리고, 좋은 수면 습관을 가지도록 노력해야겠다.

    -

    협업

    -

    레벨 2 마지막에 협업 미션이 있었다.
    -지금까지는 백엔드 크루들과 페어 프로그래밍을 하면서 협업을 경험했다.
    -이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

    -

    레벨 3 때부터 본격적으로 프로젝트가 시작된다.
    -팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

    -

    레벨 2를 마무리하며

    -

    회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. -읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

    +

    · 약 6분

    책 정보

    +
    +

    상자 밖에 있는 사람
    +아빈저연구소

    +
    +

    자기기만과 자기배반

    +

    책에서는 자기기만과 자기배반에 대한 내용을 다룬다.

    +
      +
    • 자기기만: 자신의 문제를 인정하지 않는 것
    • +
    • 자기배반: 다른 사람을 위해 무언가 해야만 한다는 생각을 반하는 행위
    • +
    +

    자기배반을 한다면 자기기만 상태가 된다.
    +자기기만 상태에 빠지는 것을 책에서는 상자 안에 들어간다고 표현한다.

    +

    읽고 나서

    +

    최근에 읽은 책 중 가장 마음이 불편했다.
    +그렇기에 더더욱 나에게 필요한 내용이 담겨있었다.

    +

    살면서 많은 선택의 순간이 존재했고, 그 순간마다 자기배반을 택하는 경우가 많았다.
    +작게는 집안일을 해야 하는데 몸이 조금 힘들다고 하지 않거나
    +크게는 잘못을 인정해야 하는 상황에서 그러지 않은 경우가 있었다.
    +이런 상황이 반복되어 결국 상자 안에 나 자신을 가두는 경우가 많았다.

    +

    더 나은 삶을 위해 내가 상자 안에 있는지 지속적으로 확인하고, 상자 밖으로 나가려는 연습을 해야겠다.
    +넓은 시선을 가지고, 항상 내가 틀릴 수 있다는 것을 생각하고 살아가자.

    +

    밑줄 친 문장들

    +
    +

    우리의 생각은 지식보다 작다.
    +우리의 지식은 사랑보다 작다.
    +우리의 사랑은 존재보다 작다.
    +그리고 우리가 생각하는 나는 실제의 나보다 그만큼 작다.
    +R. D. 랭
    +p.19

    +
    +
    +

    우리가 외적으로 어떤 행동을 하든지 간에, 사람들은 우리 마음에서 그들을 어떻게 대하고 있는지에 따라 주로 반응합니다.
    +우리가 사람들에 대해 어떻게 느끼게 되는지는 우리가 상자 안에 있는지 혹은 상자 밖에 있는지에 따라 달라지게 됩니다.
    +p.66

    +
    +
    +

    비난은 감정에 속하고 낙관은 의지에 속한다.
    +인간은 감정보다 더 큰 존재이다.
    +알랭, 탁닛한
    +p.103

    +
    +
    +

    우리가 자신에게만 집중하고 있는 한, 혼자서 일하는 것 이상의 창조적인 결과나 협력을 이끌어 낸다는 것은 불가능합니다.
    +오늘날 경제 환경에서는 혼자서는 일의 결과를 탁월하게 만들어 내기가 어렵습니다.
    +내가 중심이어야 된다는 폐쇄적인 사고는 함께 일하는 사람들의 열정을 불러오지 못합니다.
    +p.175

    +
    +
    +

    솔직함은 우리의 문제를 해결하는 열쇠입니다.
    +그것은 자신의 행동과 관련된 사람에 대해 기꺼이 사과를 하는 것입니다.
    +그것만이 실타래처럼 엉킨 관계의 문제를 해결할 수 있기 때문이죠.
    +p.188

    +
    +
    +

    누군가를 나와 같이 동일한 가치를 지닌 한 인간으로 생각해서 그 사람을 위해 내가 상자 밖에 계속 머무르고 싶은 열망이 생길 때, 나는 이미 그 사람에 대해 상자 밖에 있다.
    +p.214

    +
    +
    +

    대부분의 사람들이 관계 기술을 가지고 그들이 겪고 있는 문제를 바로잡으려고 하는 노력이 결실을 얻지 못하는 것은 결코 그러한 기술 부족 때문에 생기는 것이 아닙니다.
    +그것들은 자기배반 때문에 생겨납니다.
    +p.224

    +
    +
    +

    우리는 함께 일하고 우리와 함께 살아가는 사람이 진정으로 누구인지 알지 못합니다.
    +우리가 그들과 진정으로 함께 소통하기 전까지는 우리는 그들의 가치를 잘 모릅니다.
    +우리의 위대함이란 다른 사람들의 위대한 점을 발견해 주는 것에 있습니다.
    +p.280

    +
    \ No newline at end of file diff --git a/page/21.html b/page/21.html index eb181b3a2..360cb8f38 100644 --- a/page/21.html +++ b/page/21.html @@ -13,35 +13,63 @@ - - + + -

    · 약 4분

    레벨 인터뷰

    -

    레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
    -따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
    -이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
    -기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

    -

    API 문서 도구 선택

    -

    큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
    -백엔드 팀원이 함께 의사결정을 했고, 미션 기간이 짧은 만큼 팀 차원에서 비교적 학습하기 쉬운 Swagger를 선택했다.
    -추가로 들어가는 시간 대비 하이 리턴이라고 생각했다고 답변했다.

    -

    팀 차원의 학습 비용을 언급해서, 다음과 같은 좋은 피드백을 받았다.

    -
    -

    특히 팀으로 의사결정하는 과정을 공유해 준 점이 좋았고 기술적 의사결정 과정에서 팀의 학습비용을 고려한 점이 좋았음.
    -앞으로도 학습 비용은 주요하게 고려해야 할 사항

    -
    -

    PUT과 PATCH & 토큰과 세션

    -

    PUT과 PATCH 차이를 설명하는 부분에서는 PATCH를 사용할 때 페이로드가 적어진다는 내용을 빼먹고 답변을 했다.
    -토큰과 세션의 경우 기술을 잘 모르는 사람에게 설명해달라는 제약조건이 추가되었다.

    -

    해당 내용을 답변하면서 기술적인 깊이가 많이 부족했다는 생각이 든다.
    -실제로 레벨 2 때 이론적인 학습 시간이 매우 적었고, 집중력도 많이 부족했다.
    -앞으로 어떻게 깊이를 채울지 고민을 할 수 있는 질문들이었다.

    -

    추가로 기술을 잘 모르는 사람에게 설명하는 가정을 두고 학습을 한다면 큰 도움이 될 거라는 피드백을 받았다.

    -

    그 외 개선할 점

    -

    인터뷰할 때 특유의 말버릇을 개선하기
    -생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
    -기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
    -이전에 공부했던거 되돌아 보는 시간 가지기

    +

    · 약 6분

    4월 21일 금요일

    +

    레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
    +레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
    +단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
    +글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

    +

    나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
    +Chat-GPT 서비스를 크루들에게 제공하고, 해당 크루들이 질문한 내용을 공유할 수 있는 건 어떤지?

    +

    기술이 목적인 사이드 프로젝트를 진행하면 좋을 것 같다는 답변을 들었고, 혼자 아니면 페어할 수 있을 정도의 인원으로 진행하면 좋겠다고 하셨다.
    +프론트랑 간단하게 배포까지 해본 경험이 있어서 혼자해도 크게 어렵지 않을 것 같아서 혼자 하기로 마음을 먹었다.

    +

    이건 못참지

    +

    도메인 구입 성공?

    +

    커피챗이 끝나고 집으로 돌아가는 길에 바로 도메인을 구매하려고 namecheap에서 적당한 도메인이 없을까 검색을 계속했다.
    +마치 어릴 때 했던 게임 닉네임 정하는 것처럼 시간이 오래 걸렸다.
    +dev, io, chat 도메인이 후보였고 집 가는 길에 결정만 하다가 구매하지 못했다.

    +

    말랑의 DM

    +

    집에 가서 밥을 먹고 말랑이랑 DM 하다 프로젝트를 같이 하자는 이야기가 나왔다.
    +우테코 최고 고수 말랑의 요구라 수락하지 않으면 후폭풍을 감당할 수 없었다.

    +

    이런저런 대화를 나누다가 난 빠르게 프로토타입을 만들어 보고 싶어서 프론트를 구현한다고 했고, 말랑은 GPT api를 조사하기로 했다.
    +추가로 도메인에 관한 이야기를 하다가 woowachat이 언급되었고, namecheap에서 chat 도메인을 사용한 woowa.chat으로 구매했다.
    +이후에 teco.chat으로 변경했다!

    +

    도메인 설정 및 배포

    +

    토요일에 구매한 도메인을 CDN, 보안 등 다양한 기능을 제공하는 Cloudflare에 도메인 등록을 했다.
    +나에게 익숙한 Nuxt3를 사용하기로 했고, Cloudflare Pages를 이용하여 배포했다.

    +

    GPT

    +

    무료 크레딧을 사용하니 api limit이 있어 분당 3번밖에 사용할 수 없었다.
    +일단 백엔드를 구축하기 전에는 무료 크레딧을 사용할 생각이다.

    +

    Sonarcloud

    +

    정적 코드 분석 도구로 Sonarcloud를 적용했다.
    +Sonarcloud는 SonarQube의 SaaS 버전이고 사용이 매우 편하다.
    +예전에 Sonarcloud를 사용할 땐 버튼 몇 번 누르면 적용할 수 있었는데, 이번에는 바로 github action을 사용하라는 안내 페이지로 이동했다.
    +Sonarcloud가 자체적으로 github repository에 push 하면 정적 분석을 해주는 기능을 원했고, Administration -> Analysis Method에 Automatic Analysis를 설정하니 되었다.
    +너무 꽁꽁 숨겨져있네

    +

    Tiptap

    +

    코드 하이라이팅 기능을 넣고 싶어서 Tiptap을 사용했다.
    +Tiptap은 Headless WYSIWYG 에디터로 사용자 정의 기능에 특화되어있는 에디터다.
    +아직 Tiptap이 제공하는 모든 기능을 자연스럽게 사용하지는 못하지만 CodeBlockLowlight 플러그인을 사용하여 코드 블록을 예쁘게 출력할 수 있었다.
    +api 반환값 그대로 tiptap의 content에 설정했더니 코드 블록이 설정되지 않아서 백 틱 3개를 <pre><code>로 변환했다.
    +추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
    +변환하는 로직은 GPT의 도움을 많이 받았다.

    +
    const replaceCodeFences = (input: String) => {
    +    const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
    +    return input
    +        .replace(codeFencesRegex, (match, p1, p2) => {
    +        const languageClass = p1 ? ` class="language-${p1}"` : "";
    +        return `<pre><code${languageClass}>${p2}</code></pre>`;
    +        })
    +        .replace(/\n/g, "<br>");
    +};
    +
    +

    Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

    +

    tecochat

    +

    폰트 및 favicon 적용

    +

    타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
    +추가로 favicon도 간단하게 적용해서 만족스러웠다.

    \ No newline at end of file diff --git a/page/22.html b/page/22.html index 933e11cd2..358766671 100644 --- a/page/22.html +++ b/page/22.html @@ -13,76 +13,217 @@ - - + + -

    · 약 5분

    1단계: AWS 배포
    -2단계: https://github.com/woowacourse/jwp-shopping-order/pull/7

    -

    장바구니 주문 미션

    -

    배포 및 협업을 할 수 있는 미션이었다.
    -마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

    -

    배포

    -

    이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
    -각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
    -배포 스크립트를 작성하는 경험을 해볼 수 있었다.
    -배포 스크립트에 시간을 많이 투자하진 않았고, 다음과 같이 간단하게 작성했다.

    -
    echo "Start Deploy Script"
    -REPOSITORY_NAME=/home/ubuntu/jwp-shopping-order
    -PROJECT_NAME=jwp-shopping-order
    -
    -echo "Change Directory"
    -cd $REPOSITORY_NAME
    -
    -echo "Git Pull"
    -git pull origin step2
    -
    -echo "Build"
    -./gradlew bootJar
    -
    -echo "Copy, Start Server"
    -mv ./build/libs/$PROJECT_NAME.jar .
    -
    -PID=$(pgrep -f $PROJECT_NAME)
    -
    -if [ -n $PID ]; then
    -        kill -9 $PID
    -	sleep 5
    -fi
    -
    -nohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &
    +

    · 약 8분

    설정 환경

    +

    소프트웨어 이미지: Amazon Linux 2023 AMI
    +아키텍쳐: ARM
    +인스턴스 유형: t4g.small
    +환경 구성이 완료된 Elastic Beanstalk
    +단일 Spring Boot 프로젝트가 존재하는 Github Repository

    +

    [EC2 CLI] Swap 메모리 설정

    +

    t4g.small이 램이 2G인데 램이 부족하다고 느껴져서 swap 메모리를 설정했다.
    +아래 명령어를 따라 swap 메모리를 설정하고 free -h 명령어를 통해 잘 설정되었는지 확인할 수 있다.

    +
    # fallocate 이용하여 스왑 파일 생성
    +sudo fallocate -l 2G /swapfile
    +
    +# 권한 설정
    +sudo chmod 600 /swapfile
    +
    +# 파일을 Swap 포맷으로 변경 후 시스템에 등록
    +sudo mkswap /swapfile
    +sudo swapon /swapfile
    +
    +# Swap 메모리 부팅시 자동으로 마운트하도록 적용
    +# 최하단에 다음 구문 설정 -> /swapfile swap swap defaults 0 0
    +sudo vim /etc/fstab
     
    -

    협업

    -

    일단 우스랑 우코가 먼저 잠실로 와줘서 너무 감사했다.
    -백엔드가 아닌 다른 크루들과 해보는 첫 협업이라 약간 두근거렸다.
    -예상외로 대화가 잘 되어서, 빠르게 명세를 정할 수 있었다.

    -

    부족했던 부분

    -

    여러가지 방법에 대한 장단점을 고려해보기

    -

    백엔드와 테이블 명세나 쿠폰 구현에 대해서 이야기할 때 장단에 대해 많이 고려하지 못한 것 같다.
    -조금 더 시간을 많이 들여서 장단점을 고려했다면 더 좋은 결과물이 나오지 않았을까?
    -앞으로 선택의 순간에서 조금 더 시간을 들여보는 것도 좋을 것 같다.

    -

    새로 배운 부분

    -

    expose headers

    -

    웹 페이지에서 Location 헤더를 받을 수 없는 문제가 있었다.
    -기본적으로 허용 목록에 존재하는 응답헤더만 반환한다는 것을 모르고 있었다.
    -이를 expose headers 설정을 통해 해결할 수 있었다.
    -nginx 설정에 다음과 같이 추가해 주었다.

    -
    add_header 'Access-Control-Expose-Headers' 'Location'
    +

    [EC2 CLI] jenkins 설치

    +
    sudo wget -O /etc/yum.repos.d/jenkins.repo \
    +    https://pkg.jenkins.io/redhat-stable/jenkins.repo
    +sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
    +sudo yum upgrade
    +sudo yum install java-17-amazon-corretto-devel
    +sudo yum install jenkins
    +sudo systemctl daemon-reload
    +
    +

    Jenkins 공식 홈페이지 를 참고하여 설치하는 게 좋다.

    +

    [EC2 CLI] Jenkins 시작

    +
    sudo systemctl enable jenkins
    +sudo systemctl start jenkins
    +
    +

    enable로 설정하여 부팅시 자동시작 되도록 설정한다.

    +

    [EC2 CLI] nginx & git 설치

    +
    sudo yum install nginx
    +sudo systemctl enable nginx
    +sudo systemctl start nginx
    +
    +sudo yum install git
    +
    +

    nginx와 코드를 불러올 때 사용할 git을 설치한다.

    +

    [EC2 CLI] nginx 리버스 프록시 설정

    +

    아래 설정 파일은 공식 홈페이지에서 안내한 기본적인 설정 파일이다.

    +
    upstream jenkins {
    +  keepalive 32; # keepalive connections
    +  server 127.0.0.1:8080; # jenkins ip and port
    +}
    +
    +# Required for Jenkins websocket agents
    +map $http_upgrade $connection_upgrade {
    +  default upgrade;
    +  '' close;
    +}
    +
    +server {
    +  listen          80;       # Listen on port 80 for IPv4 requests
    +
    +  server_name     jenkins.example.com;  # replace 'jenkins.example.com' with your server domain name
    +
    +  # this is the jenkins web root directory
    +  # (mentioned in the output of "systemctl cat jenkins")
    +  root            /var/run/jenkins/war/;
    +
    +  access_log      /var/log/nginx/jenkins.access.log;
    +  error_log       /var/log/nginx/jenkins.error.log;
    +
    +  # pass through headers from Jenkins that Nginx considers invalid
    +  ignore_invalid_headers off;
    +
    +  location ~ "^/static/[0-9a-fA-F]{8}\/(.*)$" {
    +    # rewrite all static files into requests to the root
    +    # E.g /static/12345678/css/something.css will become /css/something.css
    +    rewrite "^/static/[0-9a-fA-F]{8}\/(.*)" /$1 last;
    +  }
    +
    +  location /userContent {
    +    # have nginx handle all the static requests to userContent folder
    +    # note : This is the $JENKINS_HOME dir
    +    root /var/lib/jenkins/;
    +    if (!-f $request_filename){
    +      # this file does not exist, might be a directory or a /**view** url
    +      rewrite (.*) /$1 last;
    +      break;
    +    }
    +    sendfile on;
    +  }
    +
    +  location / {
    +      sendfile off;
    +      proxy_pass         http://jenkins;
    +      proxy_redirect     default;
    +      proxy_http_version 1.1;
    +
    +      # Required for Jenkins websocket agents
    +      proxy_set_header   Connection        $connection_upgrade;
    +      proxy_set_header   Upgrade           $http_upgrade;
    +
    +      proxy_set_header   Host              $host;
    +      proxy_set_header   X-Real-IP         $remote_addr;
    +      proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
    +      proxy_set_header   X-Forwarded-Proto $scheme;
    +      proxy_max_temp_file_size 0;
    +
    +      #this is the maximum upload size
    +      client_max_body_size       10m;
    +      client_body_buffer_size    128k;
    +
    +      proxy_connect_timeout      90;
    +      proxy_send_timeout         90;
    +      proxy_read_timeout         90;
    +      proxy_buffering            off;
    +      proxy_request_buffering    off; # Required for HTTP CLI commands
    +      proxy_set_header Connection ""; # Clear for keepalive
    +  }
    +
    +}
     
    -

    읽기 전용 트랜잭션

    -

    단순 조회 요청에 대한 성능을 향상시켜준다는 것이라고 간단히만 알고 있었다.
    -이번에 코멘트가 달려서 조금 더 자세히 공부해 보기로 했다.
    -Transactional(readOnly = true)를 사용하는 경우 다음과 같이 동작한다.

    -

    setReadOnly(true) 설정이 된 Connection으로 연결을 시도를 한다. 이 설정을 하는 경우 DB마다 다르게 동작한다.

    +

    Jenkins는 8080 포트로 동작하기 때문에 리버스 프록시를 설정해준다.
    +/etc/nginx/conf.d 아래 default.conf 파일을 하나 생성하고 위와 같이 입력하고 저장한다.
    +nginx의 기본 설정 파일에 존재하는 include /etc/nginx/conf.d/*.conf; 설정 때문에 .conf 로 끝난다면 설정이 적용된다.
    +설정 후 sudo nginx -t로 설정파일이 정상인지 확인하고, sudo systemctl restart nginx 명령어로 nginx를 재시작한다.

    +

    [Jenkins] Jenkins 접속

    +

    Jenkins를 설치한 EC2 인스턴스 인바운드 설정에 80번 포트가 열려있는지 확인한다.
    +EC2의 아이피 주소를 입력하고 들어가면 비밀번호를 입력하라는 창이 나온다.

    +

    jenkins-start

    +

    초기 비밀번호를 입력해야 하는데 sudo cat /var/lib/jenkins/secrets/initialAdminPasswor 를 입력해 초기 비밀번호를 얻을 수 있다.
    +비밀번호를 입력하면 플러그인 설정 창이 나올텐데 install suggested plugins을 클릭하여 Jenkins가 추천하는 기본 플러그인들을 설치하면 된다.
    +플러그인을 설치하면 계정 및 주소 설정을 해야하는데 이건 편하게 설정하면 된다.

    +

    [Jenkins] Jenkins Blue Ocean 설치

    +

    Jenkins 관리 → Plugin Manager에서 Blue Ocean을 검색해 설치한다.

    +

    [AWS IAM & EC2] IAM으로 EC2 인스턴스 권한 설정하기

    +

    S3와 Elastic Beanstalk에 접근할 수 있는 권한을 부여하려면 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk 두 개의 정책을 가지고 있는 역할을 생성해야 한다.
    +IAM에서 다음과 같이 역할을 하나 새로 생성한다.

    +
      +
    1. 엔터티 선택
    2. +
    +

    aws-iam1

    +
      +
    1. 권한 추가
    2. +
    +

    aws-iam2

    +
      +
    1. 이름 지정, 검토 및 생성
    2. +
    +

    aws-iam3

    +
      +
    1. 생성한 IAM EC2 Jenkins 인스턴스를 선택하고, 작업 → 보안 → IAM 역할 수정을 눌러 Role 설정
    2. +
    +

    aws-iam4

    +

    [AWS S3] Jar 파일을 업로드 할 S3 버킷 생성

    +

    버킷을 생성할 때 다음 설정을 제외하고 모두 차단 활성화를 해준다.

      -
    • h2의 Connection 구현체는 readOnly 설정을 무시하는 방향으로 구현되어 Transactional 적용되지 않는다.
    • -
    • MySQL 8.0(InnoDB 사용 시)의 경우 읽기 전용으로 알려진 트랜잭션의 경우 트랜잭션 ID를 설정하지 않기 때문에 조회 속도가 더 빨라진다.
    • +
    • 새 ACL(액세스 제어 목록)을 통해 부여된 버킷 및 객체에 대한 퍼블릭 액세스 차단
    -

    ORM 프레임워크를 사용한다면 prepareTransactionalConnection를 호출한다고 한다.
    -추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

    -

    DAO에 @Transactional 적용

    -

    DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
    -Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
    -DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

    +

    aws-s3

    +

    [Github] Blue Ocean에서 파이프라인 생성에 필요한 Github Token 생성

    +

    repo, user:email 권한이 있는 토큰이 필요하다.

    +

    [Jenkins] 블루 오션 시작

    +

    jenkins-blue-ocean1

    +

    블루 오션 열기로 파이프라인을 생성한다.
    +토큰 입력 → 조직 선택 → CI/CD 설정할 Repository 선택을 하면 파이프라인 창으로 넘어간다.
    +Jenkinsfile을 직접 작성하여 설정하기 위해 간단하게 print 하나 출력하는 것으로 설정했다.

    +

    jenkins-blue-ocean2

    +

    파이프라인이 실행될 텐데 pipeline status에서 아래와 같이 초록불이 뜨면 된다.

    +

    jenkins-blue-ocean3

    +

    [Github Repsoitory] Jenkinsfile 설정

    +

    블루 오션 시작을 통해 설정하면 Jenkinsfile이 하나 만들어지고, 아래와 같이 원하는 파이프라인을 설정한다.

    +
    pipeline {
    +  agent any
    +  stages {
    +    stage('build and test') {
    +      steps {
    +        sh '/gradlew clean build'
    +      }
    +    }
    +    stage('zip') {
    +      steps {
    +        sh 'mv ./build/libs/woowachat.jar .'
    +        sh 'zip -r woowachat.zip .platform delivery.jar Procfile'
    +      }
    +    }
    +    stage('upload') {
    +      steps {
    +        sh 'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2'
    +      }
    +    }
    +    stage('deploy') {
    +      steps {
    +        sh 'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket="woowa-chat",S3Key="woowachat.zip"'
    +        sh 'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}'
    +      }
    +    }
    +  }
    +}
    +
    +

    [Github] Webhooks 설정

    +

    github-hook

    +

    push 이벤트가 발생할 때 http://Jenkins주소/github-webhook/ 로 post request를 하도록 웹훅을 설정한다.

    +

    참고 자료

    +

    Install Jenkins - CentOS, Jenkins
    +Nginx Reverse Proxy Configuration, Jenkins
    +Amazon Corretto 17 JDK Install, AWS
    +Amazon Linux 2023 packages, AWS

    \ No newline at end of file diff --git a/page/23.html b/page/23.html index 3031f88b7..10907354c 100644 --- a/page/23.html +++ b/page/23.html @@ -13,39 +13,54 @@ - - + + -

    · 약 5분

    개요

    -

    원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
    -레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

    -

    나의 채팅 확인하고 이어하는 기능

    -

    GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
    -예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

    -

    chat1

    -

    좋아요와 댓글 기능

    -

    다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
    -누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
    -또한 댓글 추가 및 삭제 기능도 추가했다.

    -

    키워드 추출

    -

    어떻게 키워드 추출을 할지 고민을 많이 했는데, 일단 GPT를 이용해서 키워드를 추출하기로 했다.
    -해당 부분은 첫 질문에 대한 키워드만 추출하도록 했다.
    -백엔드에선 말랑이 이벤트 이용해서 첫 채팅 요청이 이루어지면, 비동기로 키워드를 추출하는 질문을 추가로 날리도록 구현하였다.
    -CSV 형식으로 GPT에게 답변을 입력해달라고 요청받는데, 이 부분이 문제(프롬프트 엔지니어링 부분이 반환된다.)가 좀 있는 것 같아서 개선이 필요한 것 같다.

    -

    chat2

    -

    다른 크루의 채팅 복사해서 이어하는 기능

    -

    다른 크루들의 채팅을 읽다가 궁금한 점이 있다면 복사해서 바로 질문을 할 수 있는 기능을 추가했다.
    -채팅이 복사된 후 바로 GPT와 대화를 할 수 있는 메인 화면으로 이동한다.

    -

    사용성 고려하기

    -

    chat3

    -

    위 화면은 회원가입 창이다.
    -사실 가장 마음에 드는 부분이고, 회원가입(닉네임만 입력하지만)할 때 익명을 원하는 사람들의 고민을 도와주게 끔 음식, 과일, 과자 등의 요소들을 입력하도록 유도했다! -추가로 GPT의 답변이 오면 자동으로 화면을 스크롤 해주는 것과 같이 사용성을 개선해 보려고 노력했지만 쉽지 않았다.
    -제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

    -

    향후 계획

    -

    실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
    -크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
    -일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

    +

    · 약 5분

    프론트엔트

    +

    닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
    +추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
    +자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
    +여유가 된다면 자신의 채팅을 볼 수 있는 기능이나, 채팅을 이어서 할 수 있는 기능, 댓글 기능도 추가할 예정이다.

    +

    백엔드

    +

    최대한 빨리 서비스를 크루들에게 제공하기로 정해서, 백엔드는 말랑이 일단 다 만들고 있다.
    +말랑이 한 부분이 너무 많아서 내가 못 따라가는 것 같다.
    +나중에 백엔드 코드를 이해하는 시간을 가져야겠다.

    +

    Http Request Header

    +

    아직 인증에 대한 부분을 하지 않아서 요청 헤더에 이름을 보내기로 했다.
    +말랑이 한글은 안된다고 말해줘서 Base64로 인코딩하고, 백엔드에서 디코딩 하여 사용하기로 했다.
    +아래는 pinia에 있는 name 값을 인코딩 하는 코드다. deprecated 되었다는데, 다른 방법을 사용할 줄 몰라서 일단 이걸 사용했다.

    +
    const encodedName = () => {
    +  const uriComponent = unescape(encodeURIComponent(name.value));
    +  return btoa(uriComponent);
    +};
    +
    +

    Elastic Beanstalk

    +

    가장 빠르게 백엔드를 배포할 수 있는 방법이 뭘지 고민하다가 Elastic Beanstalk를 사용하기로 했다.
    +Elastic Beanstalk를 사용하면 인프라에 대해 잘 알지 못해도 애플리케이션을 빠르게 배포하고 관리할 수 있다.
    +모니터링, 로깅, 로드 밸런싱 등 다양한 기능을 제공한다.

    +

    Elastic Beanstalk RDS 설정 후 분리

    +

    초기 설정 시 RDS를 연결하고 설정 완료 후 분리한다면, Beanstalk 인스턴스 -> RDS 요청 시 인바운드 설정을 안 해도 된다.
    +RDS 분리 시 Beanstalk에 기본적으로 설정되어 있는 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD와 같은 환경 변수가 같이 제거된다.
    +추가로 Elastic Beanstalk로 RDS를 설정하면 기본 데이터베이스 명은 ebdb다.

    +

    Elastic Beanstalk nginx 설정

    +

    업로드하는 zip 파일 내부에 .platform/nginx/conf.d/ 경로에 설정 파일을 추가하면 nginx 설정을 할 수 있다.

    +

    Jenkins

    +

    백엔드 코드를 일일히 배포하기 불편해서 Jenkins를 이용하여 Repository에 코드를 push 할 때 자동으로 배포가 되게 설정하기로 했다.
    +작년에 확인했을 땐 2022년 12월 31일까지 EC2 ARM 기반 t4g.small이 무료였는데, 다시 들어가 보니 2023년까지 12월 31일까지 t4g.small을 무료로 사용할 수 있었다.
    +t4g.small은 램이 2G인데, 예전에는 부족하지 않았다고 생각했는데 Java 17을 써서 그런가 빌드 할 때 램이 많이 부족한 것 같아서 Swap 메모리 2기가를 추가로 설정했다.
    +추가로 build.gradle에서 아래와 같이 설정한다면 테스트 시 사용하는 램을 늘릴 수 있다. 기본값은 512MB라고 한다.

    +
    test {
    +    maxHeapSize = "1024m"
    +}
    +
    +

    Jenkins Blue Ocean

    +

    Blue Ocean은 Jenkins Pipeline을 구성하는 데에 있어 편리하게 해주는 도구다.
    +시각화도 잘 되어있고, 설정도 편리한 것 같다.
    +오늘 적용해 보니 램이 부족하여 중간에 잘 안되기도 하고 그래서 그냥 "Pipeline만 사용할 걸 그랬나?" 라는 생각이 든다.

    +

    참고 자료

    +

    Elastic Beanstalk, AWS
    +EC2 AWS Graviton, AWS
    +Default Memory Settings, AWS

    \ No newline at end of file diff --git a/page/24.html b/page/24.html index b3680fe6b..1afa62601 100644 --- a/page/24.html +++ b/page/24.html @@ -13,109 +13,49 @@ - - + + -

    · 약 5분

    요구사항

    -

    지하철 미션에는 다음과 같은 요구사항이 있었다.

    -
      -
    • 거리별 추가 요금 정책
    • -
    • 노선별 추가 요금 정책
    • -
    • 연령별 요금 할인 정책
    • -
    -

    인터페이스 사용

    -

    요금 정책은 다음과 같이 인터페이스로 표현할 수 있다.
    -요금을 계산하는 메서드는 최단 경로 계산의 결과, 사용자의 정보, 요금을 받아 요금을 계산한다.

    -
    public interface FarePolicy {
    -    int calculate(Path path, Passenger passenger, int fare);
    -}
    -
    -public class BaseFarePolicy implements FarePolicy { ... }
    -public class DistanceFarePolicy implements FarePolicy { ... }
    -public class AgeDiscountFarePolicy implements FarePolicy { ... }
    -
    -

    composite1

    -

    모든 요금 정책을 포함하는 새로운 요금 정책 만들기

    -

    나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
    -이 또한 FarePolicy를 구현한 형태가 되고, 필드로는 나머지 구현체들을 가지고 있다.

    -
    public class SubwayFarePolicy implements FarePolicy {
    -
    -    private final List<FarePolicy> farePolicies;
    -
    -    public SubwayFarePolicy(final List<FarePolicy> farePolicies) {
    -        this.farePolicies = farePolicies;
    -    }
    -
    -    @Override
    -    public int calculate(final Path path, final Passenger passenger, final int fare) {
    -        int calculatedFare = fare;
    -        for (FarePolicy farePolicy : farePolicies) {
    -            calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);
    -        }
    -        return calculatedFare;
    -    }
    -}
    -
    -

    따라서 그림으로 본다면 다음과 같은 구조가 된다.

    -

    composite2

    -

    정책의 순서

    -

    지하철 요구사항은 순서가 중요했다.
    -금액의 총합을 구하고, 그 후에 할인 정책이 들어가야했다.
    -따라서 자식들의 순서를 관리할 때 주의를 기울여야 했다.
    -Configuration 클래스에 다음과 같이 순서를 직접 적용시켰다.

    -
    @Configuration
    -public class FareConfiguration {
    -
    -    @Bean
    -    public FarePolicy farePolicy() {
    -        return new SubwayFarePolicy(List.of(
    -                new BaseFarePolicy(),
    -                new DistanceFarePolicy(),
    -                new AgeDiscountFarePolicy()
    -        ));
    -    }
    -}
    +

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-racingcar/pull/24
    +2단계: https://github.com/woowacourse/jwp-racingcar/pull/128

    +

    웹 자동차 미션

    +

    사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
    +웹 자동차 미션에서는 비버와 페어가 매칭되었다.
    +레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

    +

    스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
    +첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
    +난이도 높은 미션이 아니었지만 리뷰어인 라빈에게 칭찬을 많이 받아서 기분이 좋았다.
    +라빈 감사합니다!

    +

    부족했던 부분

    +

    컨디션도 좋지 않고 열정도 식은 것 같은 느낌이 들었다.
    +미션이 다소 여유롭다고 느껴져서, 시간에 대한 부분도 잘 관리하지 못한 것 같다.
    +미션에 잘 집중하지 못해서 페어에게 많이 미안했고, 나 자신에게 아쉬웠던 부분이 많았다.

    +

    지난번 회고를 다시 보는데 집중을 잘 못한 경우가 많은 것 같다.
    +도전적이지 않거나 시간이 부족하지 않으면 집중을 잘 못하는 것 같다.
    +머릿속에서 시간적 여유가 있다고 생각할 때가 가장 위험한 순간인 것 같다.

    +

    함께 자라기에서 나온 난이도 높이기가 필요해지는 순간이다.

    +

    새로 학습한 부분

    +

    중요도가 있는 어노테이션부터 클래스 이름에 가깝게 명시하기

    +
    @SuppressWarnings("NonAsciiCharacters")
    +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    +@Transactional
    +@AutoConfigureMockMvc
    +@SpringBootTest
    +public class RacingGameIntegrationTest {
     
    -

    컴포지트 패턴이란?

    -

    composite3

    -

    GOF의 디자인 패턴 책에서는 컴포지트 패턴을 다음과 같이 설명하고 있다.

    -
    -

    부분과 전체의 계층을 표현하기 위해 객체들을 모아 트리 구조로 구성합니다.
    -사용자로 하여금 개별 객체와 복합 객체를 모두 동일하게 다룰 수 있도록 하는 패턴입니다.

    -
    -

    컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
    -이 때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

    -

    컴포지트 패턴의 구성요소

    -

    Component

    -
      -
    • 집합 관계에 정의될 모든 객체에 대한 인터페이스
    • -
    • ex) 요금 정책(FarePolicy)
    • -
    -

    Leaf

    -
      -
    • 개별 객체, 객체 합성에 기본이 되는 객체의 행동
    • -
    • ex) 거리 별 요금 정책(DistanceFarePolicy)
    • -
    -

    Composite

    -
      -
    • 여러 개의 개발 객체를 포함하는 합성 객체
    • -
    • ex) 지하철 요금 정책(SubwayFarePolicy)
    • -
    -

    Client

    -
      -
    • 인터페이스를 사용하는 클라이언트
    • -
    -

    컴포지트 패턴의 사용과 주요 목표

    -

    부분 - 전체의 관계를 표현하고 싶을 때
    -Client 기준으로 Composite와 Leaf의 차이를 알지 못해도 잘 사용할 수 있도록 해야될 때

    -

    패턴 사용시 주의해야할 부분

    -

    패턴은 공통으로 사용 가능한 역할, 책임, 협력의 템플릿이다.
    -반복되는 문제를 효율적으로 해결할 수 있지만 패턴에 매몰되서는 안된다.
    -패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
    -항상 트레이드오프를 생각하자!

    -

    참고 자료

    -

    컴포지트 패턴, GoF의 디자인 패턴
    -디자인 패턴과 프레임워크, 오브젝트

    +

    페어에게 배울 부분

    +

    비버의 성격
    +비버가 성격이 좋아서 편하게 페어를 할 수 있었다.
    +미션을 진행하면서 성급하지 않고 여유로워서 좋았다.

    +

    미션에 집중하는 부분
    +내가 미션에 잘 집중하지 못했는데도 같이 페어를 잘 진행한 것 같아서 좋았다.
    +비버가 미션에 잘 집중해서 그렇지 않았나 생각했다.
    +근육맨 비버라 그런지 체력이 좋아서 그런가?
    +중간에 잘 안 쉬고도 집중해서 미션을 진행하는 걸 보고 대단하다고 생각했다.

    +

    학습에 대한 열정
    +추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
    +비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
    +나도 5월부터 조금 더 화이팅 해야겠다.

    \ No newline at end of file diff --git a/page/25.html b/page/25.html index d12c565eb..0d6870d74 100644 --- a/page/25.html +++ b/page/25.html @@ -13,85 +13,46 @@ - - + + -

    · 약 8분

    1단계: https://github.com/woowacourse/jwp-subway-path/pull/16
    -2, 3단계: https://github.com/woowacourse/jwp-subway-path/pull/126

    -

    지하철 미션

    -

    점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
    -지하철 미션은 밀리랑 페어를 진행했다.
    -간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
    -이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
    -API와 테이블 구조를 우리가 정할 수 있는 상황이었고, 도메인 로직이 복잡했기 때문에 도메인을 먼저 구현했다.

    -

    노선의 구간 추가 및 삭제

    -

    노선을 저장하는 방법에 대해서 밀리와 이야기를 나눴다.

    -
      -
    1. 구간을 데이터베이스에서 전부 제거하고 전부 추가하는 방법
    2. -
    3. 변경된 요소만 데이터베이스에 반영하는 방법
    4. -
    -

    페어 시간이 짧아서 더욱 간단한 1번을 선택했고, 시간 내 요구사항을 만족시키기 위해 더 간단하게 구현하는 방법을 선택하는 것도 좋은 트레이드오프였던 것 같다.
    -추후 페어가 끝나고 리뷰어인 서브웨이가 일부분만 반영하는 것으로 개선해 보는 것도 좋을 것 같다고 코멘트를 남겨주셔서 추가 및 제거된 요소만 반영하도록 변경했다.

    -

    부족했던 부분

    -

    미션의 난이도가 올라간 만큼, 페어 할 땐 컨디션 관리도 잘하려고 노력하고 미션 할 때도 집중해서 잘 끝낸 것 같다.
    -우아한테크코스를 진행하면서 알아야 하는 게 많아지면서 가끔 조바심을 가질 때가 있는 것 같은데, 조바심을 경계할 필요가 있을 것 같다.
    -부족한 부분은 인정하고, 앞으로 나아가야겠다.

    +

    · 약 5분

    1단계: https://github.com/woowacourse/jwp-shopping-cart/pull/244
    +2단계: https://github.com/woowacourse/jwp-shopping-cart/pull/300

    +

    웹 장바구니 미션

    +

    장바구니 미션은 블랙캣이랑 진행했다.
    +요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
    +2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
    +Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
    +이전에 스프링 사용할 때는 아무 생각 없이 코드를 작성하는 경우가 많았는데, 코드를 작성할 때 근거가 생기고 있는 것 같다.

    새로 학습한 부분

    -

    컴포지트 패턴으로 요금 정책 추상화

    -

    요금 정책은 기본요금 정책, 거리별 요금 정책, 연령별 할인 정책이 있었다.
    -요금을 더하는 부분과, 할인하는 부분이 있어서 이 둘을 분리할까 생각했지만, 이 정도 크기의 애플리케이션에서는 오히려 분리하지 않고 하나로 합치는 게 더 좋다고 생각했다.
    -또한 분리하지 않는다면 정책의 순서가 중요한데, 연령별 할인 정책을 마지막에 두어야 했기 때문에 책임 연쇄 패턴도 고려를 했지만 조금 더 간결해 보이는 컴포지트 패턴을 선택했다.

    -

    도메인에 특정 기술의 의존성을 분리

    -

    처음에 도메인 패키지에 jgrapht 라이브러리를 의존하고 있는 클래스를 두어서 도메인 패키지가 jgrapht와 강결합이 되어버렸다.
    -따라서 도메인 패키지 내에는 경로 검색에 대한 인터페이스를 두고, 세부 구현은 도메인 패키지 외부로 분리했다.
    -최대한 간결하게 구현한다고 생각을 해도, 이런 부분은 인터페이스를 두어 결합을 피하는 것이 좋을 것 같다.

    -

    컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
    -이때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

    -

    인수 테스트 작성

    -

    인수 테스트는 사용자 스토리 시나리오 기반 테스트다.
    -브라운이 해주신 강의 + 유튜브에 있는 브라운의 강의를 보고 지하철 미션에 인수 테스트를 적용해 보았다.
    -메서드, 변수명을 전부 한글로 작성했는데 전체적인 흐름을 알기 편하고 읽기도 좋았다.
    -그리고 인수 테스트에 필요한 Steps를 만드는 과정이 너무 재밌었다.

    -

    결과는 아래와 같다.

    -
    @Nested
    -public class 노선을_전체_조회할_때 {
    -
    -    @Test
    -    void 상행종점역_부터_하행종점역으로_정렬된_결과를_반환한다() {
    -        // given
    -        노선_생성_요청("2호선", "초록", 0);
    -        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("2호선", "잠실", "잠실새내", 5);
    -        구간_생성_요청("2호선", "잠실새내", "종합운동장", 오른쪽, 5);
    -
    -        노선_생성_요청("9호선", "고동", 0);
    -        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("9호선", "봉은사", "종합운동장", 3);
    -        구간_생성_요청("9호선", "종합운동장", "삼전", 오른쪽, 7);
    -
    -        // when
    -        final var 조회_결과 = 노선_전체_조회_요청();
    -
    -        // then
    -        요청_결과의_상태를_검증한다(조회_결과, 정상_요청);
    -        노선_전체_조회_결과를_확인한다(
    -                조회_결과,
    -                노선_정보("2호선", "초록", 0, "잠실", "잠실새내", "종합운동장"),
    -                노선_정보("9호선", "고동", 0, "봉은사", "종합운동장", "삼전")
    -        );
    -    }
    -}
    -
    +

    DTO 우발적 중복

    +

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.

    +

    dto1

    +

    클래스명을 제외하고 필드와 검증 로직 그 외 모든 게 같은 DTO를 보며 중복이라고 생각을 했고, 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
    +로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러 가지 종류로 나누어 설명하고 있다.

    +
      +
    • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
    • +
    • 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.
    • +
    +

    추가와 수정은 초기에는 중복으로 보이지만 초기 생성 시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다.
    +따라서 리뷰어 웨지가 아래와 같이 의존 역전을 이용하는 방법도 있다고 알려주셨다.

    +

    dto2

    +

    Interceptor에서 인증한 값 재사용

    +

    사실 조회를 두 번 하기 싫어서 다양한 방법을 생각했었는데 이번 미션에서는 ThreadLocal을 사용했다.
    +일단 Tomcat은 요청마다 다른 스레드를 사용하고, Interceptor에서 조회해서 만든 Credential을 ThreadLocal에 넣어두었다가 ArgumentResolver에서 꺼낸 다음 ThreadLocal을 clear 하면 문제가 없을 거라 판단했다.

    +

    리뷰어인 웨지에게도 어떤 방법을 사용할지 궁금증을 작성했었다.
    +웨지는 email에 index를 걸어두고 dao 재조회를 사용할 것이라고 했다.
    +재사용하지 않고 db에 인덱스를 걸 생각은 하지 못했는데, 제일 직관적이고 좋은 방법이라고 생각했다.

    페어에게 배울 부분

    -

    의견 조율하기

    -

    밀리가 필요한 부분에서 의견을 적극적으로 내줘서 진행이 수월했다.
    -의사소통이 매우 잘 돼서 좋았고 덕분에 시간 내에 요구사항을 만족해 미션을 제출할 수 있었던 것 같다.

    -

    꼼꼼하게 코딩하기

    -

    밀리는 코딩을 엄청 꼼꼼하게 하는 것 같다.
    -변수명, 메서드명을 중요하게 생각했고, 좋은 변수명을 잘 짓는 것 같다.
    -또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

    -

    편한 분위기

    -

    전체적으로 페어 할 때 편하게 진행했던 것 같다.
    -일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
    -나는 과연 다른 사람들에게 편한 사람일까?

    +

    기록

    +

    블랙캣은 기록을 굉장히 잘 하는 크루였다.
    +노션에 페어를 진행하면서 했던 내용 + 고민했던 부분 + 회고를 꼼꼼하게 기록해서 공유해 주었다.
    +추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

    +

    의견 일치시키기

    +

    페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
    +따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
    +블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

    +

    빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

    \ No newline at end of file diff --git a/page/26.html b/page/26.html index 744361db6..3b1db4bb8 100644 --- a/page/26.html +++ b/page/26.html @@ -13,11 +13,11 @@ - - + + -

    · 약 8분

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
    +

    · 약 8분

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
    요청에 담긴 Body를 통해 전달받은 값을 DTO로 매핑하여 추가와 수정을 했다.

    장바구니 미션에서의 상품 추가 및 수정

    중복1

    @@ -26,7 +26,7 @@

    장바구니 미 위 경우는 중복일까? 중복이 아닐까?

    이 부분에 대해서 다음과 같은 리뷰를 받았다.

    -

    ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

    +

    ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

    질문에 대해 아래와 같이 답변을 했다.

    @@ -43,7 +43,7 @@

    중복과 우발적 중복

    하나로 사용하는 건 안좋아보이고, 중복은 제거하고 싶은 마음

    지금은 추가, 수정 2가지 경우 밖에 없지만 조금 더 복잡한 요구사항이 주어져서 10가지 경우로 입력을 받으면 어떻게 해야할까?
    서비스 계층에서도 계층의 분리를 위해서 다른 DTO를 사용하고 있다면 20개의 DTO를 만들어야 할까?
    -리뷰어가 알려준 의존 역전을 이용한 방법을 통해 이를 해결해보자!

    +리뷰어가 알려준 의존 역전을 이용한 방법을 통해 이를 해결해보자!

    중복 제거 전 코드

    현재 코드에서는 아래와 같은 구조로 되어있다.
    Controller와 Service에서 저장, 수정할 때 각각의 DTO를 사용하고 있다. @@ -85,8 +85,8 @@

    인터페이스 작성하기

    구현체 작성하기

    중복4

    -

    위에서 작성한 인터페이스를 구현하는 클래스를 작성한다.
    -요청은 ProductRequest 클래스로 받고, 서비스에 전달할 땐 해당 인터페이스의 명세만 맞추면 문제없이 사용할 수 있다.

    +

    위에서 작성한 인터페이스를 구현하는 클래스를 작성한다.
    +요청은 ProductRequest 클래스로 받고, 서비스에 전달할 땐 해당 인터페이스의 명세만 맞추면 문제없이 사용할 수 있다.

    ├── controller
     │   ├── ProductController
     │   └── ProductRequest
    diff --git a/page/27.html b/page/27.html
    index d7ed635a3..ba58cc6ac 100644
    --- a/page/27.html
    +++ b/page/27.html
    @@ -13,46 +13,85 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    · 약 5분

    1단계: https://github.com/woowacourse/jwp-shopping-cart/pull/244
    -2단계: https://github.com/woowacourse/jwp-shopping-cart/pull/300

    -

    웹 장바구니 미션

    -

    장바구니 미션은 블랙캣이랑 진행했다.
    -요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
    -2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
    -Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
    -이전에 스프링 사용할 때는 아무 생각 없이 코드를 작성하는 경우가 많았는데, 코드를 작성할 때 근거가 생기고 있는 것 같다.

    -

    새로 학습한 부분

    -

    DTO 우발적 중복

    -

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.

    -

    dto1

    -

    클래스명을 제외하고 필드와 검증 로직 그 외 모든 게 같은 DTO를 보며 중복이라고 생각을 했고, 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
    -로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러 가지 종류로 나누어 설명하고 있다.

    -
      -
    • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
    • -
    • 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.
    • -
    -

    추가와 수정은 초기에는 중복으로 보이지만 초기 생성 시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다.
    -따라서 리뷰어 웨지가 아래와 같이 의존 역전을 이용하는 방법도 있다고 알려주셨다.

    -

    dto2

    -

    Interceptor에서 인증한 값 재사용

    -

    사실 조회를 두 번 하기 싫어서 다양한 방법을 생각했었는데 이번 미션에서는 ThreadLocal을 사용했다.
    -일단 Tomcat은 요청마다 다른 스레드를 사용하고, Interceptor에서 조회해서 만든 Credential을 ThreadLocal에 넣어두었다가 ArgumentResolver에서 꺼낸 다음 ThreadLocal을 clear 하면 문제가 없을 거라 판단했다.

    -

    리뷰어인 웨지에게도 어떤 방법을 사용할지 궁금증을 작성했었다.
    -웨지는 email에 index를 걸어두고 dao 재조회를 사용할 것이라고 했다.
    -재사용하지 않고 db에 인덱스를 걸 생각은 하지 못했는데, 제일 직관적이고 좋은 방법이라고 생각했다.

    +

    · 약 8분

    1단계: https://github.com/woowacourse/jwp-subway-path/pull/16
    +2, 3단계: https://github.com/woowacourse/jwp-subway-path/pull/126

    +

    지하철 미션

    +

    점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
    +지하철 미션은 밀리랑 페어를 진행했다.
    +간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
    +이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
    +API와 테이블 구조를 우리가 정할 수 있는 상황이었고, 도메인 로직이 복잡했기 때문에 도메인을 먼저 구현했다.

    +

    노선의 구간 추가 및 삭제

    +

    노선을 저장하는 방법에 대해서 밀리와 이야기를 나눴다.

    +
      +
    1. 구간을 데이터베이스에서 전부 제거하고 전부 추가하는 방법
    2. +
    3. 변경된 요소만 데이터베이스에 반영하는 방법
    4. +
    +

    페어 시간이 짧아서 더욱 간단한 1번을 선택했고, 시간 내 요구사항을 만족시키기 위해 더 간단하게 구현하는 방법을 선택하는 것도 좋은 트레이드오프였던 것 같다.
    +추후 페어가 끝나고 리뷰어인 서브웨이가 일부분만 반영하는 것으로 개선해 보는 것도 좋을 것 같다고 코멘트를 남겨주셔서 추가 및 제거된 요소만 반영하도록 변경했다.

    +

    부족했던 부분

    +

    미션의 난이도가 올라간 만큼, 페어 할 땐 컨디션 관리도 잘하려고 노력하고 미션 할 때도 집중해서 잘 끝낸 것 같다.
    +우아한테크코스를 진행하면서 알아야 하는 게 많아지면서 가끔 조바심을 가질 때가 있는 것 같은데, 조바심을 경계할 필요가 있을 것 같다.
    +부족한 부분은 인정하고, 앞으로 나아가야겠다.

    +

    새로 학습한 부분

    +

    컴포지트 패턴으로 요금 정책 추상화

    +

    요금 정책은 기본요금 정책, 거리별 요금 정책, 연령별 할인 정책이 있었다.
    +요금을 더하는 부분과, 할인하는 부분이 있어서 이 둘을 분리할까 생각했지만, 이 정도 크기의 애플리케이션에서는 오히려 분리하지 않고 하나로 합치는 게 더 좋다고 생각했다.
    +또한 분리하지 않는다면 정책의 순서가 중요한데, 연령별 할인 정책을 마지막에 두어야 했기 때문에 책임 연쇄 패턴도 고려를 했지만 조금 더 간결해 보이는 컴포지트 패턴을 선택했다.

    +

    도메인에 특정 기술의 의존성을 분리

    +

    처음에 도메인 패키지에 jgrapht 라이브러리를 의존하고 있는 클래스를 두어서 도메인 패키지가 jgrapht와 강결합이 되어버렸다.
    +따라서 도메인 패키지 내에는 경로 검색에 대한 인터페이스를 두고, 세부 구현은 도메인 패키지 외부로 분리했다.
    +최대한 간결하게 구현한다고 생각을 해도, 이런 부분은 인터페이스를 두어 결합을 피하는 것이 좋을 것 같다.

    +

    컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
    +이때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

    +

    인수 테스트 작성

    +

    인수 테스트는 사용자 스토리 시나리오 기반 테스트다.
    +브라운이 해주신 강의 + 유튜브에 있는 브라운의 강의를 보고 지하철 미션에 인수 테스트를 적용해 보았다.
    +메서드, 변수명을 전부 한글로 작성했는데 전체적인 흐름을 알기 편하고 읽기도 좋았다.
    +그리고 인수 테스트에 필요한 Steps를 만드는 과정이 너무 재밌었다.

    +

    결과는 아래와 같다.

    +
    @Nested
    +public class 노선을_전체_조회할_때 {
    +
    +    @Test
    +    void 상행종점역_부터_하행종점역으로_정렬된_결과를_반환한다() {
    +        // given
    +        노선_생성_요청("2호선", "초록", 0);
    +        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("2호선", "잠실", "잠실새내", 5);
    +        구간_생성_요청("2호선", "잠실새내", "종합운동장", 오른쪽, 5);
    +
    +        노선_생성_요청("9호선", "고동", 0);
    +        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("9호선", "봉은사", "종합운동장", 3);
    +        구간_생성_요청("9호선", "종합운동장", "삼전", 오른쪽, 7);
    +
    +        // when
    +        final var 조회_결과 = 노선_전체_조회_요청();
    +
    +        // then
    +        요청_결과의_상태를_검증한다(조회_결과, 정상_요청);
    +        노선_전체_조회_결과를_확인한다(
    +                조회_결과,
    +                노선_정보("2호선", "초록", 0, "잠실", "잠실새내", "종합운동장"),
    +                노선_정보("9호선", "고동", 0, "봉은사", "종합운동장", "삼전")
    +        );
    +    }
    +}
    +

    페어에게 배울 부분

    -

    기록

    -

    블랙캣은 기록을 굉장히 잘 하는 크루였다.
    -노션에 페어를 진행하면서 했던 내용 + 고민했던 부분 + 회고를 꼼꼼하게 기록해서 공유해 주었다.
    -추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

    -

    의견 일치시키기

    -

    페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
    -따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
    -블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

    -

    빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

    +

    의견 조율하기

    +

    밀리가 필요한 부분에서 의견을 적극적으로 내줘서 진행이 수월했다.
    +의사소통이 매우 잘 돼서 좋았고 덕분에 시간 내에 요구사항을 만족해 미션을 제출할 수 있었던 것 같다.

    +

    꼼꼼하게 코딩하기

    +

    밀리는 코딩을 엄청 꼼꼼하게 하는 것 같다.
    +변수명, 메서드명을 중요하게 생각했고, 좋은 변수명을 잘 짓는 것 같다.
    +또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

    +

    편한 분위기

    +

    전체적으로 페어 할 때 편하게 진행했던 것 같다.
    +일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
    +나는 과연 다른 사람들에게 편한 사람일까?

    \ No newline at end of file diff --git a/page/28.html b/page/28.html index 332aed923..328bac54b 100644 --- a/page/28.html +++ b/page/28.html @@ -13,49 +13,109 @@ - - + + -

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-racingcar/pull/24
    -2단계: https://github.com/woowacourse/jwp-racingcar/pull/128

    -

    웹 자동차 미션

    -

    사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
    -웹 자동차 미션에서는 비버와 페어가 매칭되었다.
    -레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

    -

    스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
    -첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
    -난이도 높은 미션이 아니었지만 리뷰어인 라빈에게 칭찬을 많이 받아서 기분이 좋았다.
    -라빈 감사합니다!

    -

    부족했던 부분

    -

    컨디션도 좋지 않고 열정도 식은 것 같은 느낌이 들었다.
    -미션이 다소 여유롭다고 느껴져서, 시간에 대한 부분도 잘 관리하지 못한 것 같다.
    -미션에 잘 집중하지 못해서 페어에게 많이 미안했고, 나 자신에게 아쉬웠던 부분이 많았다.

    -

    지난번 회고를 다시 보는데 집중을 잘 못한 경우가 많은 것 같다.
    -도전적이지 않거나 시간이 부족하지 않으면 집중을 잘 못하는 것 같다.
    -머릿속에서 시간적 여유가 있다고 생각할 때가 가장 위험한 순간인 것 같다.

    -

    함께 자라기에서 나온 난이도 높이기가 필요해지는 순간이다.

    -

    새로 학습한 부분

    -

    중요도가 있는 어노테이션부터 클래스 이름에 가깝게 명시하기

    -
    @SuppressWarnings("NonAsciiCharacters")
    -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    -@Transactional
    -@AutoConfigureMockMvc
    -@SpringBootTest
    -public class RacingGameIntegrationTest {
    +

    · 약 5분

    요구사항

    +

    지하철 미션에는 다음과 같은 요구사항이 있었다.

    +
      +
    • 거리별 추가 요금 정책
    • +
    • 노선별 추가 요금 정책
    • +
    • 연령별 요금 할인 정책
    • +
    +

    인터페이스 사용

    +

    요금 정책은 다음과 같이 인터페이스로 표현할 수 있다.
    +요금을 계산하는 메서드는 최단 경로 계산의 결과, 사용자의 정보, 요금을 받아 요금을 계산한다.

    +
    public interface FarePolicy {
    +    int calculate(Path path, Passenger passenger, int fare);
    +}
    +
    +public class BaseFarePolicy implements FarePolicy { ... }
    +public class DistanceFarePolicy implements FarePolicy { ... }
    +public class AgeDiscountFarePolicy implements FarePolicy { ... }
    +
    +

    composite1

    +

    모든 요금 정책을 포함하는 새로운 요금 정책 만들기

    +

    나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
    +이 또한 FarePolicy를 구현한 형태가 되고, 필드로는 나머지 구현체들을 가지고 있다.

    +
    public class SubwayFarePolicy implements FarePolicy {
    +
    +    private final List<FarePolicy> farePolicies;
    +
    +    public SubwayFarePolicy(final List<FarePolicy> farePolicies) {
    +        this.farePolicies = farePolicies;
    +    }
    +
    +    @Override
    +    public int calculate(final Path path, final Passenger passenger, final int fare) {
    +        int calculatedFare = fare;
    +        for (FarePolicy farePolicy : farePolicies) {
    +            calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);
    +        }
    +        return calculatedFare;
    +    }
    +}
    +
    +

    따라서 그림으로 본다면 다음과 같은 구조가 된다.

    +

    composite2

    +

    정책의 순서

    +

    지하철 요구사항은 순서가 중요했다.
    +금액의 총합을 구하고, 그 후에 할인 정책이 들어가야했다.
    +따라서 자식들의 순서를 관리할 때 주의를 기울여야 했다.
    +Configuration 클래스에 다음과 같이 순서를 직접 적용시켰다.

    +
    @Configuration
    +public class FareConfiguration {
    +
    +    @Bean
    +    public FarePolicy farePolicy() {
    +        return new SubwayFarePolicy(List.of(
    +                new BaseFarePolicy(),
    +                new DistanceFarePolicy(),
    +                new AgeDiscountFarePolicy()
    +        ));
    +    }
    +}
     
    -

    페어에게 배울 부분

    -

    비버의 성격
    -비버가 성격이 좋아서 편하게 페어를 할 수 있었다.
    -미션을 진행하면서 성급하지 않고 여유로워서 좋았다.

    -

    미션에 집중하는 부분
    -내가 미션에 잘 집중하지 못했는데도 같이 페어를 잘 진행한 것 같아서 좋았다.
    -비버가 미션에 잘 집중해서 그렇지 않았나 생각했다.
    -근육맨 비버라 그런지 체력이 좋아서 그런가?
    -중간에 잘 안 쉬고도 집중해서 미션을 진행하는 걸 보고 대단하다고 생각했다.

    -

    학습에 대한 열정
    -추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
    -비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
    -나도 5월부터 조금 더 화이팅 해야겠다.

    +

    컴포지트 패턴이란?

    +

    composite3

    +

    GOF의 디자인 패턴 책에서는 컴포지트 패턴을 다음과 같이 설명하고 있다.

    +
    +

    부분과 전체의 계층을 표현하기 위해 객체들을 모아 트리 구조로 구성합니다.
    +사용자로 하여금 개별 객체와 복합 객체를 모두 동일하게 다룰 수 있도록 하는 패턴입니다.

    +
    +

    컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
    +이 때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

    +

    컴포지트 패턴의 구성요소

    +

    Component

    +
      +
    • 집합 관계에 정의될 모든 객체에 대한 인터페이스
    • +
    • ex) 요금 정책(FarePolicy)
    • +
    +

    Leaf

    +
      +
    • 개별 객체, 객체 합성에 기본이 되는 객체의 행동
    • +
    • ex) 거리 별 요금 정책(DistanceFarePolicy)
    • +
    +

    Composite

    +
      +
    • 여러 개의 개발 객체를 포함하는 합성 객체
    • +
    • ex) 지하철 요금 정책(SubwayFarePolicy)
    • +
    +

    Client

    +
      +
    • 인터페이스를 사용하는 클라이언트
    • +
    +

    컴포지트 패턴의 사용과 주요 목표

    +

    부분 - 전체의 관계를 표현하고 싶을 때
    +Client 기준으로 Composite와 Leaf의 차이를 알지 못해도 잘 사용할 수 있도록 해야될 때

    +

    패턴 사용시 주의해야할 부분

    +

    패턴은 공통으로 사용 가능한 역할, 책임, 협력의 템플릿이다.
    +반복되는 문제를 효율적으로 해결할 수 있지만 패턴에 매몰되서는 안된다.
    +패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
    +항상 트레이드오프를 생각하자!

    +

    참고 자료

    +

    컴포지트 패턴, GoF의 디자인 패턴
    +디자인 패턴과 프레임워크, 오브젝트

    \ No newline at end of file diff --git a/page/29.html b/page/29.html index 917120565..3a664003f 100644 --- a/page/29.html +++ b/page/29.html @@ -13,54 +13,39 @@ - - + + -

    · 약 5분

    프론트엔트

    -

    닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
    -추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
    -자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
    -여유가 된다면 자신의 채팅을 볼 수 있는 기능이나, 채팅을 이어서 할 수 있는 기능, 댓글 기능도 추가할 예정이다.

    -

    백엔드

    -

    최대한 빨리 서비스를 크루들에게 제공하기로 정해서, 백엔드는 말랑이 일단 다 만들고 있다.
    -말랑이 한 부분이 너무 많아서 내가 못 따라가는 것 같다.
    -나중에 백엔드 코드를 이해하는 시간을 가져야겠다.

    -

    Http Request Header

    -

    아직 인증에 대한 부분을 하지 않아서 요청 헤더에 이름을 보내기로 했다.
    -말랑이 한글은 안된다고 말해줘서 Base64로 인코딩하고, 백엔드에서 디코딩 하여 사용하기로 했다.
    -아래는 pinia에 있는 name 값을 인코딩 하는 코드다. deprecated 되었다는데, 다른 방법을 사용할 줄 몰라서 일단 이걸 사용했다.

    -
    const encodedName = () => {
    -  const uriComponent = unescape(encodeURIComponent(name.value));
    -  return btoa(uriComponent);
    -};
    -
    -

    Elastic Beanstalk

    -

    가장 빠르게 백엔드를 배포할 수 있는 방법이 뭘지 고민하다가 Elastic Beanstalk를 사용하기로 했다.
    -Elastic Beanstalk를 사용하면 인프라에 대해 잘 알지 못해도 애플리케이션을 빠르게 배포하고 관리할 수 있다.
    -모니터링, 로깅, 로드 밸런싱 등 다양한 기능을 제공한다.

    -

    Elastic Beanstalk RDS 설정 후 분리

    -

    초기 설정 시 RDS를 연결하고 설정 완료 후 분리한다면, Beanstalk 인스턴스 -> RDS 요청 시 인바운드 설정을 안 해도 된다.
    -RDS 분리 시 Beanstalk에 기본적으로 설정되어 있는 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD와 같은 환경 변수가 같이 제거된다.
    -추가로 Elastic Beanstalk로 RDS를 설정하면 기본 데이터베이스 명은 ebdb다.

    -

    Elastic Beanstalk nginx 설정

    -

    업로드하는 zip 파일 내부에 .platform/nginx/conf.d/ 경로에 설정 파일을 추가하면 nginx 설정을 할 수 있다.

    -

    Jenkins

    -

    백엔드 코드를 일일히 배포하기 불편해서 Jenkins를 이용하여 Repository에 코드를 push 할 때 자동으로 배포가 되게 설정하기로 했다.
    -작년에 확인했을 땐 2022년 12월 31일까지 EC2 ARM 기반 t4g.small이 무료였는데, 다시 들어가 보니 2023년까지 12월 31일까지 t4g.small을 무료로 사용할 수 있었다.
    -t4g.small은 램이 2G인데, 예전에는 부족하지 않았다고 생각했는데 Java 17을 써서 그런가 빌드 할 때 램이 많이 부족한 것 같아서 Swap 메모리 2기가를 추가로 설정했다.
    -추가로 build.gradle에서 아래와 같이 설정한다면 테스트 시 사용하는 램을 늘릴 수 있다. 기본값은 512MB라고 한다.

    -
    test {
    -    maxHeapSize = "1024m"
    -}
    -
    -

    Jenkins Blue Ocean

    -

    Blue Ocean은 Jenkins Pipeline을 구성하는 데에 있어 편리하게 해주는 도구다.
    -시각화도 잘 되어있고, 설정도 편리한 것 같다.
    -오늘 적용해 보니 램이 부족하여 중간에 잘 안되기도 하고 그래서 그냥 "Pipeline만 사용할 걸 그랬나?" 라는 생각이 든다.

    -

    참고 자료

    -

    Elastic Beanstalk, AWS
    -EC2 AWS Graviton, AWS
    -Default Memory Settings, AWS

    +

    · 약 5분

    개요

    +

    원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
    +레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

    +

    나의 채팅 확인하고 이어하는 기능

    +

    GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
    +예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

    +

    chat1

    +

    좋아요와 댓글 기능

    +

    다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
    +누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
    +또한 댓글 추가 및 삭제 기능도 추가했다.

    +

    키워드 추출

    +

    어떻게 키워드 추출을 할지 고민을 많이 했는데, 일단 GPT를 이용해서 키워드를 추출하기로 했다.
    +해당 부분은 첫 질문에 대한 키워드만 추출하도록 했다.
    +백엔드에선 말랑이 이벤트 이용해서 첫 채팅 요청이 이루어지면, 비동기로 키워드를 추출하는 질문을 추가로 날리도록 구현하였다.
    +CSV 형식으로 GPT에게 답변을 입력해달라고 요청받는데, 이 부분이 문제(프롬프트 엔지니어링 부분이 반환된다.)가 좀 있는 것 같아서 개선이 필요한 것 같다.

    +

    chat2

    +

    다른 크루의 채팅 복사해서 이어하는 기능

    +

    다른 크루들의 채팅을 읽다가 궁금한 점이 있다면 복사해서 바로 질문을 할 수 있는 기능을 추가했다.
    +채팅이 복사된 후 바로 GPT와 대화를 할 수 있는 메인 화면으로 이동한다.

    +

    사용성 고려하기

    +

    chat3

    +

    위 화면은 회원가입 창이다.
    +사실 가장 마음에 드는 부분이고, 회원가입(닉네임만 입력하지만)할 때 익명을 원하는 사람들의 고민을 도와주게 끔 음식, 과일, 과자 등의 요소들을 입력하도록 유도했다! +추가로 GPT의 답변이 오면 자동으로 화면을 스크롤 해주는 것과 같이 사용성을 개선해 보려고 노력했지만 쉽지 않았다.
    +제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

    +

    향후 계획

    +

    실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
    +크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
    +일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

    \ No newline at end of file diff --git a/page/3.html b/page/3.html index ff2d2be69..f3e7251a2 100644 --- a/page/3.html +++ b/page/3.html @@ -13,95 +13,80 @@ - - + + -

    · 약 6분

    1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
    -2단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465
    -3단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580

    -

    MVC 구현

    -

    Reflection을 이용하여 Spring MVC와 유사한 기능을 구현하는 미션이었다.
    -미션의 목표는 다음과 같았다.

    +

    · 약 6분

    책 정보

    +
    +

    객체지향의 사실과 오해
    +조영호

    +
    +

    읽고 나서

    +

    조영호님의 오브젝트를 읽고 나서 다시 한 번 읽어보았다.
    +아직 이해가 안되는 부분이 많지만, 그래도 항상 새로움을 느낀다.
    +더할 나위 없이 휼륭한 객체지향 책이고, 조금 더 공부하고 다시 읽어봐야될 것 같다.

    +

    커피 전문점, 지하철 노선도, 이상한 나라의 엘리스를 예시로 든 설명이 너무 좋았고
    +좋은 내용을 담고 있지만 그렇다고 너무 무겁지 않아 가볍게 읽기도 좋은 것 같다.

    +

    책임의 자율성을 강조하는 이유 p.173

    +

    협력을 단순하게 만든다.

      -
    • MVC 프레임워크를 구현하면서 내부 동작 원리를 학습한다.
    • -
    • 점진적인 리팩토링을 경험한다.
    • +
    • 의도를 명확하게 표현 → 협력의 복잡함 저하
    • +
    • 책임의 추상화
    -

    미션의 목표와 더불어 각 클래스들이 역할과 책임을 적절히 가지도록 하고, 패키지의 의존 방향을 고민하면서 미션을 진행하는 것에 중점을 두었다.

    -

    애너테이션 기반 프레임워크 만들기

    -

    기존 코드에 ManualHandlerMapping이라는 서블릿을 직접 등록해서 사용하는 HandlerMapping 클래스가 있었고, 1단계에서는 애너테이션 기반의 AnnotationHandlerMapping을 구현해야 했기 때문에 @Controller, @RequestMapping을 Reflection을 이용하여 스캔하고, 핸들러 매핑을 등록하는 부분까지 진행해야 했다.
    -테오가 @GetMapping이나 @PostMapping 부분도 진행하면 재밌을 것 같다고 해서 같이 진행해 보았다.
    -추가로 미션 요구사항은 아니었지만 클래스 레벨에 적용된 @RequestMapping도 동작하도록 구현해보았다.

    - -

    다음과 같은 Flow로 Handler(실제 요청을 처리하는 메서드) 등록을 진행한다.

    -
      -
    1. @Controller가 적용된 클래스의 정보를 스캔하여 반환한다.
    2. -
    3. @Controller가 적용된 클래스의 @RequestMapping이 적용된 메서드들의 정보를 반환한다.
    4. -
    5. 각 메서드들을 순회하며 HandlerKey(uri + httpMethod 정보)와 HandlerExecution(인스턴스 + 실행하려는 메서드)을 생성하여 Map<HandlerKey, HandlerExecution>에 추가한다.
    6. -
    -

    AnnotationHandlerMapping의 initialize 메서드에서 Handler를 등록한다. 코드는 다음과 같다.

    -
    public void initialize() {
    -    if (!initialized.compareAndSet(false, true)) {
    -        return;
    -    }
    -
    -    final Map<Class<?>, ControllerInstance> controllers = annotationScanner.scanControllers();
    -    final Set<Method> methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());
    -    for (final Method method : methods) {
    -        final ControllerInstance controller = controllers.get(method.getDeclaringClass());
    -        final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);
    -        final List<HandlerKey> handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);
    -        handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));
    -    }
    -
    -    log.info("Initialized AnnotationHandlerMapping!");
    -    handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));
    -}
    -
    -

    Legacy MVC와 @MVC 통합

    -

    2단계는 Legacy MVC와 AnnotationHandlerMapping을 통합하는 부분이었다.
    -기존의 MVC와 애너테이션이 적용된 MVC 두 개를 같이 사용할 수 있어야 헀다.
    -대략적인 흐름은 다음과 같다.

    -
      -
    1. DispatcherServlet.service(request, response) 호출
    2. -
    3. HandlerMappings를 통해 입력받은 request에 해당하는 Handler 조회
    4. -
    5. HandlerAdapters를 통해 Handler를 실행시킬 수 있는 HandlerAdapter 조회
    6. -
    7. HandlerAdapter의.handle 메서드 실행
    8. -
    9. View의 render 호출
    10. -
    - -

    웹 애플리케이션 발전 과정

    -

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    -간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.

    - -

    내용이 길어져서 다음 문서에 정리했다.

    -

    추상적인 개념 학습 방법

    -

    직관적이지 않은 추상적인 개념을 학습할 때는 개념의 구현을 참고하면 학습에 도움이 된다고 한다.

    -
    개념구현
    OOPJava
    WASTomcat, Jetty
    IoCSpring BeanFactory, Servlet Container, Framework
    DISpring BeanFactory
    -

    정리

    -

    지금까지 스프링의 DispatcherServlet의 동작을 이론적으로만 알고 있었는데, 실제로 구현해 보니 조금 더 이해가 잘 가는 것 같다.
    -이번 미션에서 나의 리뷰어는 루카, 리뷰이는 헤나였다.
    -매 단계마다 꼼꼼하게 리뷰해 준 루카에게 너무 감사하고, 헤나에게 이상한 리뷰를 많이 남긴 것 같은데 꼼꼼히 반영해줘서 감사하다.
    -오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

    +

    외부와 내부를 명확하게 분리한다.

    +
      +
    • 요청하는 객체가 몰라도 되는 부분이 캡슐화됨으로 인터페이스와 구현의 분리
    • +
    +

    책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않는다.

    +
      +
    • 변경의 파급효과를 객체 내부로 캡슐화 → 메시지를 보내는 객체와의 결합도 저하
    • +
    +

    협력의 대상을 다양하게 선택할 수 있는 유연성을 제공한다.

    +
      +
    • 유연한 설계 → 재사용성 증가
    • +
    +

    객체의 역할을 이해하기 쉬워진다.

    +
      +
    • 응집도를 높은 상태로 유지
    • +
    +

    밑줄 친 문장들

    +
    +

    객체지향의 목표는 실세계를 모방하는 것이 아니다. +오히려 새로운 세계를 창조하는 것이다. +소프트웨어 개발자의 역할은 단순히 실세계를 소프트웨어 안으로 옮겨 담는 것이 아니라 고객과 사용자를 만족시킬 수 있는 신세계를 창조하는 것이다. +p.21

    +
    +
    +

    과거의 전통적인 개발 방법은 데이터와 프로세스를 엄격하게 구분한다. +이에 반해 객체지향에서는 데이터와 프로세스를 객체라는 하나의 틀 안에 함께 묶어 놓음으로써 객체의 자율성을 보장한다. +자율적인 객체로 구성된 공동체는 유지 보수가 쉽고 재사용이 용이한 시스템을 구축할 수 있는 가능성을 제시한다. +p.33

    +
    +
    +

    객체지향의 본질

    +

    시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법

    +

    자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.

    +

    객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.

    +

    객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다. +p.35

    +
    +
    +

    클래스의 구조와 메서드가 아니라 객체의 역할, 책임, 협력에 집중하라. +객체지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다. +p.38

    +
    +
    +

    객체지향에서 중요한 것은 동적으로 변하는 객체의 ‘상태’와 상태를 변경하는 ‘행위’다. +클래스는 타입을 구현하기 위해 프로그래밍 언어에서 제공하는 구현 메커니즘이라는 사실을 기억하라. +p.105

    +
    +
    +

    책임 주도 설계의 핵심은 어떤 행위가 필요한지를 먼저 결정한 후에 이 행위를 수행할 객체를 결정하는 것이다. +이 과정을 흔히 What/Who 사이클이라고 한다. +’어떤 행위(What)’를 수행할 것인지 결정한 후 ‘누가(who)’ 그 행위를 수행할 것인지 결정해야 한다. +여기서 ‘어떤 행위’가 바로 메시지다. +p.158

    +
    \ No newline at end of file diff --git a/page/30.html b/page/30.html index 2d851c607..25c880b81 100644 --- a/page/30.html +++ b/page/30.html @@ -13,217 +13,76 @@ - - + + -

    · 약 8분

    설정 환경

    -

    소프트웨어 이미지: Amazon Linux 2023 AMI
    -아키텍쳐: ARM
    -인스턴스 유형: t4g.small
    -환경 구성이 완료된 Elastic Beanstalk
    -단일 Spring Boot 프로젝트가 존재하는 Github Repository

    -

    [EC2 CLI] Swap 메모리 설정

    -

    t4g.small이 램이 2G인데 램이 부족하다고 느껴져서 swap 메모리를 설정했다.
    -아래 명령어를 따라 swap 메모리를 설정하고 free -h 명령어를 통해 잘 설정되었는지 확인할 수 있다.

    -
    # fallocate 이용하여 스왑 파일 생성
    -sudo fallocate -l 2G /swapfile
    -
    -# 권한 설정
    -sudo chmod 600 /swapfile
    -
    -# 파일을 Swap 포맷으로 변경 후 시스템에 등록
    -sudo mkswap /swapfile
    -sudo swapon /swapfile
    -
    -# Swap 메모리 부팅시 자동으로 마운트하도록 적용
    -# 최하단에 다음 구문 설정 -> /swapfile swap swap defaults 0 0
    -sudo vim /etc/fstab
    +

    · 약 5분

    1단계: AWS 배포
    +2단계: https://github.com/woowacourse/jwp-shopping-order/pull/7

    +

    장바구니 주문 미션

    +

    배포 및 협업을 할 수 있는 미션이었다.
    +마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

    +

    배포

    +

    이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
    +각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
    +배포 스크립트를 작성하는 경험을 해볼 수 있었다.
    +배포 스크립트에 시간을 많이 투자하진 않았고, 다음과 같이 간단하게 작성했다.

    +
    echo "Start Deploy Script"
    +REPOSITORY_NAME=/home/ubuntu/jwp-shopping-order
    +PROJECT_NAME=jwp-shopping-order
    +
    +echo "Change Directory"
    +cd $REPOSITORY_NAME
    +
    +echo "Git Pull"
    +git pull origin step2
    +
    +echo "Build"
    +./gradlew bootJar
    +
    +echo "Copy, Start Server"
    +mv ./build/libs/$PROJECT_NAME.jar .
    +
    +PID=$(pgrep -f $PROJECT_NAME)
    +
    +if [ -n $PID ]; then
    +        kill -9 $PID
    +	sleep 5
    +fi
    +
    +nohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &
     
    -

    [EC2 CLI] jenkins 설치

    -
    sudo wget -O /etc/yum.repos.d/jenkins.repo \
    -    https://pkg.jenkins.io/redhat-stable/jenkins.repo
    -sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
    -sudo yum upgrade
    -sudo yum install java-17-amazon-corretto-devel
    -sudo yum install jenkins
    -sudo systemctl daemon-reload
    -
    -

    Jenkins 공식 홈페이지 를 참고하여 설치하는 게 좋다.

    -

    [EC2 CLI] Jenkins 시작

    -
    sudo systemctl enable jenkins
    -sudo systemctl start jenkins
    -
    -

    enable로 설정하여 부팅시 자동시작 되도록 설정한다.

    -

    [EC2 CLI] nginx & git 설치

    -
    sudo yum install nginx
    -sudo systemctl enable nginx
    -sudo systemctl start nginx
    -
    -sudo yum install git
    -
    -

    nginx와 코드를 불러올 때 사용할 git을 설치한다.

    -

    [EC2 CLI] nginx 리버스 프록시 설정

    -

    아래 설정 파일은 공식 홈페이지에서 안내한 기본적인 설정 파일이다.

    -
    upstream jenkins {
    -  keepalive 32; # keepalive connections
    -  server 127.0.0.1:8080; # jenkins ip and port
    -}
    -
    -# Required for Jenkins websocket agents
    -map $http_upgrade $connection_upgrade {
    -  default upgrade;
    -  '' close;
    -}
    -
    -server {
    -  listen          80;       # Listen on port 80 for IPv4 requests
    -
    -  server_name     jenkins.example.com;  # replace 'jenkins.example.com' with your server domain name
    -
    -  # this is the jenkins web root directory
    -  # (mentioned in the output of "systemctl cat jenkins")
    -  root            /var/run/jenkins/war/;
    -
    -  access_log      /var/log/nginx/jenkins.access.log;
    -  error_log       /var/log/nginx/jenkins.error.log;
    -
    -  # pass through headers from Jenkins that Nginx considers invalid
    -  ignore_invalid_headers off;
    -
    -  location ~ "^/static/[0-9a-fA-F]{8}\/(.*)$" {
    -    # rewrite all static files into requests to the root
    -    # E.g /static/12345678/css/something.css will become /css/something.css
    -    rewrite "^/static/[0-9a-fA-F]{8}\/(.*)" /$1 last;
    -  }
    -
    -  location /userContent {
    -    # have nginx handle all the static requests to userContent folder
    -    # note : This is the $JENKINS_HOME dir
    -    root /var/lib/jenkins/;
    -    if (!-f $request_filename){
    -      # this file does not exist, might be a directory or a /**view** url
    -      rewrite (.*) /$1 last;
    -      break;
    -    }
    -    sendfile on;
    -  }
    -
    -  location / {
    -      sendfile off;
    -      proxy_pass         http://jenkins;
    -      proxy_redirect     default;
    -      proxy_http_version 1.1;
    -
    -      # Required for Jenkins websocket agents
    -      proxy_set_header   Connection        $connection_upgrade;
    -      proxy_set_header   Upgrade           $http_upgrade;
    -
    -      proxy_set_header   Host              $host;
    -      proxy_set_header   X-Real-IP         $remote_addr;
    -      proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
    -      proxy_set_header   X-Forwarded-Proto $scheme;
    -      proxy_max_temp_file_size 0;
    -
    -      #this is the maximum upload size
    -      client_max_body_size       10m;
    -      client_body_buffer_size    128k;
    -
    -      proxy_connect_timeout      90;
    -      proxy_send_timeout         90;
    -      proxy_read_timeout         90;
    -      proxy_buffering            off;
    -      proxy_request_buffering    off; # Required for HTTP CLI commands
    -      proxy_set_header Connection ""; # Clear for keepalive
    -  }
    -
    -}
    +

    협업

    +

    일단 우스랑 우코가 먼저 잠실로 와줘서 너무 감사했다.
    +백엔드가 아닌 다른 크루들과 해보는 첫 협업이라 약간 두근거렸다.
    +예상외로 대화가 잘 되어서, 빠르게 명세를 정할 수 있었다.

    +

    부족했던 부분

    +

    여러가지 방법에 대한 장단점을 고려해보기

    +

    백엔드와 테이블 명세나 쿠폰 구현에 대해서 이야기할 때 장단에 대해 많이 고려하지 못한 것 같다.
    +조금 더 시간을 많이 들여서 장단점을 고려했다면 더 좋은 결과물이 나오지 않았을까?
    +앞으로 선택의 순간에서 조금 더 시간을 들여보는 것도 좋을 것 같다.

    +

    새로 배운 부분

    +

    expose headers

    +

    웹 페이지에서 Location 헤더를 받을 수 없는 문제가 있었다.
    +기본적으로 허용 목록에 존재하는 응답헤더만 반환한다는 것을 모르고 있었다.
    +이를 expose headers 설정을 통해 해결할 수 있었다.
    +nginx 설정에 다음과 같이 추가해 주었다.

    +
    add_header 'Access-Control-Expose-Headers' 'Location'
     
    -

    Jenkins는 8080 포트로 동작하기 때문에 리버스 프록시를 설정해준다.
    -/etc/nginx/conf.d 아래 default.conf 파일을 하나 생성하고 위와 같이 입력하고 저장한다.
    -nginx의 기본 설정 파일에 존재하는 include /etc/nginx/conf.d/*.conf; 설정 때문에 .conf 로 끝난다면 설정이 적용된다.
    -설정 후 sudo nginx -t로 설정파일이 정상인지 확인하고, sudo systemctl restart nginx 명령어로 nginx를 재시작한다.

    -

    [Jenkins] Jenkins 접속

    -

    Jenkins를 설치한 EC2 인스턴스 인바운드 설정에 80번 포트가 열려있는지 확인한다.
    -EC2의 아이피 주소를 입력하고 들어가면 비밀번호를 입력하라는 창이 나온다.

    -

    jenkins-start

    -

    초기 비밀번호를 입력해야 하는데 sudo cat /var/lib/jenkins/secrets/initialAdminPasswor 를 입력해 초기 비밀번호를 얻을 수 있다.
    -비밀번호를 입력하면 플러그인 설정 창이 나올텐데 install suggested plugins을 클릭하여 Jenkins가 추천하는 기본 플러그인들을 설치하면 된다.
    -플러그인을 설치하면 계정 및 주소 설정을 해야하는데 이건 편하게 설정하면 된다.

    -

    [Jenkins] Jenkins Blue Ocean 설치

    -

    Jenkins 관리 → Plugin Manager에서 Blue Ocean을 검색해 설치한다.

    -

    [AWS IAM & EC2] IAM으로 EC2 인스턴스 권한 설정하기

    -

    S3와 Elastic Beanstalk에 접근할 수 있는 권한을 부여하려면 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk 두 개의 정책을 가지고 있는 역할을 생성해야 한다.
    -IAM에서 다음과 같이 역할을 하나 새로 생성한다.

    -
      -
    1. 엔터티 선택
    2. -
    -

    aws-iam1

    -
      -
    1. 권한 추가
    2. -
    -

    aws-iam2

    -
      -
    1. 이름 지정, 검토 및 생성
    2. -
    -

    aws-iam3

    -
      -
    1. 생성한 IAM EC2 Jenkins 인스턴스를 선택하고, 작업 → 보안 → IAM 역할 수정을 눌러 Role 설정
    2. -
    -

    aws-iam4

    -

    [AWS S3] Jar 파일을 업로드 할 S3 버킷 생성

    -

    버킷을 생성할 때 다음 설정을 제외하고 모두 차단 활성화를 해준다.

    +

    읽기 전용 트랜잭션

    +

    단순 조회 요청에 대한 성능을 향상시켜준다는 것이라고 간단히만 알고 있었다.
    +이번에 코멘트가 달려서 조금 더 자세히 공부해 보기로 했다.
    +Transactional(readOnly = true)를 사용하는 경우 다음과 같이 동작한다.

    +

    setReadOnly(true) 설정이 된 Connection으로 연결을 시도를 한다. 이 설정을 하는 경우 DB마다 다르게 동작한다.

      -
    • 새 ACL(액세스 제어 목록)을 통해 부여된 버킷 및 객체에 대한 퍼블릭 액세스 차단
    • +
    • h2의 Connection 구현체는 readOnly 설정을 무시하는 방향으로 구현되어 Transactional 적용되지 않는다.
    • +
    • MySQL 8.0(InnoDB 사용 시)의 경우 읽기 전용으로 알려진 트랜잭션의 경우 트랜잭션 ID를 설정하지 않기 때문에 조회 속도가 더 빨라진다.
    -

    aws-s3

    -

    [Github] Blue Ocean에서 파이프라인 생성에 필요한 Github Token 생성

    -

    repo, user:email 권한이 있는 토큰이 필요하다.

    -

    [Jenkins] 블루 오션 시작

    -

    jenkins-blue-ocean1

    -

    블루 오션 열기로 파이프라인을 생성한다.
    -토큰 입력 → 조직 선택 → CI/CD 설정할 Repository 선택을 하면 파이프라인 창으로 넘어간다.
    -Jenkinsfile을 직접 작성하여 설정하기 위해 간단하게 print 하나 출력하는 것으로 설정했다.

    -

    jenkins-blue-ocean2

    -

    파이프라인이 실행될 텐데 pipeline status에서 아래와 같이 초록불이 뜨면 된다.

    -

    jenkins-blue-ocean3

    -

    [Github Repsoitory] Jenkinsfile 설정

    -

    블루 오션 시작을 통해 설정하면 Jenkinsfile이 하나 만들어지고, 아래와 같이 원하는 파이프라인을 설정한다.

    -
    pipeline {
    -  agent any
    -  stages {
    -    stage('build and test') {
    -      steps {
    -        sh '/gradlew clean build'
    -      }
    -    }
    -    stage('zip') {
    -      steps {
    -        sh 'mv ./build/libs/woowachat.jar .'
    -        sh 'zip -r woowachat.zip .platform delivery.jar Procfile'
    -      }
    -    }
    -    stage('upload') {
    -      steps {
    -        sh 'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2'
    -      }
    -    }
    -    stage('deploy') {
    -      steps {
    -        sh 'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket="woowa-chat",S3Key="woowachat.zip"'
    -        sh 'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}'
    -      }
    -    }
    -  }
    -}
    -
    -

    [Github] Webhooks 설정

    -

    github-hook

    -

    push 이벤트가 발생할 때 http://Jenkins주소/github-webhook/ 로 post request를 하도록 웹훅을 설정한다.

    -

    참고 자료

    -

    Install Jenkins - CentOS, Jenkins
    -Nginx Reverse Proxy Configuration, Jenkins
    -Amazon Corretto 17 JDK Install, AWS
    -Amazon Linux 2023 packages, AWS

    +

    ORM 프레임워크를 사용한다면 prepareTransactionalConnection를 호출한다고 한다.
    +추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

    +

    DAO에 @Transactional 적용

    +

    DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
    +Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
    +DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

    \ No newline at end of file diff --git a/page/31.html b/page/31.html index 29f74a111..8352e7063 100644 --- a/page/31.html +++ b/page/31.html @@ -13,63 +13,35 @@ - - + + -

    · 약 6분

    4월 21일 금요일

    -

    레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
    -레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
    -단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
    -글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

    -

    나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
    -Chat-GPT 서비스를 크루들에게 제공하고, 해당 크루들이 질문한 내용을 공유할 수 있는 건 어떤지?

    -

    기술이 목적인 사이드 프로젝트를 진행하면 좋을 것 같다는 답변을 들었고, 혼자 아니면 페어할 수 있을 정도의 인원으로 진행하면 좋겠다고 하셨다.
    -프론트랑 간단하게 배포까지 해본 경험이 있어서 혼자해도 크게 어렵지 않을 것 같아서 혼자 하기로 마음을 먹었다.

    -

    이건 못참지

    -

    도메인 구입 성공?

    -

    커피챗이 끝나고 집으로 돌아가는 길에 바로 도메인을 구매하려고 namecheap에서 적당한 도메인이 없을까 검색을 계속했다.
    -마치 어릴 때 했던 게임 닉네임 정하는 것처럼 시간이 오래 걸렸다.
    -dev, io, chat 도메인이 후보였고 집 가는 길에 결정만 하다가 구매하지 못했다.

    -

    말랑의 DM

    -

    집에 가서 밥을 먹고 말랑이랑 DM 하다 프로젝트를 같이 하자는 이야기가 나왔다.
    -우테코 최고 고수 말랑의 요구라 수락하지 않으면 후폭풍을 감당할 수 없었다.

    -

    이런저런 대화를 나누다가 난 빠르게 프로토타입을 만들어 보고 싶어서 프론트를 구현한다고 했고, 말랑은 GPT api를 조사하기로 했다.
    -추가로 도메인에 관한 이야기를 하다가 woowachat이 언급되었고, namecheap에서 chat 도메인을 사용한 woowa.chat으로 구매했다.
    -이후에 teco.chat으로 변경했다!

    -

    도메인 설정 및 배포

    -

    토요일에 구매한 도메인을 CDN, 보안 등 다양한 기능을 제공하는 Cloudflare에 도메인 등록을 했다.
    -나에게 익숙한 Nuxt3를 사용하기로 했고, Cloudflare Pages를 이용하여 배포했다.

    -

    GPT

    -

    무료 크레딧을 사용하니 api limit이 있어 분당 3번밖에 사용할 수 없었다.
    -일단 백엔드를 구축하기 전에는 무료 크레딧을 사용할 생각이다.

    -

    Sonarcloud

    -

    정적 코드 분석 도구로 Sonarcloud를 적용했다.
    -Sonarcloud는 SonarQube의 SaaS 버전이고 사용이 매우 편하다.
    -예전에 Sonarcloud를 사용할 땐 버튼 몇 번 누르면 적용할 수 있었는데, 이번에는 바로 github action을 사용하라는 안내 페이지로 이동했다.
    -Sonarcloud가 자체적으로 github repository에 push 하면 정적 분석을 해주는 기능을 원했고, Administration -> Analysis Method에 Automatic Analysis를 설정하니 되었다.
    -너무 꽁꽁 숨겨져있네

    -

    Tiptap

    -

    코드 하이라이팅 기능을 넣고 싶어서 Tiptap을 사용했다.
    -Tiptap은 Headless WYSIWYG 에디터로 사용자 정의 기능에 특화되어있는 에디터다.
    -아직 Tiptap이 제공하는 모든 기능을 자연스럽게 사용하지는 못하지만 CodeBlockLowlight 플러그인을 사용하여 코드 블록을 예쁘게 출력할 수 있었다.
    -api 반환값 그대로 tiptap의 content에 설정했더니 코드 블록이 설정되지 않아서 백 틱 3개를 <pre><code>로 변환했다.
    -추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
    -변환하는 로직은 GPT의 도움을 많이 받았다.

    -
    const replaceCodeFences = (input: String) => {
    -    const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
    -    return input
    -        .replace(codeFencesRegex, (match, p1, p2) => {
    -        const languageClass = p1 ? ` class="language-${p1}"` : "";
    -        return `<pre><code${languageClass}>${p2}</code></pre>`;
    -        })
    -        .replace(/\n/g, "<br>");
    -};
    -
    -

    Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

    -

    tecochat

    -

    폰트 및 favicon 적용

    -

    타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
    -추가로 favicon도 간단하게 적용해서 만족스러웠다.

    +

    · 약 4분

    레벨 인터뷰

    +

    레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
    +따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
    +이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
    +기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

    +

    API 문서 도구 선택

    +

    큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
    +백엔드 팀원이 함께 의사결정을 했고, 미션 기간이 짧은 만큼 팀 차원에서 비교적 학습하기 쉬운 Swagger를 선택했다.
    +추가로 들어가는 시간 대비 하이 리턴이라고 생각했다고 답변했다.

    +

    팀 차원의 학습 비용을 언급해서, 다음과 같은 좋은 피드백을 받았다.

    +
    +

    특히 팀으로 의사결정하는 과정을 공유해 준 점이 좋았고 기술적 의사결정 과정에서 팀의 학습비용을 고려한 점이 좋았음.
    +앞으로도 학습 비용은 주요하게 고려해야 할 사항

    +
    +

    PUT과 PATCH & 토큰과 세션

    +

    PUT과 PATCH 차이를 설명하는 부분에서는 PATCH를 사용할 때 페이로드가 적어진다는 내용을 빼먹고 답변을 했다.
    +토큰과 세션의 경우 기술을 잘 모르는 사람에게 설명해달라는 제약조건이 추가되었다.

    +

    해당 내용을 답변하면서 기술적인 깊이가 많이 부족했다는 생각이 든다.
    +실제로 레벨 2 때 이론적인 학습 시간이 매우 적었고, 집중력도 많이 부족했다.
    +앞으로 어떻게 깊이를 채울지 고민을 할 수 있는 질문들이었다.

    +

    추가로 기술을 잘 모르는 사람에게 설명하는 가정을 두고 학습을 한다면 큰 도움이 될 거라는 피드백을 받았다.

    +

    그 외 개선할 점

    +

    인터뷰할 때 특유의 말버릇을 개선하기
    +생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
    +기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
    +이전에 공부했던거 되돌아 보는 시간 가지기

    \ No newline at end of file diff --git a/page/32.html b/page/32.html index 00de2d657..79c064a15 100644 --- a/page/32.html +++ b/page/32.html @@ -13,78 +13,31 @@ - - + + -

    · 약 6분

    책 정보

    -
    -

    상자 밖에 있는 사람
    -아빈저연구소

    -
    -

    자기기만과 자기배반

    -

    책에서는 자기기만과 자기배반에 대한 내용을 다룬다.

    -
      -
    • 자기기만: 자신의 문제를 인정하지 않는 것
    • -
    • 자기배반: 다른 사람을 위해 무언가 해야만 한다는 생각을 반하는 행위
    • -
    -

    자기배반을 한다면 자기기만 상태가 된다.
    -자기기만 상태에 빠지는 것을 책에서는 상자 안에 들어간다고 표현한다.

    -

    읽고 나서

    -

    최근에 읽은 책 중 가장 마음이 불편했다.
    -그렇기에 더더욱 나에게 필요한 내용이 담겨있었다.

    -

    살면서 많은 선택의 순간이 존재했고, 그 순간마다 자기배반을 택하는 경우가 많았다.
    -작게는 집안일을 해야 하는데 몸이 조금 힘들다고 하지 않거나
    -크게는 잘못을 인정해야 하는 상황에서 그러지 않은 경우가 있었다.
    -이런 상황이 반복되어 결국 상자 안에 나 자신을 가두는 경우가 많았다.

    -

    더 나은 삶을 위해 내가 상자 안에 있는지 지속적으로 확인하고, 상자 밖으로 나가려는 연습을 해야겠다.
    -넓은 시선을 가지고, 항상 내가 틀릴 수 있다는 것을 생각하고 살아가자.

    -

    밑줄 친 문장들

    -
    -

    우리의 생각은 지식보다 작다.
    -우리의 지식은 사랑보다 작다.
    -우리의 사랑은 존재보다 작다.
    -그리고 우리가 생각하는 나는 실제의 나보다 그만큼 작다.
    -R. D. 랭
    -p.19

    -
    -
    -

    우리가 외적으로 어떤 행동을 하든지 간에, 사람들은 우리 마음에서 그들을 어떻게 대하고 있는지에 따라 주로 반응합니다.
    -우리가 사람들에 대해 어떻게 느끼게 되는지는 우리가 상자 안에 있는지 혹은 상자 밖에 있는지에 따라 달라지게 됩니다.
    -p.66

    -
    -
    -

    비난은 감정에 속하고 낙관은 의지에 속한다.
    -인간은 감정보다 더 큰 존재이다.
    -알랭, 탁닛한
    -p.103

    -
    -
    -

    우리가 자신에게만 집중하고 있는 한, 혼자서 일하는 것 이상의 창조적인 결과나 협력을 이끌어 낸다는 것은 불가능합니다.
    -오늘날 경제 환경에서는 혼자서는 일의 결과를 탁월하게 만들어 내기가 어렵습니다.
    -내가 중심이어야 된다는 폐쇄적인 사고는 함께 일하는 사람들의 열정을 불러오지 못합니다.
    -p.175

    -
    -
    -

    솔직함은 우리의 문제를 해결하는 열쇠입니다.
    -그것은 자신의 행동과 관련된 사람에 대해 기꺼이 사과를 하는 것입니다.
    -그것만이 실타래처럼 엉킨 관계의 문제를 해결할 수 있기 때문이죠.
    -p.188

    -
    -
    -

    누군가를 나와 같이 동일한 가치를 지닌 한 인간으로 생각해서 그 사람을 위해 내가 상자 밖에 계속 머무르고 싶은 열망이 생길 때, 나는 이미 그 사람에 대해 상자 밖에 있다.
    -p.214

    -
    -
    -

    대부분의 사람들이 관계 기술을 가지고 그들이 겪고 있는 문제를 바로잡으려고 하는 노력이 결실을 얻지 못하는 것은 결코 그러한 기술 부족 때문에 생기는 것이 아닙니다.
    -그것들은 자기배반 때문에 생겨납니다.
    -p.224

    -
    -
    -

    우리는 함께 일하고 우리와 함께 살아가는 사람이 진정으로 누구인지 알지 못합니다.
    -우리가 그들과 진정으로 함께 소통하기 전까지는 우리는 그들의 가치를 잘 모릅니다.
    -우리의 위대함이란 다른 사람들의 위대한 점을 발견해 주는 것에 있습니다.
    -p.280

    -
    +

    · 약 3분

    23년의 6월이 오고, 레벨 2가 끝났다.
    +빠르게 지나가서 조금 아쉽다.

    +

    학습

    +

    회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
    +항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
    +미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

    +

    고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
    +방학 그리고 레벨 3 때는 조금 더 이론적인 부분을 학습하는데 집중해야겠다.

    +

    점차 학습 범위가 넓어지면서 자연스럽게 모르는 내용이 쌓여간다.
    +필요한 내용은 앞으로 천천히 학습하면 되니까 조급해지지 말아야겠다.

    +

    수면

    +

    레벨 2를 진행하는 동안 수면이 많이 부족했었고, 결과적으로는 그날의 컨디션을 많이 좌우했던 것 같다.
    +앞으로 수면 시간을 늘리고, 좋은 수면 습관을 가지도록 노력해야겠다.

    +

    협업

    +

    레벨 2 마지막에 협업 미션이 있었다.
    +지금까지는 백엔드 크루들과 페어 프로그래밍을 하면서 협업을 경험했다.
    +이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

    +

    레벨 3 때부터 본격적으로 프로젝트가 시작된다.
    +팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

    +

    레벨 2를 마무리하며

    +

    회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. +읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

    \ No newline at end of file diff --git a/page/33.html b/page/33.html index 376dcf039..69444888b 100644 --- a/page/33.html +++ b/page/33.html @@ -13,68 +13,358 @@ - - + + -

    · 약 6분

    InnoDB 스토리지 엔진의 잠금

    -

    MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
    -보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

    -

    동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
    -InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

    -

    트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

    -

    트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
    -일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

    -

    Shared & Exclusive Locks

    -

    InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

    -

    공유 잠금(S, shared lock)

    -

    데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
    -다른 트랜잭션에서 읽기가 가능하지만, 쓰기는 불가능하다.
    -예) SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;

    -

    배타적 잠금(X, exclusive lock)

    -

    데이터 변경을 위한 락, 쓰기 잠금(write lock)으로도 불린다.
    -락을 건 트랜잭션만이 해당 데이터에 접근 가능하다. 다른 트랜잭션의 경우 읽기, 쓰기가 불가능하다.
    -예) SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

    -

    Intention Locks

    -

    InnoDB는 로우 단위 잠금과 테이블 잠금의 공존을 위해 인텍션 잠금을 지원한다.
    -테이블에 있는 로우에 대해서 나중에 요청되는 것이 어떤 형태의 잠금인지 가리키기 위해 사용된다.
    -기본적으로 로우 단위 잠금을 수행하기 전에 인텐션 잠금을 먼저 획득한다.
    -인텐션 락은 기본적으로 충돌을 방지하고 데드락을 방지하는 역할을 한다.

    -

    인텐션 공유 잠금(IS, intention shared lock)

    -

    트랜잭션이 테이블의 개별 로우에 대한 공유 잠금을 수행하는 것을 의미한다.

    -

    인텐션 배타적 잠금(IX, intention exclusive lock)

    -

    트랜잭션이 테이블의 개별 로우에 대한 배타적 잠금을 수행하는 것을 의미한다.

    -

    ** 잠금간의 호환성 **

    -
    XIXSIS
    XConflictConflictConflictConflict
    IXConflictCompatibleConflictCompatible
    SConflictConflictCompatibleCompatible
    ISConflictCompatibleCompatibleCompatible
    -

    Record Locks

    -

    레코드 자체만을 잠그는 락이다.
    -InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다.

    -

    Gap Locks

    -

    레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    -레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하고, 넥스트 키 락의 일부로 사용된다.

    -

    Next-Key Locks

    -

    레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.
    -REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하기 위한 잠금이다.

    -

    AUTO-INC Locks

    -

    AUTO_INCREMENT 칼림이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 한다.
    -InnoDB 는 내부적으로 AUTO-INC 락이라고 하는 테이블 수준의 잠금을 사용한다.
    -트랜잭션과 관계 없이 INSERTREPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 해제된다.

    -

    잠금 예시

    -
    -- 레코드는 id 기준 10, 20, 30, 40, 50이 있다고 가정
    --- Record Locks: 10에 대해 락이 걸린다.
    -SELECT * FROM table_name where id = 10 for update;
    -
    --- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다.
    -SELECT * FROM table_name where id > 100 for update;
    -
    --- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다.
    -SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;
    -
    -

    참고 자료

    -

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    -Optimistic and Pessimistic record locking, IBM
    -MySQL Innodb Locks, cecil1018
    -MySQL 8.0 InnoDB Locks, MySQL
    -Locks Set by Different SQL Statements in InnoDB, MySQL

    +

    · 약 11분

    팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

    +

    설치

    +

    공식 홈페이지에 들어가서 최신 버전을 설치한다.

    +
    yarn create docusaurus
    +
    +

    배포

    +

    배포 안내 문서
    +netlify나 vercel 같은 서버리스 플랫폼을 추천하고 있고, 간단하고, 빠른 시간 안에 배포를 할 수 있다.
    +이 글에서는 github pages를 이용해서 배포하는 방법을 설명한다.

    +

    레포지토리 생성

    +

    github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
    +이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

    +

    설정 파일 수정

    +
    module.exports = {
    +  // ...
    +  url: 'https://greeng00se.github.io',
    +  baseUrl: '/',
    +  projectName: 'greeng00se.github.io',
    +  organizationName: 'greeng00se',
    +  trailingSlash: false,
    +  // ...
    +};
    +
    +

    토큰 설정

    +

    github action을 위해 배포용 토큰을 하나 생성하여 생성한 레포지토리에 Repository secrets으로 설정한다.
    +이 글에서는 토큰을 클래식 방식으로 생성했고 스코프는 [repo, user, workflow] 을 설정했다.

    +

    github

    +

    브랜치 생성

    +

    github에서 gh-pages 브랜치를 하나 생성한다.
    +repository -> settings -> pages -> branch에서 생성한 gh-pages로 브랜치를 변경한다.
    +설정한 브랜치가 배포 브랜치가 되며, 해당 브랜치에 있는 파일들을 이용해서 정적 웹사이트를 제공한다.

    +

    워크플로 작성

    +

    Docusaurus 2.0 기준 Node.js 16.14 이상의 버전을 사용해야 합니다.
    +배포시에는 Repository secrets으로 설정한 DEPLOY_TOKEN 을 이용합니다.

    +
    name: blog
    +
    +on:
    +  push:
    +    branches: [main]
    +
    +jobs:
    +  deploy:
    +    name: Deploy to GitHub Pages
    +    runs-on: ubuntu-latest
    +    steps:
    +      - uses: actions/checkout@v2
    +      - uses: actions/setup-node@v3
    +        with:
    +          node-version: 18
    +          cache: yarn
    +
    +      - name: Install dependencies
    +        run: yarn install --frozen-lockfile
    +      - name: Build website
    +        run: yarn build
    +
    +      - name: Deploy to GitHub Pages
    +        uses: peaceiris/actions-gh-pages@v3
    +        with:
    +          github_token: ${{ secrets.DEPLOY_TOKEN }}
    +          publish_dir: ./build
    +          user_name: github-actions[bot]
    +          user_email: 41898282+github-actions[bot]@users.noreply.github.com
    +
    +

    댓글 기능

    +

    giscus를 이용하여 댓글 기능을 추가한다.

    +

    giscus 설정

    +
      +
    1. 공개 저장소여야 한다.
    2. +
    3. giscus 앱이 설치되어 있어야 한다.
    4. +
    5. Discussions 기능이 해당 저장소에서 활성화되어 있어야 한다.
    6. +
    +

    자세한 내용은 giscus를 확인하자.

    +

    docusaurus 설정

    +

    swizzling을 이용하여 컴포넌트를 감싼다.
    +기존에 게시물을 giscus가 포함된 리액트 컴포넌트로 감싸는 형태가 된다.
    +아래 명령어를 이용하여 BlogPostItem을 추출할 수 있다.

    +
    yarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap
    +
    +

    명령어를 입력하면 /src/theme/BlogPostItem/index.js 위치에 파일이 생성된다.
    +파일의 내용을 아래와 같이 수정하고, 이때 setAttribute 부분은 적절하게 자신의 giscus 설정을 이용한다.

    +
    import OriginalBlogPostItem from "@theme-original/BlogPostItem";
    +import React, { useEffect, useRef } from "react";
    +// @ts-expect-error internal code
    +import { useColorMode } from "@docusaurus/theme-common";
    +import { useBlogPost } from "@docusaurus/theme-common/internal";
    +
    +const giscusSelector = "iframe.giscus-frame";
    +
    +function BlogPostItem(props) {
    +  const { colorMode } = useColorMode();
    +  const { isBlogPostPage } = useBlogPost();
    +  const giscusTheme = colorMode === "dark" ? "dark" : "light";
    +  const containerRef = useRef(null);
    +
    +  useEffect(() => {
    +    if (!isBlogPostPage) return;
    +
    +    const giscusEl = containerRef.current.querySelector(giscusSelector);
    +
    +    const createGiscusEl = () => {
    +      const script = document.createElement("script");
    +
    +      script.src = "https://giscus.app/client.js";
    +      script.setAttribute("data-repo", "teco-chat/teco-chat.github.io");
    +      script.setAttribute("data-repo-id", "R_kgDOJZ5j0Q");
    +      script.setAttribute("data-category", "Announcements");
    +      script.setAttribute("data-category-id", "DIC_kwDOJZ5j0c4CXS_Q");
    +      script.setAttribute("data-mapping", "pathname");
    +      script.setAttribute("data-strict", "0");
    +      script.setAttribute("data-reactions-enabled", "1");
    +      script.setAttribute("data-emit-metadata", "0");
    +      script.setAttribute("data-input-position", "bottom");
    +      script.setAttribute("data-theme", giscusTheme);
    +      script.setAttribute("data-lang", "ko");
    +      script.crossOrigin = "anonymous";
    +      script.async = true;
    +      
    +      containerRef.current.appendChild(script);
    +    };
    +
    +    const postThemeMessage = () => {
    +      const message = {
    +        setConfig: {
    +          theme: giscusTheme,
    +        }
    +      };
    +
    +      giscusEl.contentWindow.postMessage({ giscus: message }, "https://giscus.app");
    +    };
    +
    +    giscusEl ? postThemeMessage() : createGiscusEl();
    +  }, [giscusTheme]);
    +
    +  return (
    +    <>
    +      <OriginalBlogPostItem {...props} />
    +      {isBlogPostPage && <div ref={containerRef} />}
    +    </>
    +  );
    +}
    +
    +export default BlogPostItem;
    +
    +

    알고리아 설정 및 직접 관리하기

    +

    알고리아를 사용하면 검색 기능을 추가할 수 있다.
    +유료 플랜이나 netlify를 사용하는 경우 크롤러를 따로 제공해 주는 것 같다.

    +

    무료 플랜은 직접 인덱스를 수집하는 방법과, docsearch를 이용하는 방법이 있다.
    +docsearch에 등록한다면 일주일에 한 번씩 크롤링이 진행된다.
    +이 글에서는 직접 인덱스를 수집하는 방법을 사용한다.

    + +

    알고리아 애플리케이션 생성 및 키 확인

    +

    회원가입을 하고 새로운 애플리케이션 생성을 누른다.
    +생성을 다 마치면 다음과 같이 api 키를 확인할 수 있다.

    +

    algolia

    +

    키 생성

    +

    직접 인덱스를 수집하기 위한 키를 생성한다.
    +addObject, editSettings, deleteIndex acl(접근 제어 목록)이 있으면 된다.

    +

    key

    +

    .env 파일 생성

    +

    프로젝트 폴더 상단에 .env 파일을 생성한다.

    +
    APPLICATION_ID=MVIU5UEMOM
    +API_KEY=인덱스_생성용_키
    +
    +

    config 파일 생성

    +

    마찬가지로 최상단에 config.json 파일을 생성한다. +설정 파일은 해당 링크를 참고한다.
    +또는 Docusaurus의 설정 파일을 참고한다.

    +
    {
    +  "index_name": "teco",
    +  "start_urls": [
    +    "https://teco-chat.github.io/"
    +  ],
    +  "sitemap_urls": [
    +    "https://teco-chat.github.io/sitemap.xml"
    +  ],
    +  "sitemap_alternate_links": true,
    +  "stop_urls": [
    +    "/tests"
    +  ],
    +  "selectors": {
    +    "lvl0": {
    +      "selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",
    +      "type": "xpath",
    +      "global": true,
    +      "default_value": "Documentation"
    +    },
    +    "lvl1": "header h1",
    +    "lvl2": "article h2",
    +    "lvl3": "article h3",
    +    "lvl4": "article h4",
    +    "lvl5": "article h5, article td:first-child",
    +    "lvl6": "article h6",
    +    "text": "article p, article li, article td:last-child"
    +  },
    +  "strip_chars": " .,;:#",
    +  "custom_settings": {
    +    "separatorsToIndex": "_",
    +    "attributesForFaceting": [
    +      "language",
    +      "version",
    +      "type",
    +      "docusaurus_tag"
    +    ],
    +    "attributesToRetrieve": [
    +      "hierarchy",
    +      "content",
    +      "anchor",
    +      "url",
    +      "url_without_anchor",
    +      "type"
    +    ]
    +  },
    +  "conversation_id": [
    +    "833762294"
    +  ],
    +  "nb_hits": 46250
    +}
    +
    +

    docker 이용하여 크롤링

    +

    docker와 jq가 필요하다.
    +jq가 설치되어 있지 않으면 mac 기준 brew를 이용해서 설치할 수 있다.

    +
    brew install jq
    +
    +

    다음 명령어를 이용하여 .env와 config.json을 이용하여 크롤링을 한다.

    +
    docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper
    +
    +

    docusaurus 설정

    +

    전에 확인한 APP ID, Search-Only API KEY, IndexName을 이용하여 docusaurus.config 파일에 설정한다.

    +
    themeConfig:
    +  /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    +  ({
    +    ...
    +    algolia: {
    +      appId: 'MVIU5UEMOM', // Application ID
    +      apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key
    +      indexName: 'teco', // config.json에 설정한 인덱스명
    +      contextualSearch: true,
    +    },
    +  })
    +
    +

    부가 설정

    +

    화면 상단 Github Icon

    +

    파일 최하단에 아래 css 구문을 추가한다.

    +
    .header-github-link:hover {
    +  opacity: 0.6;
    +}
    +
    +.header-github-link:before {
    +  content: '';
    +  width: 24px;
    +  height: 24px;
    +  display: flex;
    +  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
    +    no-repeat;
    +}
    +
    +html[data-theme='dark'] .header-github-link:before {
    +  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
    +    no-repeat;
    +}
    +
    +

    themeconfig -> navbar에 github link를 설정한다.

    +
    navbar: {
    +  title: 'HELLO',
    +  items: [
    +    {
    +        href: 'https://github.com/greeng00se',
    +        position: 'right',
    +        className: 'header-github-link',
    +        'aria-label': 'GitHub repository',
    +    },
    +  ],
    +},
    +
    +

    코드블럭

    +

    java나 kotlin의 경우 기본적으로 하이라이팅을 지원해 주지 않는다.
    +prism 설정을 아래와 같이 변경해 준다.

    +
    prism: {
    +  theme: lightCodeTheme,
    +  darkTheme: darkCodeTheme,
    +  additionalLanguages: ['java', 'kotlin'],
    +}
    +
    +

    mermaid

    +

    mermaid를 사용하려면 @docusaurus/theme-mermaid 를 설치해야 한다.

    +
    yarn add @docusaurus/theme-mermaid
    +
    +

    설치 후 아래와 같이 설정을 추가한다.

    +
    const config = {
    +  ...
    +  markdown: {
    +    mermaid: true,
    +  },
    +  themes: [
    +    '@docusaurus/theme-mermaid'
    +  ],
    +};
    +
    +

    themeConfig에서 mermaid의 테마를 지정할 수 있다.

    +
    themeConfig:
    +    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    +    ({
    +      ...
    +      mermaid: {
    +        theme: {
    +          light: 'neutral', 
    +          dark: 'dark'
    +        },
    +      },
    +    }),
    +
    +

    국제화 설정

    +

    국제화 설정을 한다면 Older Entries 형태의 설명이 다음 페이지 로 변경된다.
    +설정파일에서 i18n에 있는 로케일 설정을 ko로 변경하면 된다.

    +
    i18n: {
    +  defaultLocale: "ko",
    +  locales: ["ko"],
    +},
    +
    +

    블로그 글 author

    +

    팀원 별로 문서를 관리한다면 다음과 같이 어떤 팀원이 글을 작성했는지 설정해야 한다.

    +

    author

    +

    authors.yml 파일을 이용하여 사용자에 대한 기본 설정을 할 수 있다.

    +
    herb:
    +  name: 허브
    +  title: Backend
    +  url: https://github.com/greeng00se
    +  image_url: https://github.com/greeng00se.png
    +
    +mallang:
    +  name: 말랑
    +  title: Backend
    +  url: https://github.com/shin-mallang
    +  image_url: https://github.com/shin-mallang.png
    +
    +

    블로그 글을 작성할 때 다음과 같이 authors에 넣어주기만 하면 된다.

    +
    ---
    +slug: 1
    +title: Hello World
    +authors: [herb, mallang]
    +tags: [hello, docusaurus]
    +---
    +
    +첫 번째 문서 내용
    +
    \ No newline at end of file diff --git a/page/34.html b/page/34.html index c50f635a5..5640a95f0 100644 --- a/page/34.html +++ b/page/34.html @@ -13,74 +13,70 @@ - - + + -

    · 약 5분

    MySQL 엔진의 잠금

    -

    MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
    -MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

    -

    글로벌 락(Global lock)

    -

    MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

    -
      -
    • 영향을 미치는 범위는 해당 서버 전체이다.
    • -
    • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.
    • -
    -

    한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
    -데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
    -InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

    -
    -- GLOBAL LOCK
    -FLUSH TABLES WITH READ LOCK;
    --- UNLOCK
    -UNLOCK TABLES;
    +

    · 약 5분

    웹소켓

    +

    단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
    +웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

    +

    웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

    +

    웹소켓 등장 배경

    +

    웹소켓이 등장하기 이전, 실시간성을 보장하기 위해 Polling, Long polling, Streaming 같은 기술을 사용했어야 했다.
    +이는 실시간성이나 양방향성을 만족시키지 못했고, HTTP를 이용하기 때문에 과도한 오버헤드가 발생했다.

    +

    Polling: 주기적으로 서버에 요청을 보내 수신할 정보가 있는지 확인하는 방법

      +
    • 서버에서 보낼 내용이 없어도 클라이언트는 알 수 없다.
    • +
    • 계속해서 요청을 보내 확인을 해야하기 때문에 서버에 불필요한 부하를 주어야 한다.
    • +

    Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

      +
    • 폴링 방식보다 서버에 적은 부하를 줄 수 있지만, 요청의 주기가 짧으면 폴링과 차이가 없어진다.
    • +

    Streaming: 클라이언트가 request를 보내면 커넥션을 맺고, 이 커넥션을 유지하면서 서버가 계속 데이터를 보내는 방법

      +
    • 클라이언트가 서버에 요청을 하고 싶다면 새로운 커넥션을 맺어야 한다.
    • +
    +

    웹소켓의 동작

    +

    MySQL 5.5 버전 이전의 기본 스토리지 엔진이다.
    -트랜잭션을 지원하지 않고, SELECT 작업 속도가 빠르다.

    -

    테이블 락(Table lock)

    -

    개별 테이블 단위로 설정되는 잠금이다.
    -명시적 또는 묵시적으로 특정 테이블의 락을 획득할 수 있다.
    -묵시적 락은 MyISAM이나 MEMORY 테이블에 데이터를 변경하는 쿼리를 실행하면 발생한다.
    -InnoDB 테이블에는 DML 쿼리는 무시되고 DDL 일 경우에만 묵시적으로 락을 획득한다.

    -
    -- TABLE LOCK
    -LOCK TABLES table_name [ READ | WRITE ]
    -
    --- UNLOCK
    -UNLOCK TABLES;
    -
    -

    네임드 락(Named lock)

    -

    임의의 문자열에 대한 잠금을 설정할 수 있는 잠금으로 유저 레벨 락으로도 불린다.
    -여러 스레드나 프로세스가 동일한 데이터를 수정하려는 경우, 동시에 수정하지 못하도록 보호할 수 있다.

    -
    -- aGVyYg== 라는 문자열에 대한 잠금 획득, 이미 잠금을 사용중인 경우 1초 동안만 대기
    -SELECT GET_LOCK('aGVyYg==', 1);
    -
    --- 문자열에 대한 잠금이 설정되어 있는지 확인한다.
    -SELECT IS_FREE_LOCK('aGVyYg==');
    -
    --- 문자열에 대한 잠금을 해제한다.
    -SELECT RELEASE_LOCK('aGVyYg==');
    -
    --- 위 3개 함수 모두 정상적으로 락을 획득하거나 해제한 경우에 1을, 아니면 0을 반환한다.
    +    Client->>Server: 양방향 통신
    +    Server->>Client: 
     
    --- 모든 문자열에 대한 잠금을 해제한다. 해제된 잠금의 개수를 반환한다.
    -SELECT RELEASE_ALL_LOCKS();
    +    Client->>Server: 종료
    +    Server->>Client: ">
    +

    1. Upgrade 요청

    +

    WebSocket 프로토콜로 전환하는 HTTP 요청을 보낸다.
    +이는 HTTP와 같이 80, 443 포트를 사용한다.
    +웹소켓으로 전환하기 위해서는 Upgrade: websocket, Connection: Upgrade 헤더가 필요하다.
    +Sec-WebSocket-Key는 서버에서 Sec-WebSocket-Accept를 계산하여 응답하고 이 값이 예상한 값과 다르면 연결이 수립되지 않는다.
    +Sec-WebSocket-Protocol의 경우 서브프로토콜의 목록으로 서버 측에서는 해당 목록 중 하나를 선택하여 반환해야 한다.
    +만약 서버측에서 여러 개 지원이 가능한 경우 지원 가능한 프로토콜 중 첫번째 프로토콜을 클라이언트측으로 보낸다.

    +
    GET /chats HTTP/1.1
    +Host: localhost:8080
    +Upgrade: websocket
    +Connection: Upgrade
    +Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
    +Sec-WebSocket-Protocol: v10.stomp, v11.stomp
    +Sec-WebSocket-Version: 13
    +Origin: http://localhost:8080
     
    -

    메타데이터 락(Metadata lock)

    -

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    -명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    -보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    -
    -- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
    --- 아래 구문 실행 시 메타데이터 락을 자동으로 획득한다.
    -RENAME TABLE rank TO rank_backup, rank_new TO rank;
    +

    2. Switching Protocols

    +

    서버는 101 Switching Protocols 응답을 반환한다.
    +Sec-WebSocket-Accept은 Sec-WebSocket-Key 뒤에 258EAFA5-E914-47DA-95CA-C5AB0DC85B11를 붙이고 SHA1로 해싱 후 Base64로 인코딩하여 반환한다.
    +이는 서버 웹소켓 프로토콜의 지원 여부를 클라이언트에게 명확히 알리기 위해 존재한다.

    +
    HTTP/1.1 101 Switching Protocols 
    +Upgrade: websocket
    +Connection: Upgrade
    +Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
    +Sec-WebSocket-Protocol: v10.stomp
     
    -

    참고 자료

    -

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    -MySQL의 User Level Lock를 활용한다면?, gywndi
    -Locking Functions, MySQL 5.7 Reference
    -Locking Functions, MySQL 8.0 Reference

    +

    3. 통신 후 종료

    +

    연결이 수립되면 웹소켓 프레임 단위로 양방향 통신을 한다.
    +연결 종료를 원하는 경우 클라이언트, 서버 모두 연결 종료를 요청할 수 있다.

    +

    참고 자료

    +

    https://datatracker.ietf.org/doc/html/rfc6455
    +https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
    +https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
    +https://docs.spring.io/spring-framework/reference/web/websocket.html

    \ No newline at end of file diff --git a/page/35.html b/page/35.html index 78e6bd21f..902c4d254 100644 --- a/page/35.html +++ b/page/35.html @@ -13,138 +13,99 @@ - - + + -

    · 약 10분

    트랜잭션(Transaction)

    -

    데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
    -트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
    -논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

    -

    트랜잭션의 속성(ACID)

    -

    원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
    -일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
    -격리성(Isolation): 각각의 트랜잭션은 독립적이라 서로에게 영향을 주지 않아야 한다.
    -지속성(Durability): 트랜잭션이 성공적으로 완료된다면 영구적으로 결과에 반영되어야 한다.

    -

    트랜잭션 주의사항

    -

    트랜잭션은 꼭 필요한 최소의 코드에만 적용하는 것이 좋다.(트랜잭션의 범위를 최소화하라)
    -구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

    -

    데이터의 일관성과 안전성을 보장하기 위해 배제해야 한다.
    -네트워크 작업을 트랜잭션 내부에 포함한다면 다음과 같은 문제가 발생할 수 있다.

      -
    • 네트워크 작업이 중간에 실패할 가능성(안전성 X)
    • -
    • 통신으로 인해 데이터가 변경될 수 있는 부분(일관성 X)
    • -
    -

    격리 수준(Isolation level)

    -

    여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 데이터의 조회 및 변경을 허용할지 결정하는 것을 말한다.
    -격리 수준이 높아질 수록 동시 처리 성능이 떨어지는 것이 일반적이지만, SERIALIZABLE이 아니라면 크게 성능의 저하가 발생하지 않는다.

    -

    READ UNCOMMITTED

    -

    각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다.
    -더티 리드 현상이 발생하기 때문에 정합성의 문제가 많은 격리 수준이다.
    -MySQL 사용시 최소 READ COMMITTED 이상의 격리 수준 사용을 권장한다.

    - -

    READ COMMITTED

    -

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    -오라클 DBMS에서 기본으로 사용되는 격리 수준이다.
    -REPEATABLE READ가 보장되지 않기 때문에 NON-REPEATABLE READ 문제가 발생한다.

    - -

    REPEATABLE READ

    -

    트랜잭션이 시작되기 전에 COMMIT이 완료된 내용에 대해서만 조회할 수 있다.
    -MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준이다.
    -MVCC를 이용해 언두(Undo) 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장한다.
    -동일한 결과를 보장하는 방법은 다음과 같다.

    +

    · 약 5분

    자바 17, 스프링 6.0, 스프링 부트 3.1

    +

    팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
    +2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

    +

    자바 변경 사항

    +

    우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
    +따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

    +

    Switch Expressions(Java 14)

    +

    Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

    +
    enum RESULT {
    +    WIN, LOSE, DRAW
    +}
    +
    +RESULT result = RESULT.WIN;
    +
    +int prize = switch (result) {
    +    case WIN -> 10_000_000;
    +    case LOSE, DRAW -> 5_000_000;
    +	default -> 0;
    +};
    +
    +

    주요 특징은 다음과 같다.

      -
    • 모든 InnoDB 트랜잭션은 순차적으로 증가하는 고유한 트랜잭션 번호를 가진다.
    • -
    • Undo 영역에 백업된 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함되어있다.
    • -
    • Undo 영역의 백업된 데이터는 스토리지 엔진이 불필요하다고 판단하는 경우 삭제된다.
    • -
    • REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 가장 오래된 트랜잭션 번호보다 앞선 Undo 영역의 데이터는 삭제하지 않는다.
    • +
    • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
    • +
    • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
    • +
    • break 문이 필요 없다.
    • +
    • default 블록을 통해 기본 값을 지정할 수 있다.
    -

    InnoDB에서는 갭 락과 넥스트 키 락을 이용하여 팬텀 리드 현상을 방지한다.

    - -

    갭 락: 레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    -넥스트 키 락: 레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.

    -

    동시성을 제어하는 방법 중 하나로 하나의 레코드에 대해 여러 개의 버전이 동시에 관리되는 것이다.

      -
    • PostgreSQL은 다중 버전의 데이터를 저장하는 것으로 MVCC를 구현한다.
    • -
    • Oracle, InnoDB는 Undo log를 이용해 이 기능을 구현한다.(최신 버전의 데이터만 DB에 저장)
    • -

    잠금을 사용하지 않는 읽관된 읽기를 제공하는 것이 목적이다.

    -

    SERIALIZABLE

    -

    트랜잭션을 순차적으로 진행시키는 격리 수준이고 따라서 동시 처리 성능도 다른 격리 수준보다 떨어진다.
    -트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 접근할 수 없고 단순한 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야만 한다.
    -InnoDB에서는 팬텀 리드 현상이 REPEATABLE READ 격리 수준에서 발생하지 않기 때문에 굳이 사용할 필요는 없다.

    -

    격리 수준에 따른 부정합 문제

    -

    격리 수준에 따라 더티 리드, 반복 가능하지 않은 조회, 팬텀 리드 문제가 발생한다.

    -
    격리 수준 / 부정합 문제더티 리드반복 가능하지 않은 조회팬텀 리드
    READ UNCOMMITTEDOOO
    READ COMMITTEDXOO
    REPEATABLE READXXO(InnoDB는 X)
    SERIALIZABLEXXX
    -

    더티 리드(Dirty read)

    -

    어떤 트랜잭션에서 처리한 작업이 완료되지 않았어도 다른 트랜잭션에서 볼 수 있는 현상
    -트랜잭션 격리 수준이 READ UNCOMMITTED일 때 발생한다.
    -예) B가 레코드를 추가하고 커밋을 하지 않았지만, A가 해당 레코드를 조회할 수 있는 경우

    -

    반복 가능하지 않은 조회(Non-repeatable read)

    -

    한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 그 값이 다른 현상
    -예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

    - -

    팬텀 리드(Phantom read, Phantom row)

    -

    한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
    -예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

    - +

    Text Block(Java 15)

    +

    Java 15에는 새로운 문자열 표현방식이 추가되었다.
    +긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

    +
    @Repository
    +public interface PostRepository extends JpaRepository<Post, Long> {
    +    @Query("""
    +        SELECT p FROM Post p
    +        WHERE p.title LIKE %:keyword%
    +        OR p.content LIKE %:keyword%
    +        """)
    +    List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
    +}
    +
    +

    NPE 메시지(Java 15)

    +
    String name = null;
    +name.chars();
    +
    +/** 
    +# before
    +java.lang.NullPointerException
    +	at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)
    +
    +# after
    +Cannot invoke "String.chars()" because "name" is null
    +java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
    +*/
    +
    +

    Record(Java 16)

    +

    Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
    +Record를 선언하는 경우 접근자, 생성자, equals & hashcode, toString이 제공된다.
    +데이터 전송 용도로 적합해 보인다.

    +
    public record PostDto(String title, String content) {
    +}
    +
    +

    추가적인 변경사항

    +

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    +

    스프링, 스프링 부트 변경 사항

    +

    스프링과 스프링 부트에도 많은 변경 사항이 있었다.
    +따라서 필요해보이는 몇개 정도만 정리했다.

    +

    스프링 요구사항

    +

    Java 17, Jakarta EE 9 이상이어야 한다.

    +

    네임스페이스 변경

    +

    Jakarta EE 9가 적용되면서 네임스페이스도 전반적으로 javax -> jakarta로 변경되었다.

    +

    PathPatternParser - trailing slash 허용하지 않음

    +

    6.0 이전의 경우 기본 설정 기준으로 @GetMapping("/hello")@GetMapping("/hello/")가 동일했다.
    +6.0 이후의 PathPatternParser가 기본으로 사용되고, /hello/hello/는 서로 다른 URL로 매칭된다.

    +
    +

    PathPatternParser used by default (with the ability to opt into PathMatcher).

    +
    +

    HTTP interface client

    +

    자바 인터페이스와 어노테이션을 이용하여 HTTP 요청을 위한 서비스를 정의할 수 있는 방법이 추가되었다.
    +자세한 내용은 토비님의 강의를 참고하면 좋을 것 같다.

    +

    스프링 부트 최소 요구사항

    +

    Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6
    +이외에도 서드파티들의 최신 릴리즈 버전을 사용함으로, 문제가 발생하는 경우 해당 버전에 맞는 릴리즈 노트를 참고할 수 있을 것 같다.

    참고 자료

    -

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    -Isolation Level, MySQL

    +

    어느 월급쟁이개발자 의 스프링 부트 따라잡기
    +자바 9-16 주요 특징 복습하기
    +Java EE에서 Jakarta EE로의 전환
    +Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩
    +What's New in Spring Framework 6.x
    +Spring Boot 3.0 Release Notes
    +Spring Boot 3.1 Release Notes

    \ No newline at end of file diff --git a/page/36.html b/page/36.html index f5a1704e4..253629465 100644 --- a/page/36.html +++ b/page/36.html @@ -13,50 +13,60 @@ - - + + -

    · 약 5분

    테스트 대역이란?

    -

    모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
    -Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

    -

    테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
    -외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

    -

    테스트 대역의 타입 계층 구조

    - -

    더미(Dummy)

    -

    가장 단순하고, 원시적인 유형의 테스트 대역이다.
    -기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
    -만약 메서드가 무언가 반환을 해야하는 경우 0, null과 같은 값을 반환한다.

    -

    스텁(Stub)

    -

    시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
    -이를 통해 특정 조건에서 메서드가 예상한대로 동작하는지 확인할 수 있다.

    -

    스파이(Spy)

    -

    스텁과 유사하지만 호출 여부를 기록하거나 호출할 때 전달한 인자값을 기록할 수 있다.
    -예) 메일 전송 기능을 가진 객체를 테스트 대역으로 구현했을 때 메일 전송 횟수를 기록한다.

    -

    목, 모의 객체(Mock)

    -

    목은 더미, 스텁, 스파이를 포함한다.
    -호출 시 사전에 정의된 결과를 반환하고, 예상치 못한 호출이 있을 경우 예외를 던질 수 있다.
    -또한 호출에 대한 검증을 할 수 있다.

    -

    가짜(Fake)

    -

    DOC와 동일한 기능을 제공하지만, 더욱 간단한 방법으로 구현된 것이다.
    -예) 실제 데이터베이스와 유사하게 동작하는 가짜 객체를 만들어 테스트할 수 있다.

    -

    의존 구성 요소, DOC를 테스트 더블로 대체할 수 있다.
    -테스트 더블은 DOC와 동일한 API를 제공해야 한다.

    -

    상호작용에 따른 목과 스텁 구분

    -

    단위 테스트 p.149 에서는 테스트 대역을 크게 목과 스텁으로 구분한다.
    -목은 SUT와 관련된 상호작용을 모방하고 검사하는 반면, 스텁은 단순 모방만 한다.

    -
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색
    -

    테스트 대상 시스템
    -테스트를 하려는 대상

    -

    참고 자료

    -

    소프트웨어 장인 정신 이야기 - 3장 고급 테스트 주도 개발, 로버트 C. 마틴
    -단위 테스트 - 5장 목과 테스트 취약성, 블라디미르 코리코프
    -테스트 주도 개발 시작하기 - 7장 대역, 최범균
    -테스트 더블, Martin Fowler
    -테스트 관련 용어 정리, Johngrib
    -Test Double, Gerard Meszaros

    +

    · 약 6분

    ./route.png

    +

    이미지 생성의 책임

    +

    위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
    +따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

    +

    해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

    +
      +
    • 이미지 생성
    • +
    • 선과 점 표현
    • +
    • 투명한 배경색
    • +
    +

    현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

    +

    고려한 기술

    +

    백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

    +
      +
    • Python의 Matplotlib
    • +
    • AWT(Abstract Window Toolkit) [최종 선택]
    • +
    • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
    • +
    • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)
    • +
    +

    Python & Matplotlib

    +

    데이터 시각화 라이브러리
    +이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

    +
      +
    • 코드가 간단해서 유지 보수성이 좋다.
    • +
    • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
    • +
    • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.
    • +
    +

    Java AWT 이외의 라이브러리

    +

    Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

    +
    라이브러리설명제외 이유
    SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
    JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
    simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
    matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
    +

    Java & AWT(Abstract Window Toolkit)

    +

    그래픽과 이미지를 그리기 위한 도구
    +이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

    +
      +
    • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
    • +
    • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
    • +
    • 추가적인 api 호출을 하지 않아도 된다.
    • +
    +

    기술 선택

    +

    AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
    +하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

    +

    유지 보수

    +

    AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
    +따라서 다음과 같은 방법으로 공유하기로 했다.

    +
      +
    1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
    2. +
    3. AWT를 사용한 부분을 문서화하여 공유한다.
    4. +
    +

    레벨 3를 마무리하며 내용 추가

    +

    기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
    +AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

    \ No newline at end of file diff --git a/page/37.html b/page/37.html index 5c5beb413..1c46d5da6 100644 --- a/page/37.html +++ b/page/37.html @@ -13,83 +13,50 @@ - - + + -

    · 약 6분

    클래스 파일

    -

    자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
    -컴파일된 클래스파일은 어떤 구조로 되어있을까?

    -

    클래스 파일의 데이터 형식

    -

    8비트 바이트의 스트림으로 구성된다.
    -16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
    -멀티바이트의 경우 항상 big endian 순서로 저장된다.

    -

    u1 → unsigned 1byte
    -u2 → unsigned 2byte
    -u4 → unsigned 4byte

    -

    클래스 파일 구조

    -
    ClassFile {
    -    u4             magic;
    -    u2             minor_version;
    -    u2             major_version;
    -    u2             constant_pool_count;
    -    cp_info        constant_pool[constant_pool_count-1];
    -    u2             access_flags;
    -    u2             this_class;
    -    u2             super_class;
    -    u2             interfaces_count;
    -    u2             interfaces[interfaces_count];
    -    u2             fields_count;
    -    field_info     fields[fields_count];
    -    u2             methods_count;
    -    method_info    methods[methods_count];
    -    u2             attributes_count;
    -    attribute_info attributes[attributes_count];
    +

    · 약 3분

    개요

    +

    정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
    +하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

    +

    예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

    +

    프로젝트를 진행하며 ImageIo.write 메서드가 호출되는 지 검증이 필요했다.
    +해당 static 메서드를 호출하는 부분을 따로 RouteImageUploader 클래스로 최대한 분리했다.
    +이미지 저장 기능 자체가 외부로 나가는 상호작용이고, 호출 횟수를 검사하는데는 mock을 사용하는게 적절하다고 판단했다.

    +
    public void upload(BufferedImage bufferedImage) {
    +    File file = new File(파일경로);
    +    try {
    +        ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);
    +    } catch (IOException e) {
    +        throw new DrawException(IMAGE_SAVE_FAIL);
    +    }
     }
     
    -

    매직넘버

    -

    모든 클래스 파일은 0xCAFEBABE라는 매직넘버로 시작한다.
    -보통 매직넘버는 파일 종류를 식별하는 용도로 사용된다.

    -

    클래스 파일 포맷 버전

    -

    클래스 파일 버전 값은 클래스로더의 호환성 보장을 위해 꼭 필요한 값이다.

    -
      -
    • Java 17 버전으로 빌드한다면 class version 61 ex) 00 00 00 3D
    • -
    -

    호환되지 않는 버전의 클래스 파일을 로딩하려고 하는 경우 런타임에 UnsupportedClassVersionError 예외가 발생한다.

    -

    class file format major versions

    -
    Java SEReleasedMajorSupported majors
    8March 20145245 .. 52
    9September 20175345 .. 53
    10March 20185445 .. 54
    11September 20185545 .. 55
    12March 20195645 .. 56
    13September 20195745 .. 57
    14March 20205845 .. 58
    15September 20205945 .. 59
    16March 20216045 .. 60
    17September 20216145 .. 61
    -

    상수 풀

    -

    2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
    -클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
    -JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

    -

    액세스 플래그

    -

    클래스, 인터페이스와 같은 파일의 속성을 표시한다.
    -예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.

    -
      -
    • 계산은 다음과 같이 이루어진다. ACC_PUBLIC xor ACC_INTERFACE xor ACC_ABSTRACT
    • -
    -

    공식문서에 들어가면 각 플래그에 대한 설명 + 플래그 설정시 동시에 설정되면 안되는 플래그와 같은 설명이 자세하게 나와있다.

    -

    Class access and property modifiers

    -
    Flag NameValueInterpretation
    ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
    ACC_FINAL0x0010Declared final; no subclasses allowed.
    ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
    ACC_INTERFACE0x0200Is an interface, not a class.
    ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
    ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
    ACC_ANNOTATION0x2000Declared as an annotation type.
    ACC_ENUM0x4000Declared as an enum type.
    ACC_MODULE0x8000Is a module, not a class or interface.
    -

    this_class

    -

    클래스명과 같은 이름을 표현하는 값으로, 상수 풀에서 클래스명과 일치하는 항목의 인덱스를 참조한다.
    -해당 인덱스의 항목은 CONSTANT_Class_infoclass 형식의 값이어야 한다.

    -

    super_class

    -

    상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
    -아무것도 상속하지 않는 클래스의 경우 java.lang.Object의 인덱스 값이 들어있다.

    -

    interface, field, method

    -

    각각의 개수와, 정보에 대한 값이 들어있다.
    -interface, field, method를 표시하는 방법이 각각 다르고, 접근자에 대한 플래그도 각각 다르다.

    -

    attributes

    -

    해당 클래스 파일에서 사용하는 추가 정보의 모음이다. 예) 소스파일명
    -정해진 클래스 파일의 구조를 확장하는 역할을 한다.

    -

    클래스 파일 확인하면서 사용한 툴

    -

    IntelliJ plugin - BinEd
    -IntelliJ plugin - jclasslib Bytecode Viewer

    +

    Mocking static methods

    +

    Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
    +mockStatic을 사용하면 MockedStatic<T>이 반환되는데 사용 후 꼭 close를 해줘야 한다.

    +

    JUnit의 @BeforeAll로 설정하고 @AfterAll 메서드로 종료하는 방법도 있지만 MockedStatic<T>의 상위 인터페이스인 ScopedMock이 AutoCloseable을 구현하고 있기에 try-with-resources를 사용하는 방법이 더욱 좋은 것 같다.

    +
    // given
    +BufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);
    +RouteImageUploader routeImageUploader = new RouteImageUploader();
    +
    +// expect
    +try (MockedStatic<ImageIO> imageIO = Mockito.mockStatic(ImageIO.class)) {
    +    routeImageUploader.upload(bufferedImage);
    +    imageIO.verify(
    +            () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),
    +            times(1)
    +    );
    +}
    +
    +

    마치며

    +

    정적 메서드를 모킹하는 것은 안티패턴이으로 적절한 추상화를 이용해 테스트 하기 좋은 코드를 만드는 연습을 하자.
    +하지만 추상화를 하면 할 수록 코드의 복잡도는 증가한다.
    +항상 상황을 고려하고 간결함을 포기할 만큼 중요한 부분인지 적절한 트레이드오프를 고려하자.

    참고 자료

    -

    2장 JVM 이야기, 자바 최적화
    -Class file in Java, File Format
    -java se11 Class 파일 형식, Oracle
    -java se17 Class 파일 형식, Oracle

    +

    Mocking static methods
    +Mockito mock static methods
    +Enable mocking static methods in Mockito

    \ No newline at end of file diff --git a/page/38.html b/page/38.html index b39338460..2d423ef84 100644 --- a/page/38.html +++ b/page/38.html @@ -13,355 +13,181 @@ - - + + -

    · 약 10분

    체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
    -이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
    -템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

    -

    기존 코드

    -
    public class User {
    -    private final int id;
    -    private final String name;
    -
    -    public User(final int id, final String name) {
    -        this.id = id;
    -        this.name = name;
    -    }
    -
    -    public int getId() {
    -        return id;
    -    }
    -
    -    public String getName() {
    -        return name;
    -    }
    -}
    -
    -

    SELECT, DELETE 중복 제거

    -

    변하지 않는 부분: try-with-resource, preparedStatement를 사용하는 부분, executeUpdate로 실행 등등
    -변하는 부분: SQL Query, 매개변수

    -

    다음과 같이 쿼리를 실행하는 부분을 분리하고 가변인수를 사용한다면 SELECT와 DELETE의 중복을 제거할 수 있다.

    -
    public void insert(final String name) {
    -    final String query = "INSERT INTO User (name) VALUES (?)";
    -    executeUpdate(query, name);
    -}
    -
    -public void delete(final int userId) {
    -    final String query = "DELETE FROM user WHERE user_id = ?";
    -    executeUpdate(query, userId);
    -}
    -
    -private void executeUpdate(final String query, final Object... parameters) {
    -    final Connection connection = connectionPool.getConnection();
    -    try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
    -        for (int i = 1; i <= parameters.length; i++) {
    -            preparedStatement.setObject(i, parameters[i - 1]);
    -        }
    -        preparedStatement.executeUpdate();
    -    } catch (final SQLException e) {
    -        throw new IllegalArgumentException(e.getMessage());
    -    }
    -}
    -
    -

    조회 분리하기 - 1. 콜백을 위한 인터페이스 정의

    -

    조회는 INSERT, DELETE와 달리 값을 반환받아야 하기 때문에 다른 방법을 사용해야 한다.
    -이 때 콜백이라는 것을 사용하여 중복을 제거할 수 있다.

    -

    프로그래밍에서 콜백은 다른 코드의 인수로 넘겨주는 실행 가능한 코드를 뜻한다.
    -자바에서는 람다나 익명 클래스를 넘겨서 사용할 수 있다.

    -

    데이터베이스에서 값을 조회하고, 해당 값을 객체로 매핑하여 값을 반환해야 한다.
    -executeQuery로 조회한 값은 ResultSet 안에 들어가있다.
    -이를 원하는 타입의 값으로 변환해야하니 일단 콜백을 위한 인터페이스를 만들어야 한다.

    -
    @FunctionalInterface
    -public interface RowMapper {
    -    User mapRow(final ResultSet resultSet) throws SQLException;
    -}
    +

    · 약 7분

    개요

    +

    이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

    +

    사용 기술

    +

    언어: Python 3.10
    +이미지 생성: matplotlib
    +서비스: AWS Lambda, AWS API Gateway
    +이미지 저장 및 URL: AWS S3, AWS CloudFront

    +

    플로우는 다음과 같다.

    + +

    요구사항

    +

    ./route.png

    +

    우측 상단의 경로 이미지를 생성하려고 한다.
    +경로 이미지 생성에 대한 요구사항은 다음과 같다.

    +
      +
    • 위도, 경도로 이루어진 배열을 입력받는다.
    • +
    • 이미지 생성
    • +
    • 선과 점 표현
    • +
    • 투명한 배경색
    • +
    • 위경도 차이가 크든 작든 제공하는 이미지 내에 경로가 다 포함되어 있어야 한다.
    • +
    +

    이미지 출력 방식

    +
      +
    1. 위경도를 처리한 값으로 직접 경로를 그린 다음 이미지 형태로 저장
    2. +
    3. 플롯을 그려주는 라이브러리 사용하여 이미지 형태로 저장
    4. +
    +

    이미지 출력 방식의 경우 1번과 2번을 고민했었다.
    +파이썬으로는 플롯을 그려주는 라이브러리인 matplotlib을 사용했다.

    +

    로컬에서 기능 구현

    +
    import time
    +
    +import matplotlib.pyplot as plt
    +
    +
    +def draw(point):
    +    start = time.time()
    +    x, y = zip(*point)
    +    pixel_x, pixel_y = convert_to_pixel_values(x, y)
    +    draw_lines(pixel_x, pixel_y)
    +    end = time.time()
    +    print(end - start)
    +    
    +def convert_to_pixel_values(x, y):
    +    max_diff = max(max(x) - min(x), max(y) - min(y))
    +    return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)
    +
    +
    +def scale_to_pixel_values(points, max_diff):
    +    min_value = min(points)
    +    scaled_coordinates = [(p - min_value) / max_diff for p in points]
    +    return scaled_coordinates
    +
    +
    +def draw_lines(x, y):
    +    figure = plt.gcf()
    +    figure.set_size_inches(5, 5)
    +    plt.plot(x, y, c = 'w',linewidth=5)
    +    plt.scatter(x[3],y[3], c = 'w', s = 125)
    +    plt.axis('off')
    +    plt.savefig('name.png', transparent=True, format='png')
    +
    +point = [
    +    [126.96352960597338, 37.590841000217125],
    +    [126.96987292787792, 37.58435564234159],
    +    [126.98128481452298, 37.58594375113966],
    +    [126.99360339342958, 37.58248524741927],
    +    [126.99867565340067, 37.56778118088622],
    +    [127.001935378366117, 37.55985240444085],
    +    [126.9831048919687, 37.548030119488665],
    +    [126.97189273528845, 37.5119879225856],
    +    [127.02689859997221, 37.48488593333883]
    +]
    +
    +draw(point)
     
    -

    조회 분리하기 - 2. 단건 조회

    -

    위에서 정의한 RowMapper를 메서드에서 어떻게 사용해야 할까?
    -아래와 같이 SQL 쿼리, RowMapper, 파라미터를 분리한 메서드에 넘겨주고 쿼리 실행 후 매핑한 값을 반환하도록 한다.

    -
    public User findById(final int userId) {
    -    final String query = "SELECT * FROM user WHERE id = ?";
    -    return queryForSingleResult(query, resultSet -> {
    -        final int id = resultSet.getInt("id");
    -        final String name = resultSet.getString("name");
    -        return new User(id, name);
    -    }, userId);
    -}
    +

    생성 결과는 아래와 같다. (예시를 위해 검은색으로 출력)

    +

    ./routeImage.png

    +

    AWS Lambda

    +

    썸네일 생성 서버를 따로 두기는 기능 대비 비용이 너무 클 것이라고 생각했다.
    +따라서 서버리스로 파일을 처리했다.
    +추가로 s3 접근은 boto3를 사용했다.

    +

    람다 S3 접근을 위한 IAM 생성

    +

    AmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy 두가지를 추가해서 Lambda 전용 역할을 만들어 사용했다.

    +

    람다 배포용 코드

    +

    기술 구현 가능 여부를 확인할 땐 위치 점을 찍는 기능을 람다에 배포하지 않았다.

    +
    
    +import io
    +import uuid
    +
    +import boto3
    +import matplotlib.pyplot as plt
    +
    +PIXEL = 255
    +BUCKET_NAME = 'image-plot'
    +S3 = 's3'
    +
    +def lambda_handler(event, context):
    +    x = event['x']
    +    y = event['y']
    +    image_name = str(uuid.uuid4())
    +
    +    img_data = draw(x, y)
    +    s3 = boto3.client(S3)
    +    s3.put_object(Body=img_data.getvalue(), ContentType='image/png', Bucket=BUCKET_NAME, Key=image_name)
    +    url = f'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}'
    +
    +    return {
    +        'statusCode': 200,
    +        'body': url
    +    }
    +
    +def draw(x, y):
    +    pixel_x, pixel_y = convert_to_pixel_values(x, y)
    +    img_data = draw_lines(pixel_x, pixel_y)
    +    plt.close()
    +    return img_data
    +
    +def convert_to_pixel_values(x, y):
    +    max_diff = max(max(x) - min(x), max(y) - min(y))
    +    return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)
    +
    +def scale_to_pixel_values(points, max_diff):
    +    min_value = min(points)
    +    scaled_coordinates = [(p - min_value) / max_diff for p in points]
    +    pixel_values = [int(p * PIXEL) for p in scaled_coordinates]
    +    return pixel_values
    +
    +def draw_lines(x, y):
    +    plt.plot(x, y, 'k-', linewidth=10)
    +    plt.axis('off')
    +    img_data = io.BytesIO()
    +    plt.savefig(img_data, transparent=True, format='png')
    +    img_data.seek(0)
    +    return img_data
     
    -private User queryForSingleResult(
    -        final String query,
    -        final RowMapper rowMapper,
    -        final Object... parameters
    -) {
    -    final Connection connection = connectionPool.getConnection();
    -    try (final PreparedStatement preparedStatement = connection.prepareStatement(query);
    -         final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {
    -        if (resultSet.next()) {
    -            return rowMapper.mapRow(resultSet);
    -        }
    -        return null;
    -    } catch (SQLException e) {
    -        throw new IllegalArgumentException(e.getMessage());
    -    }
    -}
    -
    -private ResultSet executeQuery(
    -        final PreparedStatement preparedStatement,
    -        final Object[] parameters) throws SQLException {
    -    for (int i = 1; i <= parameters.length; i++) {
    -        preparedStatement.setObject(i, parameters[i - 1]);
    -    }
    -    return preparedStatement.executeQuery();
    -}
     
    -

    조회 분리하기 - 3. 다건 조회

    -

    단건 조회와 유사하다.

    -
    public List<User> findAll() {
    -    final String query = "SELECT * FROM user";
    -    return query(query, resultSet -> {
    -        final int id = resultSet.getInt("id");
    -        final String name = resultSet.getString("name");
    -        return new User(id, name);
    -    });
    -}
    -
    -private List<User> query(final String query, final RowMapper rowMapper, final Object... parameters) {
    -    final Connection connection = connectionPool.getConnection();
    -    try (final PreparedStatement preparedStatement = connection.prepareStatement(query);
    -         final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {
    -        final List<User> result = new ArrayList<>();
    -        while (resultSet.next()) {
    -            result.add(rowMapper.mapRow(resultSet));
    -        }
    -        return result;
    -    } catch (SQLException e) {
    -        throw new IllegalArgumentException(e.getMessage());
    -    }
    -}
    -
    -private ResultSet executeQuery(
    -        final PreparedStatement preparedStatement,
    -        final Object[] parameters) throws SQLException {
    -    for (int i = 1; i <= parameters.length; i++) {
    -        preparedStatement.setObject(i, parameters[i - 1]);
    -    }
    -    return preparedStatement.executeQuery();
    -}
    +

    Layer 추가를 위한 zip 파일 생성

    +

    matplotlib의 경우 외부 라이브러리기 때문에 따로 Layer를 추가해야 한다.
    +zip 파일을 만들어서 업로드해야한다.
    +이때 python의 Lambda 런타임에 대한 계층 경로는 python이다.
    +따라서 압축한 zip 파일은 다음과 같은 구조를 띄어야 한다.

    +
    pillow.zip
    +│ python/PIL
    +└ python/Pillow-5.3.0.dist-info
     
    -

    제네릭 사용하기

    -

    위의 코드는 User를 조회할 때만 사용할 수 있다.
    -아래와 같이 제네릭을 적용하여 다른 Dao에서도 사용 가능하도록 변경할 수 있다.

    -
    @FunctionalInterface
    -public interface RowMapper<T> {
    -    T mapRow(final ResultSet resultSet) throws SQLException;
    -}
    -
    -private <T> List<T> query(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}
    -private <T> T queryForSingleResult(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}
    +

    Ubuntu 기준 다음 명령어를 입력하여 생성을 진행했다.

    +
    sudo apt update
    +sudo apt install zip
    +sudo apt install python3-pip
    +
    +mkdir python
    +pip3 install matplotlib -t python # pip3 install 설치할_패키지 -t 설치_경로
    +zip -r my_layer.zip python # zip -r 압축_파일명 압축_파일이_존재하는_경로
     
    -

    메서드 분리한 부분 클래스로 분리하기 + Optional 사용하기

    -

    메서드로 분리한 부분을 JdbcTemplate이라는 클래스를 만들어 옮긴다.
    -또한 null을 반환하기 보단 Optional로 감싸서 반환하도록 변경한다.
    -최종적으로 아래와 같은 코드가 완성된다.

    -
    public class UserDao {
    -    private final RowMapper<User> rowMapper = resultSet -> {
    -        final int id = resultSet.getInt("id");
    -        final String name = resultSet.getString("name");
    -        return new User(id, name);
    -    };
    -    private final JdbcTemplate jdbcTemplate;
    -
    -    public UserDao(final JdbcTemplate jdbcTemplate) {
    -        this.jdbcTemplate = jdbcTemplate;
    -    }
    -
    -    public void insert(final String name) {
    -        final String query = "INSERT INTO User (name) VALUES (?)";
    -        jdbcTemplate.executeUpdate(query, name);
    -    }
    -
    -    public void delete(final int userId) {
    -        final String query = "DELETE FROM user WHERE user_id = ?";
    -        jdbcTemplate.executeUpdate(query, userId);
    -    }
    -
    -    public Optional<User> findById(final int userId) {
    -        final String query = "SELECT * FROM user WHERE id = ?";
    -        return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);
    -    }
    -
    -    public List<User> findAll() {
    -        final String query = "SELECT * FROM user";
    -        return jdbcTemplate.query(query, rowMapper);
    -    }
    -}
    -
    +

    No module named 'numpy.core._multiarray_umath' 에러

    +

    Layer 추가 후 람다 실행 시 발생한 에러였다.
    +처음에 mac에서 zip 파일을 생성해서 업로드했는데 해당 문제가 발생했다.
    +이는 lambda가 돌아가는 동일한 환경에서 layer를 위한 zip 파일을 만들지 않아서 발생하는 문제다.
    +간단하게 ec2 인스턴스를 하나 만들어서 따로 Layer를 생성하면 문제가 발생하지 않는다.

    +

    적정기술에 대한 생각

    +

    프로젝트에 Lambda와 Python을 사용하려고 했지만 아쉽게도 반려당했다.
    +AWS Lambda를 사용하는 것은 인스턴스에 해당 코드를 배포하는 것보다 더 효율적인 방법일 수 있다.
    +하지만 현재 프로젝트에서 가용 가능한 자원, 기술의 난이도, 사용하는 팀원을 고려한다면 Lambda는 적정기술이 아닐 수 있다.
    +따라서 해당 이미지 생성기를 어떻게 적용할지 조금 더 고려를 해야 될 것으로 보인다.

    +

    최종적으로 Java AWT를 사용하기로 결정했다.

    +

    참고 자료

    +

    AWS Lambda
    +Lambda Layer
    +Python Lambda 함수에 대한 .zip 파일 아카이브 작업
    +No module named 'numpy.core._multiarray_umath'
    +사례별로 알아본 안전한 S3 사용 가이드

    \ No newline at end of file diff --git a/page/39.html b/page/39.html index 716a6b9ac..9a4db7c56 100644 --- a/page/39.html +++ b/page/39.html @@ -13,77 +13,201 @@ - - + + -

    · 약 8분

    레벨 1이 끝났다.
    -우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
    -혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
    -하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

    -

    Keep

    -

    나만의 루틴 만들기

    -

    스스로가 외부의 영향을 많이 받는다고 생각한다.
    -최대한 꾸준히 할 수 있는 시간을 만드는 것이 중요하다고 생각한다.

    -

    매일 8시에 도착하여 아침에 해야 할 일을 정리하거나, 우선순위에 따라 처리하고
    -소화능력이 부족하기 때문에 점심은 도시락(그래봤자 계란2개)을 준비하고
    -항상 똑같은 컨디션을 유지하기 위해 항상 6시에 집에 간다.
    -이제 바빠질 테니 일찍 집에 가는 일은 어쩔 수 없이 줄어들겠지만😢

    -

    선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

    -

    크루들과 친하게 지내기

    -

    10명 정도의 크루의 닉네임을 외우고 친하게 지낸다면 성공적이라고 생각했었다.
    -하다 보니 더 많은 크루들의 닉네임을 외운 것 같다.
    -앞으로도 크루들과 친하게 지내고 아무 때나 말을 걸 수 있는 크루가 늘어나길 :)

    -

    글쓰기

    -

    글을 잘 쓰는 편은 아니지만 꾸준히 작성하려고 노력했다.
    -매 미션마다 회고를 작성하니 생각도 정리되고 개선점도 찾을 수 있어서 좋았다.

    -

    우아한테크코스에는 레벨마다 글쓰기를 진행하는데, 운이 좋게 글쓰기 상을 받았다.
    -사실 겉으로 드러내지 않았지만 꼭 받아보고 싶었다.
    -글쓰기 조원, 투표해 준 크루들에게 너무 감사하다.

    -

    코드 리뷰 스터디

    -

    누누, 주노, 다즐, 말랑, 박스터, 오잉, 깃짱와 코드 리뷰 스터디를 진행했다.
    -과연 도움이 될까 생각했지만 결과적으로는 코드 리뷰를 하면서 성장을 많이 한 것 같다.
    -투자한 시간 대비 가성비가 좋은 활동이었다.
    -누누가 스터디장인데 과연 꾸준히 이어나가려나?

    -

    레벨 인터뷰

    -

    인터뷰할 때 많이 떨지 않아서 좋았다.
    -남들 앞에서 이야기를 하거나, 면접을 보면 항상 엄청 떨어서 걱정했는데
    -기술적인 질문을 받았을 때 떨지 않고 잘 대답할 수 있었다.
    -우아한테크코스 생활을 하면서 다른 크루가 질문했을 때, 최대한 이해하기 쉽게 설명하려고 했던 경험이 도움이 된 것 같다.
    -이후 레벨 인터뷰를 진행할 때 다음과 같은 부분을 고려하면 더 좋을 것 같다.

    +

    · 약 12분

    개요

    +

    여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
    +경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

    +

    구현 결과

    +

    ./result.png

    +

    예시 데이터는 다음과 같다.
    +서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

    +
    List<Double> x = List.of(
    +        126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
    +        126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
    +);
    +List<Double> y = List.of(
    +        37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
    +        37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
    +);
    +List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
    +List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);
    +
    +

    IMAGE_SIZE & ROUTE_SIZE

    +
    private static final int IMAGE_SIZE = 800;
    +private static final int ROUTE_SIZE = 600;
    +
    +

    코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
    +IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
    +ROUTE_SIZE의 경우 상하좌우 100px 만큼의 간격을 위해 존재한다.
    +따라서 실제 경로 이미지의 크기는 600 * 600 사이즈로 생성된다.

    +

    ./600.png

    +

    사이즈 변경의 이유

    +

    255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

    +

    주요 클래스

    +

    요약

    +
    클래스명설명특이사항
    Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
    CoordinatesCoordinate의 일급 컬렉션-
    Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
    PositionsPositions의 일급 컬렉션-
    RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
    RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
    RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
    BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
    Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
    +

    의존관계

    + +

    Coordinates(위도, 경도의 일급 컬렉션)

    +

    List<Double> 2개(위도, 경도)인 형태로 관리하는 방법이 있었지만, 위치 점을 여러개 찍는 부분에서 로직이 복잡해 질 것 같아서 Coordinate(x, y)와 일급 컬렉션인 Coordinates로 관리하기로 했다.
    +Coordinates 클래스에는 다음 두 개의 인터페이스가 존재한다.

    +
      +
    • calculatePositions: 경로 이미지의 크기를 받아 실제 이미지 생성시 사용될 Positions를 반환
    • +
    • indexOf: 다른 Coordinates를 받아 동일한 위치점에 해당하는 인덱스를 반환하는
    • +
    +

    Positions 계산 로직은 다음과 같다.
    +위도, 경도 각각에 대한 부분을 이미지 생성시 필요한 값으로 변환한다.

    +
    // 호출
    +// List<Integer> xPositions = toPositions(xValues, maxDifference, routeImageSize);
    +// List<Integer> yPositions = toPositions(yValues, maxDifference, routeImageSize);
    +
    +private List<Integer> toPositions(List<Double> values, Double maxDifference, Integer routeImageSize) {
    +    Double minValue = Collections.min(values);
    +    return values.stream()
    +            .map(value -> normalizeCoordinate(value, maxDifference, minValue))
    +            .map(value -> mapToPosition(value, routeImageSize))
    +            .toList();
    +}
    +
    +private double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {
    +    return (coordinate - minValue) / maxDifference;
    +}
    +
    +private int mapToPosition(Double coordinate, Integer routeImageSize) {
    +    return (int) (coordinate * routeImageSize);
    +}
    +
    +

    위도로 예시든 내용이다.

    +
      +
    1. Collections.min(values) → 위도 리스트의 최소값을 구한다.
    2. +
    3. normalizeCoordinate → 각각의 위도 값에서 최소값을 빼고 0 ~ 1 사이 값으로 변환 후 위경도의 최대 차이로 나눈다.
    4. +
    5. mapToPosition → 그래프 크기를 받아 0 ~ 1 사이 값을 실제 이미지를 위한 위치값으로 변환한다.
    6. +
    +

    Positions(실제 이미지 생성에 사용할 위치)

    +

    Positions 클래스에는 다음 다섯 개의 인터페이스가 존재한다.

      -
    • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
    • -
    • 두괄식 표현
    • -
    • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
    • -
    • 설명할 수 있을만큼 시간 충분히 가지기
    • -
    • 인터뷰어의 질문 의도를 명확히 이해하지 못했다면 의도 다시 물어보기
    • -
    • 끝맺는 부분 연습하기(자신감 있게)
    • -
    • 기술적인 집착가지기
    • -
    • 기술적인 부분을 꼼꼼히 준비했으면 협업 관련 질문도 준비하기
    • +
    • align: 이미지 사이즈와 경로 이미지 사이즈를 받아 Position 값들을 중앙 정렬한다.
    • +
    • getPositionsByIndexes: 인덱스 리스트를 받아 입력받은 인덱스에 해당하는 값들을 반환한다.
    • +
    • size: 크기를 반환한다.
    • +
    • xPositions: x 값들을 반환한다.
    • +
    • yPositions: y 값들을 반환한다.
    -

    Problem

    -

    페어프로그래밍

    -

    우아한테크코스를 진행하면서 가장 어려운 활동 중 하나라고 생각한다.
    -페어는 매번 바뀌고, 미션의 복잡도도 증가하기 때문인 것 같다.
    -소통 능력, 시간관리가 부족했고, 만족스럽지 않았다.
    -하지만 페어를 진행하고, 회고를 하다 보니 나만의 노하우가 쌓이는 느낌이다.
    -레벨 2에서는 부족했던 부분을 개선하여 함께하고 싶은 페어가 되고 싶다.

    -

    집중하는 시간⏱️ 부족

    -

    레벨 1을 진행하면서 집중하는 시간이 많이 부족했다.
    -이른 아침과 오후에 개인적으로 집중할 수 있는 공간을 예약해서 온전히 나만의 시간을 가져야겠다.

    -

    Try

    -

    허브🌿와의 티타임?

    -

    소프트 스킬을 늘릴 방법을 생각하다가 대화를 나누지 못한 다른 크루들과 깜짝 커피챗을 하면 어떨까 생각했다.
    -예를 들어 잡담방에 저와 커피챗 하실 분 :) 하면서 올릴 수 있을 것 같다.
    -참여하는 사람이 있을지, 안 좋게 보는 게 아닐지 걱정되지만 그래도 재밌을 것 같다.
    -저랑 허브티 한잔 하실래요?

    -

    기술적인 부분

    -

    우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
    -시간의 여유가 될 때 책을 조금씩 읽어야겠다.
    -블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

    -

    레벨 1을 마무리하며

    -

    시간이 빠르게 흘러갔다.
    -타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
    -또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

    +

    중앙 정렬 로직은 다음과 같다.

    +
    public Positions align(int imageSize, int routeSize) {
    +    int xOffset = calculateOffset(Position::x, imageSize);
    +    int yOffset = calculateOffset(Position::y, imageSize);
    +
    +    return items.stream()
    +            .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))
    +            .collect(collectingAndThen(toList(), Positions::new));
    +}
    +
    +private int calculateOffset(ToIntFunction<Position> positionToInteger, int imageSize) {
    +    List<Integer> positions = items.stream()
    +            .mapToInt(positionToInteger)
    +            .boxed()
    +            .toList();
    +
    +    int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;
    +    return imageSize / 2 - midValue;
    +}
    +
    +

    상하좌우 여백을 동일하게 주기 위해서 offset 값을 구해서 x, y 값에 각각 더하는 형태로 중앙 정렬을 수행했다.
    +BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

    +

    ./800.png

    +

    따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

    +

    x 값 → 계산한 offset 그대로 더한다.
    +y 값 → imageSize(800)에서 y + offset 값을 뺀다.

    +

    RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

    +

    BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
    +그림을 그리기 위해 설정한 상수들이 존재한다.

    +
    // RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
    +// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
    +// 이를 RGBA라고 부른다.
    +private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
    +// 배경 투명색
    +private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
    +// 경로를 위한 STROKE
    +private static final int LINE_STROKE_WIDTH = 7;
    +private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    +// 위치 점을 위한 STROKE
    +private static final int POINT_STROKE_WIDTH = 20;
    +private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    +// 안티앨리어싱 등 화질 개선을 위한 설정
    +private static final Map<Object, Object> renderingHints = Map.of(
    +        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
    +        RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
    +        RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
    +);
    +
    +

    RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

    +
      +
    • drawLine: 선을 그린다.
    • +
    • drawPoint: 점을 찍는다.
    • +
    • dispose: 자원 할당을 해제한다.
    • +
    +

    dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

    +

    이미지 생성 Flow

    +

    1. 이미지 생성 준비

    + +

    2. 선 그리기 요청

    + +

    3. 위치 점 그리기 요청

    + +

    4. 업로드 요청

    + +

    전체 Flow

    +
    \ No newline at end of file diff --git a/page/4.html b/page/4.html index 4f0a97236..11126ad6a 100644 --- a/page/4.html +++ b/page/4.html @@ -13,91 +13,46 @@ - - + + -

    · 약 5분

    테스트 격리

    -

    테스트의 순서에 따라 성공 실패 여부가 결정되는 비결정적인(non-determinism) 테스트가 되어서는 안되고, 테스트는 항상 순서에 상관없이 독립적으로 수행되도록 보장되어야 한다. 일반적으로 자원의 공유, 외부 API, 시간 등으로 비결정적인 테스트가 된다. 이를 해결하기 위해 테스트 대역을 사용하거나, 컨텍스트를 재실행하는 @DirtiesContext, 자원을 초기화하기 위해 테스트 이후에 테이블을 롤백 하는 @Transactional등 다양한 방법이 있다.
    -해당 글에서는 스프링에서 데이터베이스 자원의 공유를 방지하기 위해 테스트 격리를 수행하는 부분에 대해 설명한다.

    -

    테스트끼리 서로 의존하면 안 된다.
    -서로 의존하게 된다면 하나의 테스트가 실패할 때, 또 다른 하나의 테스트가 실패할 수 있다.
    -다른 테스트에 의존하지 않고, 독립적으로 실행 가능한 테스트가 좋은 테스트다.

    -

    TestExecutionListener

    -

    스프링에서는 TextExecutionListner를 이용하여 각 테스트 실행 단계에서 이벤트를 수신할 수 있다.
    -이를 이용하면 JUnit의 @BeforeEach를 사용하는 것과 유사하게, 테스트의 생명주기 이전 또는 이후에 필요한 작업을 실행시킬 수 있다.

    -
    public interface TestExecutionListener {
    -    default void beforeTestClass(TestContext testContext) throws Exception {}
    -    default void prepareTestInstance(TestContext testContext) throws Exception {}
    -    default void beforeTestMethod(TestContext testContext) throws Exception {}
    -    default void beforeTestExecution(TestContext testContext) throws Exception {}
    -    default void afterTestExecution(TestContext testContext) throws Exception {}
    -    default void afterTestMethod(TestContext testContext) throws Exception {}
    -    default void afterTestClass(TestContext testContext) throws Exception {}
    +

    · 약 2분

    이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    +ISO-8601을 기반으로 작성
    +설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

    +

    날짜와 시간에 관련된 데이터를 다루는 국제 표준

    +

    LocalDate, LocalTime, LocalDateTime

    +

    날짜와 시간을 표현하는 클래스

    +

    Instant

    +

    유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
    +기계의 관점에서 시간 표현

    +

    Duration, Period

    +

    간격을 표현하는 클래스

    +

    TemporalAdjusters

    +

    복잡한 날짜 조정이 필요할 때 사용
    +필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

    +
    @FunctionalInterface
    +public interface TemporalAdjuster {
    +    Temporal adjustInto(Temporal temporal);
     }
     
    -

    AbstractTestExecutionListener 상속하여 구현

    -

    AbstractTestExecutionListener를 상속받아 테스트 격리 환경을 만들어주는 클래스로, 인터페이스인 TextExecutionListner와 달리 Ordered가 구현되어 있어 해당 클래스를 상속받아 구현한 클래스는 프레임워크가 제공하는 리스너 다음에 실행시키도록 해준다.
    -다음과 같이 데이터베이스에서 각각의 테이블에 해당하는 Truncate 쿼리를 만들어서 조회하고, Test 메서드가 끝날때 마다 해당 쿼리를 실행하여 테이블을 초기화시키도록 설정한다.

    -
    
    -public class DatabaseCleaner extends AbstractTestExecutionListener {
    -
    -    private static final String TRUNCATE_TABLE_QUERY = """
    -            SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ';') 
    -            FROM INFORMATION_SCHEMA.TABLES
    -            WHERE TABLE_SCHEMA = 'PUBLIC'
    -            """;
    -
    -    @Override
    -    public void afterTestMethod(TestContext testContext) {
    -        JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);
    -        List<String> truncateTableQueries = getTruncateTableQueries(jdbcTemplate);
    -        truncateTables(jdbcTemplate, truncateTableQueries);
    -    }
    -
    -    private JdbcTemplate getJdbcTemplate(TestContext testContext) {
    -        return testContext.getApplicationContext().getBean(JdbcTemplate.class);
    -    }
    -
    -    private List<String> getTruncateTableQueries(JdbcTemplate jdbcTemplate) {
    -        return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);
    -    }
    -
    -    private void truncateTables(JdbcTemplate jdbcTemplate, List<String> truncateTableQueries) {
    -        jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");
    -        truncateTableQueries.forEach(jdbcTemplate::execute);
    -        jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");
    -    }
    -}
    -
    -
    -

    Listener 등록

    -

    @TestExecutionListeners를 이용하여 사용자 정의 리스너를 등록할 수 있다.
    -mergeMode의 기본값은 REPLACE_DEFAULTS로 리스너가 이미 존재하는 경우 등록된 리스너로 변경된다.
    -MERGE_WITH_DEFAULTS로 설정한다면 Ordered 기준으로 순서가 결정된다.
    -이후 격리가 필요한 테스트들은 다음의 추상 클래스를 상속하여 사용하면 된다.

    -
    
    -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    -@TestExecutionListeners(
    -        value = DatabaseCleaner.class,
    -        mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
    -)
    -public abstract class AcceptanceTest {
    -
    -    @LocalServerPort
    -    private int port;
    -
    -    @BeforeEach
    -    public void setUp() {
    -        RestAssured.port = port;
    -    }
    -}
    -
    +

    DateTimeFormatter

    +

    날짜와 시간 포맷 클래스
    +특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

    +

    ZoneId, ZoneOffset

    +

    ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
    +ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

    +
    Instant instant = Instant.now();
    +LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
     

    참고 자료

    -

    The Spring TestExecutionListener, Baeldung
    -인수테스트에서 테스트 격리하기, 테코블
    -Eradicating Non-Determinism in Tests, martin fowler
    -@SpringBootTest의 테스트 격리시키기, MangKyu

    +
    \ No newline at end of file diff --git a/page/40.html b/page/40.html index 8b5c8d746..253ae29d2 100644 --- a/page/40.html +++ b/page/40.html @@ -13,83 +13,216 @@ - - + + -

    · 약 8분

    1, 2단계: https://github.com/woowacourse/java-chess/pull/441
    -3, 4단계: https://github.com/woowacourse/java-chess/pull/529

    -

    체스

    -

    체스 미션에는 가비와 페어가 매칭되었다!
    -체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
    -하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
    -미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

    -

    가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
    -최종적으로 결정한 부분은 다음과 같다.

    -

    각 기물의 이동 가능여부
    -Rank와 File은 각각 위치값을 가지고 있고, 값의 차이를 이용해서 각 기물의 이동 가능 여부를 계산했다.
    -직선 → Rank와 File 차이 중 하나가 0이어야 한다.
    -대각선 → Rank와 File 차이의 절대값이 같아야 한다. ex) abs(-2) == abs(2)
    -나이트 → 차이의 절대값이 하나는 2 나머지 하나는 1이어야 한다.

    -

    도착 칸의 기물 여부
    -아군 → 이동이 불가능하다.
    -적군 → 이동이 가능하다. 적군을 잡는다.

    -

    중간에 기물 존재 여부
    -이동 경로에 기물이 존재하면 안된다.

    -

    데이터베이스 사용
    -체스 미션은 특별하게 데이터베이스와 연결하는 부분이 있었다.
    -체스 게임의 상태를 다음의 두가지 방법으로 정할 수 있다고 생각했다.

    -
      -
    • 기물 전체를 저장하는 방법
    • -
    • 기보를 저장하고 게임을 불러와 기보대로 이동시키는 방법
    • -
    -

    기물이 이동할 때마다 값을 저장하고 싶었고, 기보를 저장하는 방법을 선택했다.
    -기물 전체를 저장하지 않은 이유는 다음과 같다.

    -
      -
    • 턴과 같은 부가적인 요소를 저장해야 한다.
    • -
    • 이동을 할 때 기물이 잡히는 경우 update 쿼리(이동 기물)와 delete(잡힌 기물) 2개의 쿼리를 날려야 한다.
    • -
    • 현재 구조에서 도메인의 변경이 크게(초기 상태를 구성하는 부분) 일어나야 한다.
    • -
    -

    정리하자면 기물 전체 저장과 기보 저장은 다음과 차이가 있다.
    -보드저장: 초기상태에서 32개의 Insert 쿼리(기물의 위치) + 기물 이동 시 움직임 변경(잡히는 경우 2개의 쿼리)
    -기보저장: 초기상태 애플리케이션에서 구성 + 저장된 기보를 select 쿼리로 조회해서 사용(1회) + insert 쿼리(이동 당 1회)

    -

    추가로 기보저장이 구현도 더욱 간단하다. 👍

    -

    부가적인 부분

    -

    리뷰어인 찰리🍫가 동시에 여러 게임이 진행된다면 어떨지? 에 대한 코멘트를 남겨주셔서 다양한 시도를 해봤다.

    -
      -
    • 누누의 도움으로 ConnectionPool 구현
    • -
    • ThreadLocal 사용해서 쓰레드 별 세션 관리
    • -
    • 실제로 애플리케이션 내에서 체스 게임이 진행되는 Board를 ConcurrentHashMap으로 저장(사실 이 부분은 현재 구조에서 필요없지만 2명이 서로 게임하는 경우를 생각해서 넣어보았다.)
    • -
    -

    두 명이 서로 같은 방에 입장하여 게임을 진행한다면 출력하는 부분이 까다로워질 것 같다고 예상되어(Board에 옵저버 패턴을 사용해야되나?) 해볼 엄두가 나지 않았다.

    -

    부족했던 부분

    -

    꼼꼼하게 코드를 작성하지 못한 부분
    -DB 관련 부분을 꼼꼼하게 코딩을 하지 못했다.
    -도메인 로직에만 집중하다보니 정적 중요한 DB의 코드의 예외처리, 빈 값을 반환 하는 부분을 꼼꼼하게 처리하지 못했다.
    -하지만 찰리의 꼼꼼한 리뷰로 DB부분과 나만의 JdbcTemplate을 깔끔하게 구현할 수 있었다.

    -

    시간에 대한 부담감
    -초반에는 여유롭지만 제출 마감에 가까워질 수록 사람이 급해지는 것 같다.
    -다음 페어프로그래밍할 땐 속도를 조절하고, 마음에 여유를 가져야겠다.

    -

    새로 학습한 부분

    -

    DAO 중복 제거

    -

    프롤로그에 을 작성했다.
    -DAO를 작성하는데 try-catch-resources와 여러 코드가 중복되서 제거하고싶었다.
    -템플릿 콜백 패턴으로 깔끔하게 중복을 제거할 수 있었다.👍

    -

    페어에게 배울 부분

    -

    페어 생각하기
    -가비는 누구보다 페어를 생각하고, 배려해주는 페어였다.
    -중간 중간 당 떨어질까봐 걱정도 해주고, 나의 컨디션도 확인해줬다!

    -

    미션 몰입하기
    -최근에 미션에 잘 몰입하지 못했다.
    -가비는 페어를 진행할 때 미션에 대한 몰입도가 매우 좋았다.
    -집에가서도 체스 이동에 대한 로직을 어떻게 구현할 지 생각한 뒤 꼼꼼해서 정리해서 나에게 보내주었다.
    -덕분에 나도 가비의 생각을 알 수 있어서 미션을 진행하는데 가속도가 붙은 것 같다.
    -또한 미션을 잘 마무리하고 싶은 마음이 전달되서 그런지 나도 덩달아 열심히 미션을 할 수 있었다.😄

    -

    솔직함
    -먼저 회고하자고 말 걸어줘서 정말 고마웠다고 표현해주는 부분
    -모르는게 있으면 솔직하게 말해주는 부분
    -나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
    -솔직함은 페어할 때 중요한 부분인 것 같다.

    -

    마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

    +

    · 약 12분

    이전 글

    +

    경로 이미지 생성하기 - 기술 선택
    +경로 이미지 생성하기 - 구현

    +

    개요

    +

    현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
    +경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
    +따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.

    +

    주기능의 응답속도 개선

    +

    여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
    +하지만 현재 여행 종료와 감상 생성의 응답 속도가 경로 이미지 생성 시간에 영향을 받고 있다.
    +경로 이미지 생성은 비동기 처리하여도 애플리케이션 사용에 문제가 되지 않는다.
    +소요 시간이 1초 이상 걸리는 경우가 존재하기에 이미지 생성을 비동기 처리하고 여행 종료와 감상 생성 기능의 응답 시간을 개선하는 것이 더 중요하다.

    +

    확장성 대비

    +

    현재 10분 간격으로 위치 정보를 서버에 저장하고 있다.
    +조금 더 짧은 간격으로 위치 정보를 그리는 경우 하나의 여행에 많은 위치 정보가 저장될 수밖에 없고 따라서 경로 이미지 생성에 걸리는 시간이 더 길어질 수 있다.
    +따라서 추후에 더 짧은 간격으로 위치 정보를 저장하는 경우를 대비하여 이미지 생성은 비동기로 처리하는 것이 합당하다.

    +

    비동기 처리

    +

    @Async를 사용하면 간단하게 메서드를 비동기로 동작하도록 만들 수 있다.

    +

    비동기 설정

    +

    사용하기 전에 설정 파일을 하나 만들어서 EnableAsync 설정을 해야한다.
    +해당 설정을 적용하면 비동기적으로 실행하려는 메서드에 @Async 애너테이션을 붙여주기만 하면 비동기로 동작한다.

    +
    @EnableAsync
    +@Configuration
    +public class AsyncConfig {
    +}
    +
    +

    스프링 부트를 사용하지 않는 경우 기본적으로 비동기 처리를 할 때 매번 새로운 스레드를 생성하기 때문에 스레드 풀 설정을 따로 해줘야 한다. 하지만 스프링 부트를 사용하는 경우 ThreadPoolTaskExecutor를 따로 설정하지 않아도 기본적으로 스프링 부트가 생성을 도와준다.

    +
    +

    In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing. +7.7. Task Execution and Scheduling, Spring Boot Docs

    +
    +

    @Async 적용

    +

    이미지 생성기에 Async 애너테이션을 붙여 비동기로 동작하도록 한다.

    +
    @Async
    +public void generate(
    +        List<Double> latitudes,
    +        List<Double> longitudes,
    +        List<Double> pointedLatitudes,
    +        List<Double> pointedLongitudes,
    +        Long tripId
    +) {
    +    // 이미지 생성
    +    RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);
    +    Coordinates coordinates = Coordinates.of(latitudes, longitudes);
    +    Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);
    +    drawImage(coordinates, routeImageDrawer, pointedCoordinates);
    +
    +    // 이미지 저장
    +    String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());
    +
    +    // 자원 할당 해제
    +    routeImageDrawer.dispose();
    +
    +    // 데이터베이스 값 변경
    +    Trip trip = tripRepository.findById(tripId)
    +        .orElseThrow();
    +    trip.changeRouteImageUrl(imageUrl);
    +    tripRepository.save(trip);
    +}
    +
    +

    비동기 처리시 문제점

    +

    현재 이미지 생성을 하고 저장 후, 저장 경로를 DB에 반영해야 한다.
    +따라서 패키지 간 순환 참조 형태가 되며 의존성 방향이 문제가 생긴다.

    + +

    이를 해결하기 위해서는 인터페이스를 사용하는 방법과 이벤트를 사용하는 방법이 있다.
    +인터페이스를 사용한다면 다음과 같은 구조가 된다.

    + +

    패키지 간 의존성은 해결되었지만, 이미지 경로 저장을 위해 tripId를 받아야하는 등의 논리적인 의존성은 아직 해결되지 않았다.
    +따라서 이벤트를 사용하기로 했다.

    +

    이벤트 사용

    +

    스프링의 애플리케이션 이벤트를 사용하면 비즈니스 로직의 비관심사(ex. 경로 이미지 생성)을 효율적인 방법으로 처리할 수 있다.

    +

    이벤트 발행

    +

    이벤트를 사용하려면 먼저 이벤트를 발행해야 한다.
    +스프링에서는 ApplicationEventPublisher 인터페이스를 사용하여 이벤트를 발행할 수 있다.
    +해당 인터페이스는 내부적으로 ApplicationContext가 구현하여 이벤트를 발행한다.

    +
    public void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {
    +    ...
    +
    +    // 이벤트 발행
    +    applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));
    +}
    +
    +public record TripUpdateEvent(Long tripId) {
    +}
    +
    +

    이벤트를 발행할 때 발행하는 이벤트명이 중요하다.
    +이벤트를 구독하는 도메인의 행위를 담고 있는 이벤트를 발행(ex. RouteImageGenerateEvent)한다면 논리적인 의존 관계가 남아있기에 이벤트를 적절히 사용했다고 보기 어렵다.
    +발행하는 이벤트명은 주기능이 어떤 행위(ex. TripUpdateEvent)를 했는지에 대한 정보가 담겨있는 이벤트명으로 발행하는 것이 중요하다.

    +

    이벤트 구독

    +

    이벤트를 구독하여 실행하는 메서드는 비동기로 처리하기 위하여 @Async 애너테이션을 적용했다.
    +이벤트의 구독은 여행이 정상적으로 종료될 때 여행에 대한 정보를 가지고 경로 이미지를 생성하기 위해 @TransactionalEventListener를 사용했다.

    +

    TransactionPhase을 사용하여 트랜잭션 이벤트를 어떤 단계에서 수신하고 처리할지를 지정할 수 있다.

    AFTER_COMMIT(기본값): 트랜잭션이 정상적으로 커밋 되는 경우 이벤트 실행
    +AFTER_ROLLBACK: 트랜잭션이 롤백되는 경우 이벤트 실행
    +AFTER_COMPLETION: 트랜잭션이 커밋 또는 롤백 되었을 경우 이벤트 실행
    +BEFORE_COMMIT: 트랜잭션이 커밋 되기 전 이벤트 실행

    +

    이미지 생성의 경우 트랜잭션에서 제외하기 위해 @Transactional 애너테이션을 사용하지 않았다.

    +
    @Component
    +public class TripUpdateEventHandler {
    +
    +    private final RouteImageGenerator routeImageGenerator;
    +    private final TripRepository tripRepository;
    +
    +    public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {
    +        this.routeImageGenerator = routeImageGenerator;
    +        this.tripRepository = tripRepository;
    +    }
    +
    +    @Async
    +    @TransactionalEventListener(phase = AFTER_COMMIT)
    +    public void handle(TripUpdateEvent tripUpdateEvent) {
    +        Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());
    +
    +        String imageUrl = routeImageGenerator.generate(
    +                trip.getLatitudes(),
    +                trip.getLongitudes(),
    +                trip.getPointedLatitudes(),
    +                trip.getPointedLongitudes()
    +        );
    +
    +        trip.changeRouteImageUrl(imageUrl);
    +        tripRepository.save(trip);
    +    }
    +}
    +
    +

    이벤트를 사용함으로써 패키지 간 순환 참조 문제가 다음과 같이 해결되었다.
    +또한 주기능과 부기능을 분리함으로써 경로 이미지 생성 기능에 대한 전체적인 결합도를 낮추었다.

    + +

    테스트

    +

    비동기로 동작하는 메서드를 테스트하기 위해서는 아래와 같은 방법이 있다.

    + + +
    @ContextConfiguration(classes = TestSyncConfig.class)
    +@SpringBootTest
    +public class TripUpdateEventHandlerIntegrationTest {
    +
    +    ...
    +
    +    @Test
    +    void 여행수정_이벤트를_발생시키면_이미지를_생성_요청을_한다() {
    +        // given
    +        TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);
    +        given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))
    +                .willReturn(여행());
    +
    +        // when
    +        transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));
    +
    +        // then
    +        then(routeImageGenerator)
    +                .should(times(1))
    +                .generate(any(), any(), any(), any());
    +    }
    +}
    +
    +

    처음에는 테스트에서만 동기로 설정 후 검증하려고 했다.
    +통합 테스트에선 트랜잭션이 정상 종료되었을 때 비동기로 이벤트를 구독하여 이미지 생성 메서드를 호출하는지 검증이 필요했기 때문에 최종적으로 Mockito.timeout 메서드를 사용하여 비동기 메서드가 통과될 때까지 대기하는 방향으로 변경했다.

    +

    결과

    +

    ./time.png

    +

    위 응답 시간은 위치 정보 1000개를 기준으로 테스트한 값이다.
    +응답 시간에 이미지 생성 시간이 포함되지 않아서 성능이 개선된 것을 볼 수 있다.

    +

    참고 자료

    +

    7.7. Task Execution and Scheduling, Spring Boot Docs
    +Spring Events, Baeldung
    +회원시스템 이벤트기반 아키텍처 구축하기

    \ No newline at end of file diff --git a/page/41.html b/page/41.html index 8e27a38f5..2ac8e0d6a 100644 --- a/page/41.html +++ b/page/41.html @@ -13,100 +13,91 @@ - - + + -

    · 약 9분

    GRASP(General Responsibility Assignment Software Pattern)

    -

    크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

    -

    각 패턴마다 Solution과 Problem로 구성되어 있다.

    -

    정보 전문가 패턴(Information Expert)

    -

    Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

    -

    A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

    -

    정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

    -

    필요한 정보를 가진 객체들로 책임이 분산된다.

    -

    창조자 패턴(Creator)

    -

    Q: 누가 객체 A를 생성하는가?

    -

    A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

    -
      -
    • B가 A 객체를 포함 또는 참조한다.
    • -
    • B가 A 객체를 기록한다.
    • -
    • B가 A 객체를 긴밀하게 사용한다.
    • -
    • B가 A 객체의 초기값을 가지고 있다.
    • -
    -

    생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

    -

    낮은 결합도 패턴(Low Coupling)

    -

    Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

    -

    A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

    -
    -

    결합도(Coupling) -객체 사이의 의존성이 과한 경우 결합도가 높다고 말한다.

    -
    -
      -
    • 오브젝트 p.17
    • -
    -
    -
    -

    결합도를 낮춘다면 다음과 같은 이점이 있다.

    -
      -
    • 다른 구성 요소의 변화에 영향을 받지 않는다.
    • -
    • 재사용이 편리해진다.
    • -
    • 해당 클래스에 대한 이해가 쉬워진다. (의존하는 클래스가 적기 때문에)
    • -
    -

    높은 응집도 패턴(High Cohesion)

    -

    Q. 객체를 관리하기 쉽게 하려면 어떻게 해야 할까?

    -

    A. 높은 응집도를 유지할 수 있게 책임을 할당해야 한다.

    -
    -

    응집도(Cohesion) -연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도가 높다고 말한다.

    -
    -
      -
    • 오브젝트 p.26
    • -
    -
    -
    -

    변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

    -
      -
    • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
    • -
    • 유지보수가 쉬워진다.
    • -
    • 낮은 결합도 또한 지원한다.
    • -
    • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.
    • -
    -

    컨트롤러 패턴(Controller)

    -

    Q. 사용자의 요청을 처리하는 것은 누가 담당해야 하는가?

    -

    A. 사용자의 요청을 처리하는 Controller 객체를 만들어서 사용해야 한다.

    -

    어떤 서브시스템이 존재한다고 가정할 때

    -
      -
    • 직접적으로 객체에 접근하여 프로그램을 사용한다면 결합도가 상승한다.
    • -
    • 서브 시스템에 들어오는 요청을 처리해주는 컨트롤러가 있다면 사용하는 입장에서는 해당 컨트롤러만 알면 된다.
    • -
    • 만약 서브 시스템의 변경이 생겼을 때 외부에 미치는 영향도 줄어든다.
    • -
    -

    다형성 패턴(Polymorphism)

    -

    Q. 객체의 타입에 따라 행동이 바뀐다면 책임을 어떻게 할당해야 할까?

    -

    A. OOP가 지원하는 다형성을 적극적으로 활용한다. (인터페이스를 두고 행동에 대한 부분을 구현)

    -

    객체의 종류에 따라 분기하는 조건문이 아닌 다형성을 사용하는 것이 좋은 방법이다.

    -

    새로운 타입이 추가되었을 때 조건문을 사용한다면 기존의 조건문을 수정해야 하지만 다형성을 활용하면 쉽게 확장할 수 있다.

    -

    변경 보호 패턴(Protected Variations)

    -

    Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

    -

    A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

    -

    간접 참조 패턴(Indirection)

    -

    Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

    -

    A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

    -

    중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

    -

    중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

    -

    순수한 가공물 패턴(Pure Fabrication)

    -

    Q. 책임을 할당한 도메인 객체가 Low Coupling, High Cohesion, 재사용성 등의 목적을 위반한다면 어떻게 해야 할까?

    -

    A. 도메인 개념을 포함하지 않는 클래스를 하나 만들고 매우 응집된 책임을 할당할 수 있다.

    -

    행동을 추가할 때, 해당 책임을 수행할 도메인 개념이 존재하지 않는다면 도메인과 무관한 인공적인 객체를 만든다음 해당 객체에게 책임을 할당한다.

    -

    객체가 데이터베이스에 저장해야 할 값을 가지고 있다고, 정보 전문가 패턴을 적용하여 데이터베이스에 저장하라는 책임을 가지라고 하지 않는다.

    -

    예) 상점과 고객 클래스가 있고 서로 다른 통화를 사용하고 있다고 가정

    -
      -
    • 서로 다른 통화를 사용하고 있기 때문에 거래를 하려면 환전을 해야한다.
    • -
    • 두 클래스 다 환전에 대한 책임을 부여하기 애매하다면 환전을 책임하는 클래스를 추가하고 사용할 수 있다.
    • -
    -

    참고 자료

    -

    오브젝트 5장. 책임 할당하기, 조영호

    -

    Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman

    -

    GRASP, 한빛 네트워크

    +

    · 약 6분

    CloudWatch

    +

    AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
    +지표를 감시하여 알림을 보내는 기능도 제공한다.
    +프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
    +요금 정보에 대한 자세한 정보는 다음 링크에서 확인할 수 있다.

    +

    CloudWatch Metrics

    +

    기본적으로 5분마다 지표에 대한 정보가 수집된다.
    +세부 모니터링(Detailed Monitoring)을 활성화하면 1분마다 지표를 수집한다.
    +대시보드에서 InstanceId로 검색하여 수집된 지표를 확인할 수 있다.

    +

    ./cloudwatch1.png

    +

    CPUUtilization, NetworkIn, NetworkOut과 같은 기본적인 지표를 제공하고, 메모리, 디스크 공간과 같은 지표를 확인하려면 사용자 지정 지표를 설정해야 한다.

    +

    CloudWatch Agent 설치

    +

    CloudWatch Agent 사용자 지정 지표와 로그를 수집할 수 있다.

    +

    IAM 역할 설정

    +

    기본적으로 EC2 인스턴스가 CloudWatchAgentServerPolicy에 대한 권한이 있어야 한다.
    +IAM → 역할에서 역할 생성을 클릭한다.

    +

    ./cloudwatch2.png

    +

    CloudWatchAgentServerPolicy 권한 정책을 선택하고, 적당한 역할 이름을 입력해서 역할을 생성한다.

    +

    ./cloudwatch3.png

    +

    EC2 인스턴스 목록으로 들어가서, CloudWatch Agent를 설치할 EC2 인스턴스를 클릭한다.
    +작업 → 보안 → IAM 역할 수정에서 이전에 생성한 역할을 지정한다.

    +

    ./cloudwatch4.png

    +

    설치

    +

    환경은 다음과 같다.

    +

    OS: ubuntu 22.04
    +인스턴스 유형: t4g.small (ARM64)

    +

    아래 명령어를 입력하여 설치한다.

    +
    wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb
    +sudo dpkg -i -E ./amazon-cloudwatch-agent.deb
    +
    +

    사용 설명서에 각 인스턴스 유형마다 다운로드 링크가 자세하게 안내되어 있다.

    +

    Wizard

    +

    CloudWatch Wizard를 사용하면 간단하게 설정 파일 생성할 수 있다.
    +로그를 수집하도록 설정하는 경우 Wizard 실행 명령어 입력 전 log 파일의 절대 경로를 복사해두는 것이 좋다.
    +아래의 명령어를 입력하여 Wizard를 실행할 수 있다.

    +
    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
    +
    +

    설정을 진행하다 보면 설정 파일이 어떻게 구성될지 확인할 수 있다.
    +로그를 추가할 것이냐고 물어보는 입력창이 나오면 준비해뒀던 로그 파일의 절대 경로를 입력한다.

    +

    ./cloudwatch5.png

    +

    중간에 SSM parameter store에 설정 파일을 저장할 것이냐고 물어보는 창이 나온다.

    +
    Do you want to store the config in the SSM parameter store?
    +1. yes
    +2. no
    +
    +

    추가적으로 설정하지 않는 경우 2번을 선택한다.
    +Parameter Store 관리에 대한 내용은 다음의 문서를 참고하면 좋을 거 같다.
    +설정이 완료되면 /opt/aws/amazon-cloudwatch-agent/bin/config.json 에 설정에 대한 내용이 저장된다.

    +

    설정 파일 적용

    +

    아래의 명령어를 입력하여 설정파일을 적용할 수 있다.
    +file 뒤에는 설정 파일에 대한 절대경로(아래 명령어 기준 기본 생성 위치)를 입력하면 된다.

    +
    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
    +
    +

    types.db: no such file or directory 에러

    +

    다음과 같은 에러가 발생한다면 types.db 파일을 생성해서 문제를 해결할 수 있다.

    +
    Error running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory
    +
    +

    types.db 파일 생성

    +
    sudo mkdir /usr/share/collectd
    +sudo touch /usr/share/collectd/types.db
    +
    +

    지표 확인

    +

    CloudWatch Metrics에 가보면 CWAgent라는 네임스페이스가 추가된 것을 볼 수 있다.

    +

    ./cloudwatch6.png

    +

    다음과 같이 설정 파일에 네임스페이스를 추가하여 지표에 대한 네임스페이스를 변경할 수 있다.

    +
    {
    +  "metrics": {
    +    "namespace": "2023-hello-world",
    +    ......
    +   },
    +} 
    +
    +

    로그

    +

    CloudWatch → 로그 그룹으로 가면 Wizard로 추가한 로그를 확인할 수 있다.

    +

    ./cloudwatch7.png

    +

    참고 자료

    +

    CloudWatch란 무엇입니까?
    +Amazon CloudWatch 요금
    +Linux 인스턴스 지표
    +서버에 CloudWatch 에이전트 설치 및 실행
    +CloudWatch Agent를 Parameter Store에서 관리해 보기
    +CloudWatch에이전트 구성 파일

    \ No newline at end of file diff --git a/page/42.html b/page/42.html index c406f8d4d..b0cb84a49 100644 --- a/page/42.html +++ b/page/42.html @@ -13,59 +13,42 @@ - - + + -

    · 약 6분

    1단계: https://github.com/woowacourse/java-blackjack/pull/427
    -2단계: https://github.com/woowacourse/java-blackjack/pull/537

    -

    블랙잭

    -

    블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
    -이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

    -

    블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
    -후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

    -

    미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
    -"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

    -

    곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
    -중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
    -부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

    -

    이 부분에 대해 생각이 많아져서 전 리뷰어인 터틀🐢과도 대화를 나누었다.
    -터틀은 제어할 수 없는 부분보다 제어할 수 있는 부분(궁극적인 목표인 좋은 코드를 작성하는 것)에 집중해보라고 하셨다.

    -

    좋은 코드, 좋은 페어에 대한 부분을 일단 지속적으로 생각해봐야겠다.

    -

    부족했던 부분

    -

    페어 신경쓰기
    -이번 페어할 때 적극적으로 의견을 내보도록 했다. 그렇기에 너무 의견을 강하게 밀어붙인 느낌이 들어서 미안했다.
    -후추가 압박을 느꼈을 수도 있을 것 같다는 생각이 든다.
    -중간 중간 작은 회고를 진행해보는 것이 좋을까?

    -

    체력 관리
    -요즘 잘 못먹는 것 같다.
    -앞으로 살 날이 많은데 잘 챙겨먹고, 힘내야겠다.

    -

    중간 중간 돌아보기
    -이번 미션과 관련된 내용은 아니지만 우테코를 잘 활용 하고 있는지 생각을 해봐야겠다.
    -내가 우테코에 지원한 이유를 항상 잊지 않아야겠다.

    -

    새로 학습한 부분

    -

    상태 패턴
    -객체의 내부 상태에 따라 스스로 행동을 변경하도록 하는 패턴으로 if/else/switch와 같은 조건문을 효과적으로 제거할 수 있다.
    -블랙잭 미션을 진행하면서 상태 패턴에 대한 부분을 처음 적용해보았다.
    -처음 적용하기 전에는 별로라고 생각했는데, 생각보다 괜찮은 것 같다.

    -

    일관성, 가독성, 추상화
    -이번 리뷰어는 검프🍫 였다!
    -검프의 리뷰는 간결함에 관련된 내용이 많았다.
    -일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
    -읽기 좋고, 간결한 방향으로 코드를 작성하는 방법을 배운 것 같다.
    -코드를 바라보는 시점이 하나 늘어난 기분이다!(앞으로 적용하는 것은 나의 몫이지만)

    -

    페어에게 배울 부분

    -

    생각 정리
    -중간 중간 현재 상황에 대해 그림을 그리거나, 글을 적으면서 정리한다.
    -페어와 동일한 부분을 이해하고 있는지 확인한다.
    -진행하는데 매우 도움이 되었던 것 같다.
    -나도 다음 페어때부터 펜이랑 종이를 준비해야겠다.

    -

    가감없이 의견을 말해주는 부분
    -진행 상황에 대한 부분, 진행 속도, 지금 자신이 이해하고 있는 부분을 말해줘서 편했다.
    -회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

    -

    도메인 언어에 신경쓰는 부분
    -클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
    -요구사항 정리도 깔끔하게 잘하는 것 같다.

    -

    후추 최고 👍

    +

    · 약 4분

    회고

    +

    지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
    +레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
    +부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
    +내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

    +

    아쉬운 점

    +

    문서화

    +

    개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
    +프로젝트를 진행하면서 내가 한 부분을 조금 더 꼼꼼하게, 이해하기 쉽게 문서화를 했더라면 팀원들에게 더욱 도움이 되었을 텐데 이 부분에 시간을 조금 더 투자하지 못했던 부분에서 아쉬움이 많이 들었다.
    +방학 기간 동안 문서화를 하지 못했던 부분을 개인 블로그 올리면서 조금 더 채워보려고 한다.

    +

    내가 못하는 부분이라면 시간을 들이자

    +

    잘 못하는 부분이라면 시간을 들여서라도 중간은 가도록 해야겠다는 생각이 많이 들었다.
    +말을 하기 전에 정리해서 의견을 내는 것, 발표 준비, 감정 조절 등등 +못하는 부분을 인지하고, 개선하자.

    +

    컴포트 존 벗어나기

    +

    조금 더 도전적으로 목표를 잡았으면 좋았을 것 같다.
    +매번 근거를 가지고 기술을 도입하고, 코드를 작성하려고 노력했다.
    +하지만 지속적으로 개선하려고 하는 부분이 다소 부족했다.

    +

    좋았던 점

    +

    좋았던 점도 문서화

    +

    팀 블로그도 먼저 도입하자고 제안하고, 내가 했던 부분은 문서화를 꽤 많이 해서 팀원들과 공유할 수 있었다.
    +백엔드 크루 4명이서 같이 한 부분에 대해서는 기능 구현한다고 문서화가 조금 미흡해서 보충을 해야겠다.

    +

    내가 디자인한 트립드로우 로고

    + +

    트립드로우 로고를 만들었다.
    +팀원들이 대표 색상(파란색)을 정해줬고, 주말 동안 신나게 로고 디자인을 했던 것 같다.
    +아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

    +

    기술 선택의 이유

    +

    기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
    +100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

    +

    마치며

    +

    플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
    +안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

    \ No newline at end of file diff --git a/page/43.html b/page/43.html index ac8fc72c6..08fd234f6 100644 --- a/page/43.html +++ b/page/43.html @@ -13,149 +13,439 @@ - - + + -

    · 약 11분

    1단계: https://github.com/woowacourse/java-ladder/pull/97
    -2단계: https://github.com/woowacourse/java-ladder/pull/234

    -

    사다리 타기

    -

    사다리 타기 미션에서는 우가와 페어가 매칭되었다.
    -이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

    -

    우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

    -

    2단계에서는 2가지 방법으로 구현해봤다.

    -
      -
    1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
    2. -
    3. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법
    4. -
    -

    Position 기준으로 사다리 게임을 진행하는 방법

    -

    사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
    -구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
    -또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

    +

    · 약 21분

    복제(Replication)

    +

    한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
    +원본 데이터를 가지는 서버를 Primary 또는 Source 라고 부르고, 복제된 데이터를 가지는 서버를 Secondary 또는 Replica 라고 부른다.

    +

    복제를 하는 이유

    +

    1. 스케일 아웃

    +

    사용자의 트래픽이 증가하는 경우, 데이터베이스에 가해지는 부하도 자연스럽게 증가한다.
    +이를 처리하기 위해 복제를 통한 스케일 아웃을 적용하여 애플리케이션에서 사용하는 쿼리들을 각각의 데이터베이스로 분산 시킬 수 있다.

    +

    2. 데이터 백업

    +

    실제 운영되는 서비스가 사용하고 있는 DB에서 백업을 진행하는 경우, 서비스에 영향을 미칠 수 있다.
    +따라서 실제 서비스에 영향이 가지 않도록 복제를 통해 Replica 서버를 구축하여, Replica 서버에서 복제를 진행하는 방법으로 영향을 최소화 할 수 있다.

    +

    3. 데이터 분석

    +

    백업과 마찬가지로 복잡하고 무거운 분석용 쿼리의 서비스에 영향을 미칠 수 있다.
    +마찬가지로 복제를 사용해 분석용 쿼리를 사용할 수 있는 환경을 만들 수 있다.

    +

    4. 데이터의 지리적 분산

    +

    빠른 응답을 위해 애플리케이션 서버에 가깝게 서버를 구성하거나, 고가용성(High Availability)을 위해서도 사용된다.

    +

    바이너리 로그 파일 위치 기반 복제

    +

    MySQL 서버에서 발생하는 변경사항에 대한 로그 파일을 바이너리 로그라고 한다.
    +바이너리 로그를 통해 데이터 변경, 테이블 구조 변경, 계정이나 권한 변경에 대한 정보가 저장된다.
    +MySQL의 복제는 바이너리 로그 기반으로 구현되어 있다. 이를 Replica 서버로 전달하고 바이너리 로그 기반으로 데이터를 변경 사항을 반영한다.

    + +

    Binary Log Dump Thread: 바이너리 로그의 내용을 Replica 서버로 전달
    +Replication I/O Thread: Binary 로그 이벤트를 가져와 로컬 서버의 파일(Relay Log)로 저장
    +Replication SQL Thread: 릴레이 로그 파일의 이벤트를 읽고 실행

    +

    바이너리 로그 방식의 문제점

    +

    바이너리 로그 방식은 서버에 장애가 발생했을 때 복제 토폴로지 변경이 까다롭다.
    +토폴로지란 네트워크의 요소들을 물리적으로 연결해 놓은 것, 또는 그 연결 방식을 말한다.

    + +

    위와 같이 Source 서버, Replica 2대가 존재하고, C 서버에 복제 지연이 되었을 때 문제가 발생한다.

    +

    A 서버에서 장애가 발생한다면 B 서버를 Source 서버로 승격하고, C에게 조회 쿼리를 분산시킨다.
    +하지만 여기서 C 서버에는 A 서버와 동기화가 안되었으니 조회 시 문제가 발생한다.
    +뒤늦게 B 서버와 동기화를 하려고 해도, 어떤 바이너리 로그, 어떤 위치와 동기화해야하는지 알기 어렵다.

    +

    글로벌 트랜잭션 아이디(GTID) 기반 복제

    +

    GTID 방식을 사용하여 참여한 모든 데이터베이스가 발생한 이벤트에 고유한 식별값을 부여한다면, 동기화에 대한 문제를 간단하게 해결할 수 있다.
    +위의 예시와 같이 복제 지연과 함께 장애가 발생한다해도 특정 GTID 부터 복제를 재개하면 된다.

    +

    복제 토폴로지에 참여한 모든 서버에서 고유하도록 각 이벤트에 부여된 식별값
    +[source_id]:[transaction_id]로 구성되며, source_id는 서버를 식별하기 위한 값이고 transaction_id는 커밋된 트랜잭션을 식별하기 위한 값으로 1씩 증가하는 형태로 발급된다.

    +

    복제 토폴로지

    +

    싱글 레플리카 복제 구성

    +

    가장 간단한 구성으로 제일 많이 사용하는 형태다.
    +replica 서버를 읽기 전용, 예비 서버, 백업 용도로 많이 사용한다.

    + +

    멀티 레플리카 복제 구성

    +

    2개의 replica 서버를 사용하는 형태다.
    +하나의 replica는 예비 용도로 남겨두는 형태다.
    +추후에 트래픽이 증가하는 경우 예비 용도의 replica를 사용함으로 읽기 요청의 부하 분산을 할 수 있다.

    + +

    체인 복제 구성

    +

    replica 서버가 많은 경우 바이너리 로그를 전달하는 작업 자체가 부하가 될 수 있다.
    +따라서 1:M:M 구조로 체인 복제 구성을 고려할 수 있다.

    + +

    듀얼 소스 복제 구성

    +

    2개의 MySQL 서버 모두 읽기와 쓰기가 가능하도록 하는 구성이다.
    +각 서버에서 변경된 데이터는 다른 서버에 반영된다.
    +목적에 따라 ACTIVE-ACTIVE 형태 또는 ACTIVE-PASSIVE 형태로 사용할 수 있다.
    +ACTIVE-PASSIVE 형태인 경우 싱글 레플리카 복제 구성과 동일해보이지만, ACTIVE 서버에서 문제가 발생하면 설정의 변경없이 PASSIVE 서버로 쓰기 작업을 전환할 수 있다는 것이 장점이다.

    + +

    ACTIVE-ACTIVE: 2개의 서버 모두 쓰기 작업을 수행하는 형태
    +ACTIVE-PASSIVE: 하나의 서버에서만 쓰기 작업을 수행하는 형태

    +

    멀티 소스 복제 구성

    +

    여러개의 source 서버와 하나의 replica 서버를 사용하는 구성이다.
    +이는 source 서버의 데이터를 한 곳에 백업하는 용도로 사용, 여러 서버에 존재하는 데이터를 통합, 샤딩되어있는 테이블 데이터를 통합할 때 사용한다.

    + +

    바이너리 로그 방식 Replication 구성하기

    +

    mysql 2대를 이용하여 replication을 구성하고, spring boot application으로 source, replica 데이터베이스에 접근해보는 예제이다.
    +https://github.com/bbiac/db-replication

    +

    MySQL 환경 구성

    +

    MySQL 버전은 8.1을 사용했다.
    +13306, 13307 포트를 사용해서 MySQL 서버 2대를 띄웠다.
    +또한 사실 IP 대역으로 통신할 수 있도록 커스텀 네트워크를 추가했다.

    +
    version: '3.8'
     
    -    LadderGame --> Position
    -    Ladder --> Position
    -    Items --> Position
    -    Line --> Position
    -    Players --> Position
    +services:
    +  source:
    +    platform: linux/x86_64
    +    image: mysql:latest
    +    restart: always
    +    container_name: mysql-source
    +    environment:
    +      TZ: 'Asia/Seoul'
    +      MYSQL_DATABASE: 'db'
    +      MYSQL_USER: 'user'
    +      MYSQL_PASSWORD: 'password'
    +      MYSQL_ROOT_PASSWORD: 'password'
    +    ports:
    +      - "13306:3306"
    +    volumes:
    +      - db-source:/var/lib/mysql
    +      - db-source:/var/lib/mysql-files
    +      - ./docker/source.cnf:/etc/mysql/my.cnf
    +    networks:
    +      - mysql_network
     
    -    LadderGame --> LadderGameResult
    +  replica:
    +    platform: linux/x86_64
    +    image: mysql:latest
    +    restart: always
    +    container_name: mysql-replica
    +    environment:
    +      TZ: 'Asia/Seoul'
    +      MYSQL_DATABASE: 'db'
    +      MYSQL_USER: 'user'
    +      MYSQL_PASSWORD: 'password'
    +      MYSQL_ROOT_PASSWORD: 'password'
    +    ports:
    +      - "13307:3306"
    +    volumes:
    +      - db-replica:/var/lib/mysql
    +      - db-replica:/var/lib/mysql-files
    +      - ./docker/replica.cnf:/etc/mysql/my.cnf
    +    networks:
    +      - mysql_network
     
    -    Items --> Item
    -    Players --> Player
    +volumes:
    +  db-source:
    +  db-replica:
     
    -    LadderGameController --> InputView
    -    LadderGameController --> OutputView
    -">
    -
    public LadderGameResult play() {
    -    final Map<Player, Item> result = new LinkedHashMap<>();
    -    // 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
    -    for (Position position : Position.range(players.count())) {
    -        final Position resultPosition = ladder.play(position);
    -        result.put(players.get(position), items.get(resultPosition));
    +networks:
    +  mysql_network:
    +    driver: bridge
    +
    +

    또한 source, replica 각각 다음과 같이 db 설정을 했다.

    +
    설정설명
    server_id각각의 mysql 마다 고유한 값을 가져야 한다.
    log_bin바이너리 로그 파일 경로 설정으로 절대경로를 사용하지 않는다면 /var/lib/mysql 아래 해당 log_bin에 설정된 값으로 로그가 생성된다.
    sync_binlogN개의 트랜잭션 당 바이너리 로그를 디스크와 동기화 작업을 하도록 한다. 1은 기본값으로 안정적이지만, 가장 느리다.
    relay_log릴레이 로그 파일 경로 설정
    relay_log_purge필요 없는 릴레이 로그 파일을 자동으로 삭제하는 옵션
    read_only읽기 전용 설정
    log_replica_updatesReplication SQL Thread로 인해 실행되는 정보를 바이너리 로그에 기록 추후에 소스 서버로 승격되는 경우를 고려하면 설정하는 것이 좋다.
    + + +
    [mysqld]
    +server_id=1
    +log_bin=mysql-bin
    +sync_binlog=1
    +
    +

    도커 실행

    +

    docker-compose up 명령어로 docker-compose 설정으로 docker를 띄운다.
    +-d 옵션을 붙이면 백그라운드 모드로 실행된다.

    +
    docker-compose up -d
    +
    +

    replication slave 권한 설정

    +

    REPLICATION SLAVE 권한이 설정되어 있어야 replica 서버에서 source 서버에 접근하여 로그를 읽어올 수 있다.
    +source 서버에 접근하여 user 계정에 해당 권한을 설정해준다.

    +

    SOURCE 접속

    +
    docker exec -it mysql-source mysql -u root -p
    +
    +

    user 계정에 REPLICATION SLAVE 권한 추가

    +
    GRANT REPLICATION SLAVE ON *.* TO 'user'@'%';
    +FLUSH PRIVILEGES;
    +
    +

    SOURCE DB 정보 확인

    +

    replica 설정에 필요한 source db의 바이너리 로그 파일명과 Position을 확인한다.
    +Position 값은 실제 파일의 바이트 수를 의미한다.
    +확인한 File(SOURCE_LOG_FILE)과 Position(SOURCE_LOG_POS) 값은 replica 설정에서 사용한다.

    +
    SHOW MASTER STATUS;
    +
    ++------------------+----------+--------------+------------------+-------------------+
    +| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    ++------------------+----------+--------------+------------------+-------------------+
    +| mysql-bin.000003 |     1082 |              |                  |                   |
    ++------------------+----------+--------------+------------------+-------------------+
    +
    +

    SOURCE ip 주소 확인

    +

    docker inspect -f 옵션을 사용하면 해당 컨테이너의 세부 정보를 확인할 수 있다.
    +다음 명령어를 이용해 docker-compose 파일에 설정해둔 mysql_network에서 사용되는 사설 아이피 주소를 확인한다.

    +
    docker inspect -f "{{with index .NetworkSettings.Networks \"db-replication_mysql_network\"}}{{.IPAddress}}{{end}}" mysql-source
    +
    +

    ip 주소가 나오지 않는 경우 docker inspect mysql-source로 확인한다.
    +확인한 IP주소(SOURCE_HOST) 값은 replica 설정에서 사용한다.

    +

    replica mysql 접속

    +

    source db에 접속했던 방법과 동일하게 replica db에 접속한다.

    +
    docker exec -it mysql-replica mysql -u root -p
    +
    +

    replica 설정

    +

    이전에 source db에서 얻었던 정보들을 사용하여 replica 설정을 진행한다.
    +실제 DB 서버에서 복제하는 경우 추가적으로 source DB의 파일을 복제해야하지만 현재 복제할 데이터가 없기 때문에 해당 부분은 생략했다.
    +SOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS 를 적절히 변경한다.

    +
    STOP REPLICA;
    +
    +CHANGE REPLICATION SOURCE TO 
    +SOURCE_HOST='172.29.0.2', 
    +SOURCE_USER='user', 
    +SOURCE_PASSWORD='password', 
    +SOURCE_LOG_FILE='mysql-bin.000001', 
    +SOURCE_LOG_POS=0, 
    +GET_SOURCE_PUBLIC_KEY=1;
    +
    +START REPLICA;
    +
    +

    설정 확인

    +
    SHOW REPLICA STATUS;
    +
    ++----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
    +| Replica_IO_State                 | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File  | Read_Source_Log_Pos | Relay_Log_File         | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID                          | Source_Info_File        | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State                                | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |
    ++----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
    +| Waiting for source to send event | 172.25.0.3  | user        |        3306 |            60 | mysql-bin.000003 |                1082 | mysql-relay-bin.000002 |           868 | mysql-bin.000003      | Yes                | Yes                 |                 |                     |                    |                        |                         |                             |          0 |            |            0 |                1082 |            1078 | None            |                |             0 | No                 |                    |                    |                 |                   |                |                     0 | No                            |             0 |               |              0 |                |                             |                1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info |         0 |                NULL | Replica has read all relay log; waiting for more updates |              86400 |             |                         |                          |                |                    |                    |                   |             0 |                      |              |                    |                        |                     1 |                   |
    ++----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
    +
    +

    Replica_IO_Running, Replica_SQL_Running 값이 YES라면 정상적으로 replication 구성이 완료된 것이다.

    +

    설정을 마친 후 source db에 다음과 같이 create table 명령어를 입력한다.
    +replica db에 동일한 member table이 생성된 것을 확인할 수 있다.

    +
    CREATE TABLE member
    +(
    +    id   BIGINT PRIMARY KEY AUTO_INCREMENT,
    +    name VARCHAR(255)
    +);
    +
    +

    스프링 부트로 DB 접근하기

    +

    일반적인 트랜잭션의 경우 source, 읽기 전용 트랜잭션인 경우 replica로 요청이 가도록 구성해보자.

    +

    Environment 설정

    +

    다음과 같이 source, replica로 구분하여 설정한다.

    +
    spring:
    +  datasource:
    +    source:
    +      username: user
    +      password: password
    +      driver-class-name: com.mysql.cj.jdbc.Driver
    +      jdbc-url: jdbc:mysql://localhost:13306/db
    +    replica:
    +      username: user
    +      password: password
    +      driver-class-name: com.mysql.cj.jdbc.Driver
    +      jdbc-url: jdbc:mysql://localhost:13307/db
    +
    +

    DataSourceType 설정

    +

    단순 문자열로도 구분할 수 있지만, enum을 이용해서 트랜잭션을 구분하도록 생성한다.
    +Key는 추후에 빈 설정에 사용한다.

    +
    public enum DataSourceType {
    +    SOURCE(SOURCE_NAME),
    +    REPLICA(REPLICA_NAME),
    +    ;
    +
    +    private final String key;
    +
    +    DataSourceType(String key) {
    +        this.key = key;
    +    }
    +
    +    public static class Key {
    +        public static final String ROUTING_NAME = "ROUTING";
    +        public static final String SOURCE_NAME = "SOURCE";
    +        public static final String REPLICA_NAME = "REPLICA";
         }
    -    return new LadderGameResult(result);
     }
     
    -

    Player에게 Ladder를 전달하여 게임을 진행하는 방법

    -

    Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
    -이 방법이 사다리 게임을 위해서 객체들이 긴밀하게 협력하고, 조금 더 책임의 분배가 잘 되어있다고 생각이 되었다.

    -AbstractRoutingDataSource 설정

    +

    스프링이 지원해주는 AbstractRoutingDataSource를 상속받아 트랜잭션의 읽기 여부에 따라 다른 DataSource를 향하도록 설정한다.

    +

    정적 팩터리 메서드는 Map<DataSourceKey, DataSource>에 해당하는 값을 받아 데이터 소스를 설정한다.

    +
      +
    • setDefaultTargetDataSource: 기본 데이터 소스를 설정한다.
    • +
    • setTargetDataSources: 맵 형태로 받은 데이터 소스 값들을 설정한다.
    • +
    +

    determineCurrentLookupKey를 오버라이딩하여 트랜잭션의 읽기 여부에 따라 다른 DataSourceType을 반환하도록 설정한다.

    +
      +
    • isCurrentTransactionReadOnly() 메서드를 통해 트랜잭션이 읽기 전용인지 확인할 수 있다.
    • +
    • DataSourceType을 반환하도록 설정하고, 반환한 값에 해당하는 데이터 소스가 사용된다.
    • +
    +
    public class RoutingDataSource extends AbstractRoutingDataSource {
     
    -    LadderGameController --> LadderGame
    -    LadderGame --> Ladder
    -    LadderGame --> Players
    -    LadderGame --> Items
    +    private final Logger log = LoggerFactory.getLogger(getClass());
     
    -    Ladder --> Line
    -    Line --> LineStatus
    -    Line --> Position
    +    public static RoutingDataSource from(Map<Object, Object> dataSources) {
    +        RoutingDataSource routingDataSource = new RoutingDataSource();
    +        routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));
    +        routingDataSource.setTargetDataSources(dataSources);
    +        return routingDataSource;
    +    }
     
    -    Players --> Ladder
    -    Player --> Ladder
    +    @Override
    +    protected Object determineCurrentLookupKey() {
    +        boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
     
    -    Item --> Position
    -    Player --> Position
    +        if (readOnly) {
    +            log.info("readOnly = true, request to replica");
    +            return DataSourceType.REPLICA;
    +        }
    +        log.info("readOnly = false, request to source");
    +        return DataSourceType.SOURCE;
    +    }
    +}
    +
    +

    DataSource 설정

    +

    위에서부터 순서대로 Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy 설정이다.
    +스프링은 트랜잭션 시작시에 커넥션의 사용여부와 상관없이 커넥션을 확보한다.
    +따라서 readOnly 트랜잭션이 설정된 메서드를 사용하더라도 미리 확보된 커넥션을 사용하기 때문에 replica db로 요청을 하지 않고 source db로 요청을 한다.

    +

    TransactionSynchronizationManager.isCurrentTransactionReadOnly() 메서드 호출 시 currentTransactionReadOnly라는 ThreadLocal<Boolean>에 설정된 값을 반환하는데 readOnly 설정이 되면 이 값을 true로 설정한다. 하지만 determineCurrentLookupKey를 호출하여 key 값을 가져오는 부분보다 이후에 설정되기 때문에 determineCurrentLookupKey 메서드에서 항상 DataSourceType.SOURCE가 반환되어 source db로 요청을 한다.

    +

    LazyConnectionDataSourceProxy를 설정하는 경우 실제 DataSource를 사용하는 시점에 커넥션을 획득해서 사용하기 때문에 설정한대로 replica db로 조회 요청을 한다.

    +
    @Configuration
    +public class DataSourceConfiguration {
     
    +    @Bean
    +    @Qualifier(SOURCE_NAME)
    +    @ConfigurationProperties(prefix = "spring.datasource.source")
    +    public DataSource sourceDataSource() {
    +        return DataSourceBuilder.create().build();
    +    }
     
    -    LadderGame --> LadderGameResult
    +    @Bean
    +    @Qualifier(REPLICA_NAME)
    +    @ConfigurationProperties(prefix = "spring.datasource.replica")
    +    public DataSource replicaDataSource() {
    +        return DataSourceBuilder.create().build();
    +    }
     
    -    Items --> Item --> ItemName
    -    Players --> Player --> PlayerName
    +    @Bean
    +    @Qualifier(ROUTING_NAME)
    +    public DataSource routingDataSource(
    +            @Qualifier(SOURCE_NAME) DataSource sourceDataSource,
    +            @Qualifier(REPLICA_NAME) DataSource replicaDataSource
    +    ) {
    +        return RoutingDataSource.from(Map.of(
    +                DataSourceType.SOURCE, sourceDataSource,
    +                DataSourceType.REPLICA, replicaDataSource
    +        ));
    +    }
     
    -    LadderGameController --> InputView
    -    LadderGameController --> OutputView
    +    @Bean
    +    @Primary
    +    public DataSource dataSource(
    +            @Qualifier(ROUTING_NAME) DataSource routingDataSource
    +    ) {
    +        return new LazyConnectionDataSourceProxy(routingDataSource);
    +    }
    +}
    +
    +

    최종적으로 DataSource 빈은 다음과 같은 형태가 된다.

    + +

    동작 확인

    +

    간단하게 테스트를 작성해서 설정한대로 동작이 되는지 확인해보았다.
    +save 메서드의 경우 @Transactional, findById 메서드의 경우 @Transactional(readOnly = true)가 설정되어있다.
    +로그를 통해 save의 경우 source db로 findById의 경우 replica db로 요청을 하는 것을 알 수 있다.

    +
    @SpringBootTest
    +class MemberServiceTest {
    +
    +    @Autowired
    +    private MemberService memberService;
     
    -    OutputView --> LadderMessageGenerator">
    -
    public LadderGameResult play() {
    -    // 참가자들에게 사다리를 전달해서 사다리에게 메시지를 보내도록 한다.
    -    final Map<Player, Position> playResult = players.play(ladder);
    +    @Test
    +    void 사용자를_저장한다() {
    +        // RoutingDataSource log: readOnly = false
    +        memberService.save("bbiac");
    +    }
     
    -    final Map<Player, Item> result = new LinkedHashMap<>();
    -    for (Player player : playResult.keySet()) {
    -        result.put(player, toItem(playResult.get(player)));
    +    @Test
    +    void 사용자를_조회한다() {
    +        // RoutingDataSource log: readOnly = true
    +        assertThatThrownBy(() -> memberService.findById(MAX_VALUE))
    +                .isInstanceOf(NoSuchElementException.class);
         }
    -    return new LadderGameResult(result);
     }
     
    -

    부족했던 부분

    -

    유비쿼터스 언어에 시간을 들이기
    -유비쿼터스 언어를 정하는데 시간을 조금 더 들여야겠다고 생각했다.
    -사다리 타기의 실행 결과를 Item으로 짓다니.. 뭔가 만족스럽지 않다.
    -이전 미션과 마찬가지로, 명명하는 부분에서 부족함을 많이 느꼈다.

    -

    페어와 조금 더 친해지기
    -첫날은 페어와 친해지는 시간을 조금 더 가져야겠다고 생각했다.
    -우가랑 회고할 때 내가 시작하자마자 컨벤션 정하자고 해서 많이 당황스러웠다고 한다. 우가 미안.. 🥲

    -

    README를 조금 더 꼼꼼하게
    -이상하게 코딩에 집중하면 README를 업데이트하면서 같이 커밋 하는 걸 항상 까먹는다.
    -다음 미션에는 조금 더 신경 써야겠다.

    -

    좋은 질문을 생각하기
    -첫 PR때 리뷰어에게 질문을 남기지 못했다.
    -리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

    -

    PR 후에도 꼼꼼하게 확인하기
    -분명 알고 있는 부분이지만, 놓친 부분이 많은 것 같았다.
    -PR 하기 전에도 계속 확인을 했지만, 아무래도 IntelliJ에서 보니 코드에 익숙해져서 그런지 변경해야 할 부분이 잘 안보였다.
    -github pr에서는 전체 변경사항을 확인할 수 있으니 PR 후에도 꼭 확인해야겠다.

    -

    적극적으로 나의 의견을 말하기
    -의견을 적극적으로 내는 부분에 대해서 페어의 의견이 괜찮다고 생각하면 수용 후 개선을 하는 방향으로 진행을 했었는데, 조금 더 개선할 수 있는 방향이 있다면 나도 적극적으로 의견을 말해야겠다고 생각이 든다.
    -나도 설득하는 힘을 기르고, 페어도 좋은 방향을 알 수 있고, 결과물도 좋은 방향으로 나오지 않을까? (고민 들어주신 리뷰어 터틀🐢 감사합니다.)

    -

    새로 학습한 부분

    -

    객체의 생성 책임
    -Players가 Position을 생성하고 Player의 생성자에 넣어주었다. 하지만 이 부분에 대해서 생성 책임에 관련된 코멘트가 달렸다. -시간을 가지고 생각해 보니 Position을 가지고 있는 건 Player기 때문에 생성 책임을 Player가 담당하는 것이 좋다고 생각되었다.

    -

    생성 책임에 관한 패턴으로 GRASP의 Creator 패턴이 있는데 다음의 요소를 최대한 만족하는 클래스에 생성 책임을 할당하는 것이 좋다.

    -
      -
    • B가 A 객체를 포함 또는 참조한다.
    • -
    • B가 A 객체를 기록한다.
    • -
    • B가 A를 긴밀하게 사용한다.
    • -
    • B가 A의 초깃값을 가지고 있다.
    • -
    -

    실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

    -

    패키지 분리 기준
    -패키지 분리에 대한 나만의 기준이 아직 명확하지 않아 질문이 들어와도 명확하게 답변을 하지 못했다.
    -마지막 제출 전에 도메인 패키지 내부를 분리해 봤는데, 기준이 명확하지 않았기 때문에 좋지 않은 선택이었던 것 같다. -현재 진행하는 미션의 애플리케이션 크기가 그렇게 크지 않으니, domain 패키지에서 세부 패키지로 분리하지 않아도 될 것 같다.

    -

    사용하는 쪽에서 생각하기 & 예측가능한 코드 작성하기
    -Position에서 다음 위치나 이전 위치를 반환하는 메서드를 허용 범위(019)가 벗어난다면, 의미 없는 값이 들어간 Position을 반환하도록 했다.
    -이건 Position을 사용하는 입장을 고려하지 못한 코딩이었는데, 사용하는 입장에서는 0
    19의 값이 보장되어 있다고 생각할 것이기 때문이다.
    -따라서 hasNext, hasPrevious라는 이전 값, 이후 값이 범위 내에 있는지 확인하는 메서드를 추가하고, 기존의 값을 가져오는 메서드는 범위가 벗어나면 예외를 던지는 방향으로 해결하였다.

    -

    페어에게 배울 부분

    -

    밝은 기운을 가지고 있고 다른 사람들과 친화력이 좋은 것 같았다.
    -이번에 페어 할 때 컨디션 관리를 제대로 못해서 많이 미안했다. 다음에는 최상의 컨디션으로 페어를 준비해 봐야겠다.
    -그리고 우가랑 페어를 하고 나서, 나도 다른 사람들과 더 잘 지내봐야겠다는 생각이 들어 조금 더 용기를 내 잡담 중이다!

    -

    의견을 적극적으로 내줘서 페어프로그래밍 진행이 잘 되었다.
    -또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
    -페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

    -

    항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
    -웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

    +

    DB에서는 확인하려면 root 계정으로 접속한 후 general log를 활성화 시킨다.

    +
    SET GLOBAL log_output = 'table';
    +SET GLOBAL general_log = 1;
    +
    +

    general log를 활성화 한 후 읽기 전용 메서드를 실행한다.
    +server_id, 실행한 쿼리문을 확인할 수 있다.

    +
    SELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like '%select%';
    +
    ++----------------------------+-----------+-----------+-----------------------------------------------------------------------------+
    +| user_host                  | thread_id | server_id | convert(argument using utf8)                                                |
    ++----------------------------+-----------+-----------+-----------------------------------------------------------------------------+
    +| user[user] @  [172.25.0.1] |       277 |         2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |
    ++----------------------------+-----------+-----------+-----------------------------------------------------------------------------+
    +
    +

    확인 후 general log를 비활성화 한 후 비활성화 되었는지 확인한다.

    +
    SET GLOBAL general_log = 0;
    +SHOW VARIABLES LIKE '%general%';
    +
    ++------------------+---------------------------------+
    +| Variable_name    | Value                           |
    ++------------------+---------------------------------+
    +| general_log      | OFF                             |
    +| general_log_file | /var/lib/mysql/4b6b9db98290.log |
    ++------------------+---------------------------------+
    +
    +

    참고 자료

    +

    16장 복제, Real MySQL 8.0 - 백은빈, 이성욱
    +Replication, MySQL Docs
    +MySql - Master Slave Replication 구조 만들어보기
    +Spring 레플리케이션 트랜잭션 처리 방식
    +replication-datasource
    +Simplified Guide to MySQL Replication with Docker Compose
    +Dockerfile에서 자주 쓰이는 명령어
    +CHANGE REPLICATION SOURCE TO Statement
    +LazyConnectionDataSourceProxy
    +데이터베이스 레플리케이션을 통한 쿼리 성능 개선 (feat. Mysql, SpringBoot)
    +부하 분산을 위한 MySQL Replication 구성 및 쿼리 요청 분기
    +Use Docker Compose, Docker

    \ No newline at end of file diff --git a/page/44.html b/page/44.html index eb30d7111..3ce9a1b52 100644 --- a/page/44.html +++ b/page/44.html @@ -13,89 +13,49 @@ - - + + -

    · 약 8분

    1단계: https://github.com/woowacourse/java-racingcar/pull/510
    -2단계: https://github.com/woowacourse/java-racingcar/pull/538

    -

    자동차 경주

    -

    자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
    -우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

    -

    첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
    -시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

    -

    시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
    -mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

    -
      -
    • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
    • -
    • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.
    • -
    - -

    미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

    -

    페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
    -리팩터링을 어떻게 했는지? 이런 리뷰에 대해 어떻게 생각하는지 깊게 고민하는 시간을 가질 수 있었다.

    -

    부족했던 부분

    -

    리팩터링이 끝난 후 메서드명, 테스트시 출력하는 메시지에 대한 코멘트가 많이 달렸다.
    -객체가 어떤 책임과 역할을 가지는지 생각하는 시간을 가지고 명확한 메서드명을 작성해야겠다고 생각했다.

    -

    평소에 프로그래밍 이야기가 아닌 다른 주제로 이야기하면 잘 들으려고 하는 편이지만
    -내가 좋아하는 주제, 관심가는 주제인 프로그래밍에 대한 이야기를 할 땐 말이 많아진다.
    -다음 미션부터는 더 많은 시간을 페어의 의견과 이야기를 듣는 곳에 사용해야겠다.

    -

    새로 학습한 부분

    -

    Assertions extracting

    -

    결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
    -이전에는 필요에 따라 stream을 이용하여 검증할 값을 생성했지만, 해당 방법을 이용해서 절차를 줄일 수 있었다.

    -
    @Test
    -void extracting() {
    -    final Cars cars = new Cars(List.of("car1", "car2"));
    -
    -    assertThat(cars.getCars())
    -            .extracting(Car::getName)
    -            .containsExactly("car1", "car2");
    -}
    -
    -
    -

    아래는 리뷰어님과 대화를 나누면서 얻은 답변 + 나의 의견이다.

    -

    제어할 수 없는 부분에 대한 테스트

    -

    테스트 대상이 검증된 것이라면 작성하지 않거나, 제어할 수 있는 부분에 대한 테스트를 더욱 꼼꼼하게 작성한다.
    -이건 개인적인 생각이지만 내가 안정감이 들 수 있을 정도로 출력 범위 내의 결과를 반환하는지 정도 테스트할 수 있지 않을까?

    -

    단순 위임을 하는 메서드에 대한 테스트

    -

    위임이라는 것은 역할과 책임을 넘겨준다는 것이다.
    -호출 횟수를 검증하는 것보다 결과에 대한 테스트하는 것이 좋다.
    -단순히 위임만 하는 테스트의 경우 결과를 검증한다면 테스트가 중복되지 않을까 생각했었다.
    -따라서 중복된 테스트를 줄이기 위해 내부의 메서드를 호출하는지 검증하는 방법도 있다는 것을 알게 되었지만
    -안정적으로 결과를 테스트 하는 것이 더 좋은 방법인 것 같다.

    -

    테스트를 위한 getter 사용

    -

    테스트 용도로 도메인에 새로운 메서드가 생성되는 것은 좋지 못하다.
    -필요의 경우 생성해서 사용할 수 있지만, 기존에 있는 메서드들을 활용해보는 것이 더 좋은 방법이다.
    -이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

    -

    페어에게 배울 부분

    -

    질문이나 생각할 점이 있을 때 매우 깊게 고민하는 것 같았다.
    -생각을 정리한 후 자신의 의견을 명료하게 전달해주었다.
    -그렇기 때문에 지식을 효율적으로 습득한다.
    -난 생각을 잘 정리하지 않은 채로 내버려 둔 얕은 지식이 많은 것 같다. (이런 것도 아는 것이라고 할 수 있을까?)
    -앞으로 조금 더 머릿속에서 정리하고, 문제에 대해 깊게 고민하는 시간을 늘려야겠다.

    -

    개발에 열정을 가진 게 느껴진다.
    -나도 개발을 좋아하지만, 최근에는 의지가 약해졌었다.
    -열정이 가득한 사람을 만나니 나도 열정적인 사람이 되는 것 같다.

    -

    칭찬을 많이 해준다. 단순히 많이 해주는 것이 아니라, 진심을 담긴 칭찬을 해줬다.
    -칭찬은 고래도 춤추게 하던가?
    -그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

    -

    어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
    -이건 바로 배울 수 없지만.
    -나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

    +

    · 약 6분

    성능 테스트

    +

    API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

    +

    시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
    +다양한 상황에 대비해서 성능 테스트를 해야한다.

    +

    ./test.png

    +

    스모크 테스트(Smoke Test)

    +

    최소한의 부하를 주어 시스템이 정상적으로 동작하는지 확인하는 테스트

    +

    VU를 최소한으로 두고, 짧은 시간을 가지고 테스트한다.
    +다른 테스트를 시작하기 전에 스모크 테스트를 함으로써 테스트 스크립트에 오류가 없는지 확인할 수 있고, 성능 지표가 정상적으로 수집, 모니터링 되고 있는지 확인할 수 있다.

    +

    가상 사용자는 서버 애플리케이션에 대해 특정 테스트를 실행한다.
    +이는 다른 가상 사용자와 독립적으로 실행되며, 여러 가상 사용자를 사용하여 동시 연결을 할 수 있다.
    +스레드라고 생각하면 된다.

    +

    스파이크 테스트(Spike Test)

    +

    사용량이 급증하는 상황에서 시스템이 견디고 성능에 문제가 없는지 확인하는 테스트

    +

    티켓 발급, 할인 쿠폰 발급과 같은 이벤트를 하는 경우 대규모 트래픽이 들어온다.
    +스파이크 테스트를 통해 급증하는 부하 상황에서 시스템이 어떻게 동작하고, 부하를 잘 버티는지 확인할 수 있다.

    +

    부하 테스트(Load Test)

    +

    목푯값에 해당되는 부하를 견딜 수 있을지 확인하는 테스트

    +

    일반적인 부하 상황에서 시스템이 어떻게 동작하는지 확인하는 테스트다.
    +램프업 또는 묙푯값에 해당하는 부하 기간동안 성능이 문제가 있는지 확인하고, 시스템 변경 후에도 부하 테스트를 돌려 동일하게 목푯값을 처리하는지 확인할 수 있다.

    +

    부하 테스트를 위해 설정한 가상 사용자 수에 도달하는 데 걸리는 시간

    +

    스트레스 테스트(Stress Test)

    +

    시스템의 최대치에 해당되는 부하를 받았을 때 시스템이 어떻게 동작하는지 확인하는 테스트

    +

    그래프를 봤을 때 부하 테스트와 유사한 형태로 보이지만, 부하량이 다르다.
    +일반적으로 평균적인 목푯값 대비 작게는 50% 이상, 필요의 경우 그 이상으로 부하를 준다.
    +스트레스 테스트는 부하 테스트를 실행한 후에만 실행해야 한다. 부하 테스트가 이루어지지 않은 상황에서 스트레스 테스트를 실행하는 경우에는 병목 지점이나 문제 상황을 찾기 어려워진다.
    +또한 부하 테스트에서 사용한 스크립트를 VU값(스레드 수)만 수정하여 재사용하는 것이 좋다.

    +

    내구 테스트(Endurance Test)

    +

    평균 사용률로 일정 부하를 지속적으로 주며 시스템이 문제되는 지점을 확인하는 테스트

    +

    흡수 테스트(Soak Test)라고도 하며, 기본적인 부하 테스트의 변형이라고 볼 수 있다.
    +다른 테스트와 달리 긴 시간동안 테스트를 하는 것이 특징이며, 메모리 누수 문제와 같이 장시간 애플리케이션을 실행할 때 시스템의 문제가 발생하는 부분을 확인하는 것이 목적이다.

    +

    중단점 테스트(Breakpoint Test)

    +

    임계 지점을 찾기 위해 부하를 점진적으로 증가시키며 진행하는 테스트

    +

    문제되는 부분을 더 빨리 찾기 위해 다른 테스트를 통과한 다음에 중단점 테스트를 진행하고, 이 때 점진적으로 부하를 늘려나가는 것이 좋다.
    +스트레스 테스트를 성능 튜닝과 반복해서 진행한다면, 시스템을 더욱 발전시킬 수 있다.
    +다만 Auto Scaling이 적용된 클라우드 환경에서는 진행하지 않아야 한다.

    +

    참고 자료

    +

    Load test types, k6
    +자바 최적화 - 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드
    +아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

    \ No newline at end of file diff --git a/page/45.html b/page/45.html index 4e6c9e4b8..34e01b386 100644 --- a/page/45.html +++ b/page/45.html @@ -13,99 +13,209 @@ - - + + -

    · 약 4분

    테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
    -이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

    -

    Argument Sources

    -

    @ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
    -JUnit이 제공하는 다양한 Source가 있기 때문에, 테스트에 맞춰 다양하게 사용할 수 있다.

    -

    Value Source

    -

    값을 이용하여 제공하는 형태로, 다음과 같은 타입의 값을 매개변수로 제공할 수 있다.

    -
      -
    • short, int, long, float, double
    • -
    • byte, char, boolean, String, Class
    • -
    -
    @ParameterizedTest
    -@ValueSource(ints = {1, 100, Integer.MAX_VALUE})
    -void valueTest(final int value) {
    -    Assertions.assertThat(value).isPositive();
    +

    · 약 13분

    1, 2단계: https://github.com/woowacourse/jwp-dashboard-http/pull/302
    +3, 4단계: https://github.com/woowacourse/jwp-dashboard-http/pull/431

    +

    톰캣 구현

    +

    우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
    +그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

    +

    이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
    +톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

    +

    다이어그램

    +

    Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
    +사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
    +또한 적절하게 인터페이스를 사용하여 의존성 방향을 단방향으로 하려고 노력했다.

    + +

    코드 리뷰

    +

    크루 중 한 명이 나의 리뷰어가 되고, 내가 다른 크루의 리뷰어가 되는 형태로 진행이 되었다.
    +나의 리뷰어는 디노, 리뷰이는 필립이었다.

    +

    디노(매의 눈이 아닌 공룡의 눈?)가 매우 꼼꼼하게 코드 리뷰를 해주어서 조금 더 나은 코드를 작성할 수 있었고, 필립의 코드에서는 꼼꼼하게 예외처리 하는 부분을 배울 수 있었다.
    +한 가지 아쉬운 점은 필립에게 작성한 나의 코멘트들이 미션을 진행하면서 경험 기반으로 작성한 내용이 많아 근거가 조금 부족했고, 정리되지 않은 부분이 많았던 것 같다.
    +다음 미션부터 리뷰할 때 조금 더 시간을 투자해서 더 좋은 내용을 크루들과 공유할 수 있도록 노력해야겠다.

    +

    SessionConfig

    +

    미션을 진행 중 catalina 패키지의 Session 관련 부분을 보면서 중복 로직을 개선해 볼 수 있을 것 같아 컨트리뷰트를 시도했다.
    +세션 쿠키의 이름을 가져오는 Util 클래스의 코드를 수정했는데 기본 값은 JSESSIONID 지만 설정에 따라서 세션 쿠키명을 다르게 사용할 수 있기 때문에 해당 로직이 있는 것으로 생각했다.
    +기존의 코드는 명시된 주석의 내용과 코드의 흐름이 일치하지 않아서 약간 이해하기 어려웠다.

    +

    초기에 요청했던 PR은 기존의 코드보다 전체적으로 비교 연산을 한 번 줄일 수 있었고, context가 null인 경우 바로 기본 값을 반환함으로써 성능 개선의 효과가 있을 거라고 생각했다.
    +메인테이너인 Mark Thomas 형이 해당 로직의 경우 컴파일러가 해당 부분을 최적화 할 수 있을 거라고 기대한다고 했고, 가독성을 개선시켜보라고 조언해주셨다.
    +컴파일러 최적화는 고려해보지 못한 부분인데, 앞으로 학습해야 할 부분이 산더미라고 생각했다.

    +

    남겨준 코멘트에 따라 최종적으로는 중복된 코드를 줄이는 방향으로 코드를 수정했다.
    +결과적으로 기존 로직 대비 비교 연산을 한 번 줄일 수 있었고, 명시된 주석의 내용과 유사한 흐름의 코드를 작성하여 좋은 방향으로 리팩터링을 했다고 생각한다.

    + + +
    public static String getSessionCookieName(Context context) {
    +
    +    String result = getConfiguredSessionCookieName(context);
    +
    +    if (result == null) {
    +        result = DEFAULT_SESSION_COOKIE_NAME;
    +    }
    +
    +    return result;
     }
    -
    -

    Null & Empty Source

    -

    null 값, 빈 값을 제공한다.
    -Empty Source의 경우 다음과 같은 타입에 한해 매개변수로 제공할 수 있다.

    -
      -
    • String
    • -
    • java.util.List, java.util.Set, java.util.Map
    • -
    • primitive arrays — ex) int[]
    • -
    • object arrays — ex) String[]
    • -
    -
    @ParameterizedTest
    -@NullAndEmptySource
    -void nullAndEmptyTest(final String value) {
    -    Assertions.assertThat(value).isNullOrEmpty();
    +
    +public static String getSessionUriParamName(Context context) {
    +
    +    String result = getConfiguredSessionCookieName(context);
    +
    +    if (result == null) {
    +        result = DEFAULT_SESSION_PARAMETER_NAME;
    +    }
    +
    +    return result;
     }
    -
    -

    Enum Source

    -

    EnumSource를 이용하여 Enum 또한 매개변수로 제공할 수 있다.

    -
    enum Day {
    -    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
    +
    +private static String getConfiguredSessionCookieName(Context context) {
    +
    +    // Priority is:
    +    // 1. Cookie name defined in context
    +    // 2. Cookie name configured for app
    +    // 3. Default defined by spec
    +    if (context != null) {
    +        String cookieName = context.getSessionCookieName();
    +        if (cookieName != null && cookieName.length() > 0) {
    +            return cookieName;
    +        }
    +
    +        SessionCookieConfig scc =
    +            context.getServletContext().getSessionCookieConfig();
    +        cookieName = scc.getName();
    +        if (cookieName != null && cookieName.length() > 0) {
    +            return cookieName;
    +        }
    +    }
    +
    +    return null;
    +}
    +
    +

    HTTP 수업

    +

    미션 중간에 진행되었던 HTTP 수업에는 HTTP를 적절하게 활용하는 부분에 대해 학습했다.
    +항상 성능 개선을 위해 애플리케이션 단에서 최적화해보려고 노력을 했지만, 더 적은 시간을 투자해서 효율적으로 성능을 개선할 수 있는 방법에 대해 알 수 있었던 수업이었다.
    +HTTP 압축, HTTP 캐싱, 리소스 최적화 기법에 대해 학습했다.

    +

    스프링 부트에서는 다음 옵션을 설정하여 http의 송수신의 압축을 진행할 수 있다.

    +
    server:
    +  compression:
    +    enabled: true
     
    -

    ETC.

    -

    위에서 언급한 방법 이외에도 다양한 방법으로 매개변수를 제공할 수 있다.

    -
      -
    • CSV 파일을 이용한 CsvFileSource
    • -
    • ArgumentsProvider 구현한 클래스를 이용하는 ArgumentsSource
    • -
    -

    참고 자료

    -
    +

    수업 중 해당 압축 성능이 좋다면 왜 스프링 부트에서는 기본 값으로 설정을 하지 않았는지 궁금해졌다.
    +궁금증을 해소하지 못했는데 말랑이 잡담 채널에 다음과 같은 issue를 찾아주었다.
    +내용을 요약해 보자면 WAS 별로 압축을 하기 위해 설정해야 하는 것이 다르고, 무조건 압축을 하는 것이 최적의 경우가 아닐 수 있기 때문에 기본값으로 설정하지 않는 것 같다.

    +
    +

    If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.

    +
    +

    Phil Webb 형님의 말에 따르면 일반적인 애플리케이션을 개발하는 경우 gzip 압축을 사용하는 것이 좋지만, MSA 환경 + 데이터 센터에서 사용하는 경우 오직 다른 MSA 애플리케이션과 통신하고, 고성능 네트워크가 있기 때문에 CPU 부하를 줄이는 것이 우선시 될 수도 있다는 것이었다.

    +

    이외에도 의도하지 않은 캐싱을 막기 위해 휴리스틱 캐싱을 제거하거나, 개인 정보 유출을 막기 위해 응답 헤더에 private을 설정, ETag도 학습했다.

    +

    ETag HTTP 응답 헤더는 특정 버전의 리소스를 식별하는 식별자다.
    +웹 서버가 내용을 확인하고 변하지 않았으면, 웹 서버로 full 요청을 보내지 않기 때문에, 캐시가 더 효율적이게 된다.
    +MDN

    +

    Thread 수업

    +

    스레드에 대한 수업을 들었지만, 복잡한 내용도 워낙 많았기 때문에 설명하라고 하면 잘 못할 것 같은 느낌이 든다.
    +현재 프로젝트, 미션, 테코톡 준비를 병행해야 해서 세부적인 내용은 시간 날 때 복습하려고 한다.

    +

    스레드를 이해하고, WAS에 스레드 설정 관련한 실습이 있었는데 테오와 같이 1시간 정도 페어로 Thread 실습을 진행해 보았다.
    +학습한 내용은 다음과 같다.

    +

    threads.max: Tomcat의 최대 스레드 개수
    +max-connections: Tomcat이 유지할 수 있는 최대 커넥션 개수
    +accept-count: 최대 연결 수에 도달했을 때 연결 요청에 대해 운영 체제에서 제공하는 대기열의 최대 길이. 해당 Queue에 요청이 쌓이는 것은 Tomcat이 더 이상 요청을 받을 수 없다는 뜻이다. accpet-count queue에도 요청이 가득차면 그 이후에 오는 요청은 거부된다.

    + +

    마치며

    +

    시간은 너무 빠르게 가고 할 일은 많은 것 같다.
    +우선순위를 잘 정하고 학습을 진행해야겠다.
    +현재 데이터 다루는 부분(DB)에 대한 학습이 많이 부족한 것 같다. 해당 부분은 테코톡이 끝나는대로 채워야겠다.

    +

    참고 자료

    +

    RFC 2616
    +ETag, mdn
    +Apache Tomcat 8 Configuration Reference
    +Apache Tomcat Tuning, Terry Cho
    +maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

    \ No newline at end of file diff --git a/page/46.html b/page/46.html index 9476f4a0d..ded96d21d 100644 --- a/page/46.html +++ b/page/46.html @@ -13,21 +13,93 @@ - - + + -

    · 약 1분

    Import 자동 적용

    -

    Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

    -

    auto-import

    -

    저장시 동작

    -

    Prefrences > Tools > Actions on Save

    -

    actions-on-save

    -

    Reformat Code: Code Reformmating

    -

    Optimize imports: 사용하지 않는 Import 제거

    -

    Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

    -

    메소드 추출, 변수 추출시 final 적용

    -

    Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

    -

    final-modifier

    +

    · 약 4분

    문제 상황

    +

    현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
    +확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

    +

    비동기 예외 발생시 로깅 설정

    +

    스프링 4.1 부터 제공되는 AsyncUncaughtExceptionHandler의 경우 반환 타입이 void인 비동기 메서드를 예외 처리하기 쉽도록 도와준다.

    +

    따라서 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 핸들링하는 클래스를 생성했다.
    +기존의 동기 예외 처리의 경우 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다.
    +비동기 예외 처리도 마찬가지로 MDC의 정보를 가져와서 로그를 출력하도록 설정했다.

    +
    @Slf4j
    +public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    +
    +    private static final String LOG_FORMAT = "[%s] %s";
    +
    +    @Override
    +    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
    +        log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
    +    }
    +}
    +
    +

    AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
    +getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

    +
    @EnableAsync
    +@Configuration
    +public class AsyncConfig implements AsyncConfigurer {
    +
    +    @Override
    +    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    +        return new AsyncExceptionHandler();
    +    }
    +}
    +
    +

    이제 비동기 상황에서 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아 처리한다.

    +

    MDC 정보 연동 문제

    +

    비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없는 문제가 발생했다.

    +

    ./mdc-null.png

    +

    스프링 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

    +
    public class MdcTaskDecorator implements TaskDecorator {
    +
    +    @Override
    +    public Runnable decorate(final Runnable runnable) {
    +        Map<String, String> threadContext = MDC.getCopyOfContextMap();
    +        return () -> {
    +            MDC.setContextMap(threadContext);
    +            runnable.run();
    +        };
    +    }
    +}
    +
    +

    생성한 Decorator 클래스를 설정 파일에 등록해 준다.

    +
    @RequiredArgsConstructor
    +@EnableAsync
    +@Configuration
    +public class AsyncConfig implements AsyncConfigurer {
    +
    +    private final AsyncConfigurationProperties properties;
    +
    +    @Bean
    +    public ThreadPoolTaskExecutor taskExecutor() {
    +        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    +        executor.setCorePoolSize(properties.coreSize());
    +        executor.setMaxPoolSize(properties.maxSize());
    +        executor.setQueueCapacity(properties.queueCapacity());
    +        
    +        // highlight-next-line
    +        executor.setTaskDecorator(new MdcTaskDecorator());
    +        executor.setWaitForTasksToCompleteOnShutdown(true);
    +        executor.initialize();
    +        return executor;
    +    }
    +
    +    @Override
    +    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    +        return new AsyncExceptionHandler();
    +    }
    +}
    +
    +

    설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

    +

    ./mdc-not-null.png

    +

    참고 자료

    +

    spring async, baeldung
    +@Async will not call by @ControllerAdvice for global exception
    +Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
    +TaskDecorator, Spring docs
    +AsyncUncaughtExceptionHandler

    \ No newline at end of file diff --git a/page/47.html b/page/47.html index 56065aa4c..652abdb89 100644 --- a/page/47.html +++ b/page/47.html @@ -13,75 +13,69 @@ - - + + -

    · 약 5분

    nullable 타입

    -

    코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
    -이는 실행 시점이 아닌 컴파일 시 미리 오류가 발생할 가능성이 있는 부분을 미리 감지하여 NPE 발생의 가능성을 줄여준다.

    -

    코틀린의 경우 nullable 타입을 다음과 같이 표현한다.

    -
    val number: Int?
    -
    -

    타입 뒤에 ?를 붙여 해당 값이 null이 될 수 있다는 것을 의미한다.
    -만약 ?를 붙이지 않을 때 null을 받는 경우 컴파일 시 오류가 발생한다.

    -

    ?. Safe Calls 연산자

    -

    자바에서 NPE를 발생시키지 않기 위해 null을 처리하는 가장 간단한 방법으로는 분기를 사용하는 방법이 있다.

    -

    코틀린은 안전한 호출 연산자인 ?. 연산자를 지원한다.
    -따라서 참조 값이 null이 아닐 경우에만 메서드 호출을 할 수 있다.
    -참조 값이 null인 경우 메서드 호출이 무시되고, null을 반환한다.

    -
    public String repeat(String word) {
    -    if (word == null) {
    -        return null;
    -    }
    -    return word.repeat(2);
    -}
    -
    -

    ?: 엘비스 연산자

    -

    참조하려는 값이 null일 경우 기본 값을 반환하고 싶을 때는 어떻게 해야 할까?
    -코틀린은 null이 아닌 경우 기본 값을 지정할 때 사용할 수 있는 엘비스 연산자를 지원한다.

    -
    public String stringSafe(String word) {
    -    if (word == null) {
    -        return "";
    -    }
    -    return word;
    -}
    -
    -

    코틀린에서는 throw도 식이기 때문에 엘비스 연산자를 이용하여 예외를 던질 수 있다.
    -예를 들어 사용자 정보가 있는 저장소에 찾는 사용자가 없는 경우 아래와 같이 사용할 수 있다.

    -
    userRepository.findByName(name) ?: throw IllegalArgumentException()
    -
    -

    !! 널 아님 단언 연산자

    -

    !! 연산자를 이용한다면 강제로 어떤 값이든 non-nullable 타입으로 변경할 수 있다.
    -하지만 null인 값에 사용한다면 NPE가 발생하게 된다.
    -일반적인 경우에는 !! 연산자를 사용하는 것은 위험하다.
    -사용하기 쉽지만, 리스크가 크고 혹시나 해당 값이 추후에는 null이 될 수 있기 때문에 지양해야 된다고 생각한다.

    -
    val length: Int = word!!.length
    -
    -

    as? 안전한 캐스팅

    -

    타입 변환을 할 때 지정한 타입으로 변경할 수 없다면 ClassCastException이 발생한다.
    -코틀린에서는 as 뒤에 ?를 붙여 안전하게 타입 변환을 할 수 있다.
    -따라서 미리 변환 가능한 타입인지 확인하지 않고, 안전하게 타입을 변환 할 수 있다.

    -

    타입 변환이 불가능 할 경우 예외를 발생시키지 않고 null을 반환한다.

    -
    val value: Int? = something as? Int
    -
    -

    List에서의 null 처리

    -

    List에는 null이 아닌 값만 반환하는 filterNotNull 유틸리티 메서드를 제공한다.

    -
    val foodsWithNull: List<String?> = listOf("Pizza", "Cheese", null, "Potato")
    -val foods = foodsWithNull.filterNotNull()
    -
    +

    · 약 8분

    웹 애플리케이션 발전 과정

    +

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    +간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.
    +원래 회고에 작성하려고 했지만, 정리하다 보니 조금 길어져서 따로 분리했다.

    + +

    WWW(1989)

    +

    정적 페이지를 제공하는 웹 서버를 시작으로 동적 페이지가 필요했기 때문에 CGI가 등장했다.

    +

    CGI(1993)

    +

    CGI는 동적 콘텐츠를 제공하기 위한 규약으로, 해당 인터페이스를 구현한 스크립트를 이용해서 매 요청마다 프로세스를 실행시켜 정보를 반환하도록 한다. 하지만 매 요청마다 프로세스를 실행시키기 때문에 서버에 많은 부하가 발생할 수 있다. 따라서 이러한 단점을 극복하기 위해 나온 것이 Servlet이다.

    +

    Servlet(1996)

    +

    Servlet은 웹 서버에서 실행되는 자바 프로그램으로 HTTP를 이용하여 웹 클라이언트의 요청을 수신하고 응답한다. CGI와 다르게 매 요청마다 프로세스가 아닌 스레드를 생성하여 응답한다.
    +하지만 View 영역의 코드를 작성하기 위해 Servlet의 소스 코드를 알아야 하는 등 복잡도가 너무 높았다. 따라서 해당 문제를 해결하기 위해 JSP가 등장했다.

    +

    JSP(1999)

    +

    JSP는 HTML에 자바 코드를 작성하여 동적 웹 페이지를 생성하는 기술로, 유사한 기술로는 ASP, PHP가 있다.
    +JSP만 사용하여 프로그래밍한다면 Model 1, 아래 구성도와 같이 JSP가 View 영역만 담당한다면 Model 2라고 한다.

    + +

    MVC(2000)

    +

    위 JSP의 구성도를 보면 현재 MVC와 매우 유사한데, Govind Seshadri라는 사람이 JSP Model 2를 MVC 패턴으로 공식화를 제안했다.

    +
    +

    I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern.
    +Govind Seshadri

    +
    +

    이때 MVC 패턴이 처음 탄생한 것은 아니고, 서버 측 구현이라고 하는 것을 보니 MVC가 처음 등장한 건 아닌 것 같다.
    +해당 문서를 보면 MVC라는 용어의 등장은 1978년에 등장한 것으로 보인다.

    +

    Spring Framework(2003)

    +

    Spring은 복잡했던 J2EE을 대체하기 위해 2003년에 등장했다.
    +J2EE는 웹 기반의 엔터프라이즈 애플리케이션을 구축하기 위한 플랫폼으로 위에서 설명한 Servlet, JSP, EJB 등의 기술을 포함하고 있다.
    +하지만 이중 EJB라는 기술이 J2EE의 핵심 기술이었는데, 해당 기술이 매우 복잡했기 때문에 사용에 문제가 많았다고 한다.
    +2002년에 Rod Johnson이 EJB를 사용하지 않고 J2EE 애플리케이션을 구축하는 방법에 대해 저술한 Expert One-to-One J2EE Development라는 책을 발행했고, 출간 후 Juergen Hoeller, Yann Caroff가 Rod Johnson에게 오픈소스 제안을 하여 스프링이 탄생했다고 한다.

    +

    스프링은 엔터프라이즈 서비스 기능을 POJO에 제공하며, 이 덕분에 스프링을 사용하여 비즈니스 로직에 집중할 수 있다.

    +

    WebFlux 이전 Servlet 3.0(2009), 3.1(2013)

    +

    Tomcat의 NIO 동작 방식을 보면 Poller가 소켓 커넥션을 들고 있다가 처리가 가능할 때 스레드를 할당하는 식으로 처리를 한다. 하지만 할당 후 Servlet과 통신하는 부분은 블로킹 방식으로 요청이 끝날 때까지 스레드를 점유하고 있었고, 스레드 점유로 인해 요청이 max thread에 도달하면 요청을 처리할 수 없었다.
    +그래서 비동기 방식의 Servlet이 Servlet 3.0에 등장했다. 하지만 전통적인 I/O 방식을 사용하는 부분은 블로킹 방식으로 동작했다. Servlet 3.1에서 논블로킹 I/O가 추가되었지만, 많이 사용되지 않았다고 한다.

    +

    Spring WebFlux(2017)

    +

    적은 수의 스레드로 동시성을 처리하고, 적은 리소스로 확장이 가능한 논블로킹 방식의 웹 기술이 필요했고, 기존의 Servlet의 경우 비동기를 지원한다 해도 동기식 API들이 많이 남아있었기 때문에 이러한 Servlet에 영향을 받지 않는 기술이 필요했다. 또한 기존에 Netty와 같이 비동기, 논블로킹 방식 서버로 자리를 잘 잡은 서버를 위해 Spring WebFlux가 등장했다.
    +추가로 데이터 접근을 위해 사용하는 JDBC의 경우 Blocking API라, Spring Webflux에서는 R2DBC를 사용한다고 한다.

    +

    마치며

    +

    해당 정리 내용의 경우 Async, Non Blocking 관련된 내용을 깊게 공부한 적이 없어서 정확하지 않을 수 있다.
    +그래도 기술의 등장 배경이나 과정을 알고 있다면 조금 더 깊이 있는 학습에 도움이 된다고 생각한다.

    참고 자료

    -
    +

    웹 애플리케이션의 발전 과정, 구구 강의
    +Dynamic Content with CGI, Apache Tutorial
    +History of Spring and the Spring Framework, Spring
    +Understanding JavaServer Pages Model 2 architecture, Govind Seshadri
    +MVC, XEROX PARC
    +Expert One-to-One J2EE Development, Rod Johnson
    +배달의민족 최전방 시스템! ‘가게노출 시스템’을 소개합니다, 배달의민족
    +Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu +WebFlux Overview, Spring +Spring WebFlux와 Armeria를 이용하여 Microservice에 필요한 Reactive + RPC 동시에 잡기, Naver D2
    +Spring WebFlux란 무엇일까

    \ No newline at end of file diff --git a/page/48.html b/page/48.html index 442a7c953..de5052059 100644 --- a/page/48.html +++ b/page/48.html @@ -13,46 +13,91 @@ - - + + -

    · 약 2분

    이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    -ISO-8601을 기반으로 작성
    -설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

    -

    날짜와 시간에 관련된 데이터를 다루는 국제 표준

    -

    LocalDate, LocalTime, LocalDateTime

    -

    날짜와 시간을 표현하는 클래스

    -

    Instant

    -

    유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
    -기계의 관점에서 시간 표현

    -

    Duration, Period

    -

    간격을 표현하는 클래스

    -

    TemporalAdjusters

    -

    복잡한 날짜 조정이 필요할 때 사용
    -필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

    -
    @FunctionalInterface
    -public interface TemporalAdjuster {
    -    Temporal adjustInto(Temporal temporal);
    +

    · 약 5분

    테스트 격리

    +

    테스트의 순서에 따라 성공 실패 여부가 결정되는 비결정적인(non-determinism) 테스트가 되어서는 안되고, 테스트는 항상 순서에 상관없이 독립적으로 수행되도록 보장되어야 한다. 일반적으로 자원의 공유, 외부 API, 시간 등으로 비결정적인 테스트가 된다. 이를 해결하기 위해 테스트 대역을 사용하거나, 컨텍스트를 재실행하는 @DirtiesContext, 자원을 초기화하기 위해 테스트 이후에 테이블을 롤백 하는 @Transactional등 다양한 방법이 있다.
    +해당 글에서는 스프링에서 데이터베이스 자원의 공유를 방지하기 위해 테스트 격리를 수행하는 부분에 대해 설명한다.

    +

    테스트끼리 서로 의존하면 안 된다.
    +서로 의존하게 된다면 하나의 테스트가 실패할 때, 또 다른 하나의 테스트가 실패할 수 있다.
    +다른 테스트에 의존하지 않고, 독립적으로 실행 가능한 테스트가 좋은 테스트다.

    +

    TestExecutionListener

    +

    스프링에서는 TextExecutionListner를 이용하여 각 테스트 실행 단계에서 이벤트를 수신할 수 있다.
    +이를 이용하면 JUnit의 @BeforeEach를 사용하는 것과 유사하게, 테스트의 생명주기 이전 또는 이후에 필요한 작업을 실행시킬 수 있다.

    +
    public interface TestExecutionListener {
    +    default void beforeTestClass(TestContext testContext) throws Exception {}
    +    default void prepareTestInstance(TestContext testContext) throws Exception {}
    +    default void beforeTestMethod(TestContext testContext) throws Exception {}
    +    default void beforeTestExecution(TestContext testContext) throws Exception {}
    +    default void afterTestExecution(TestContext testContext) throws Exception {}
    +    default void afterTestMethod(TestContext testContext) throws Exception {}
    +    default void afterTestClass(TestContext testContext) throws Exception {}
     }
     
    -

    DateTimeFormatter

    -

    날짜와 시간 포맷 클래스
    -특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

    -

    ZoneId, ZoneOffset

    -

    ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
    -ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

    -
    Instant instant = Instant.now();
    -LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
    +

    AbstractTestExecutionListener 상속하여 구현

    +

    AbstractTestExecutionListener를 상속받아 테스트 격리 환경을 만들어주는 클래스로, 인터페이스인 TextExecutionListner와 달리 Ordered가 구현되어 있어 해당 클래스를 상속받아 구현한 클래스는 프레임워크가 제공하는 리스너 다음에 실행시키도록 해준다.
    +다음과 같이 데이터베이스에서 각각의 테이블에 해당하는 Truncate 쿼리를 만들어서 조회하고, Test 메서드가 끝날때 마다 해당 쿼리를 실행하여 테이블을 초기화시키도록 설정한다.

    +
    
    +public class DatabaseCleaner extends AbstractTestExecutionListener {
    +
    +    private static final String TRUNCATE_TABLE_QUERY = """
    +            SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ';') 
    +            FROM INFORMATION_SCHEMA.TABLES
    +            WHERE TABLE_SCHEMA = 'PUBLIC'
    +            """;
    +
    +    @Override
    +    public void afterTestMethod(TestContext testContext) {
    +        JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);
    +        List<String> truncateTableQueries = getTruncateTableQueries(jdbcTemplate);
    +        truncateTables(jdbcTemplate, truncateTableQueries);
    +    }
    +
    +    private JdbcTemplate getJdbcTemplate(TestContext testContext) {
    +        return testContext.getApplicationContext().getBean(JdbcTemplate.class);
    +    }
    +
    +    private List<String> getTruncateTableQueries(JdbcTemplate jdbcTemplate) {
    +        return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);
    +    }
    +
    +    private void truncateTables(JdbcTemplate jdbcTemplate, List<String> truncateTableQueries) {
    +        jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");
    +        truncateTableQueries.forEach(jdbcTemplate::execute);
    +        jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");
    +    }
    +}
    +
    +
    +

    Listener 등록

    +

    @TestExecutionListeners를 이용하여 사용자 정의 리스너를 등록할 수 있다.
    +mergeMode의 기본값은 REPLACE_DEFAULTS로 리스너가 이미 존재하는 경우 등록된 리스너로 변경된다.
    +MERGE_WITH_DEFAULTS로 설정한다면 Ordered 기준으로 순서가 결정된다.
    +이후 격리가 필요한 테스트들은 다음의 추상 클래스를 상속하여 사용하면 된다.

    +
    
    +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    +@TestExecutionListeners(
    +        value = DatabaseCleaner.class,
    +        mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
    +)
    +public abstract class AcceptanceTest {
    +
    +    @LocalServerPort
    +    private int port;
    +
    +    @BeforeEach
    +    public void setUp() {
    +        RestAssured.port = port;
    +    }
    +}
    +
     

    참고 자료

    -
    +

    The Spring TestExecutionListener, Baeldung
    +인수테스트에서 테스트 격리하기, 테코블
    +Eradicating Non-Determinism in Tests, martin fowler
    +@SpringBootTest의 테스트 격리시키기, MangKyu

    \ No newline at end of file diff --git a/page/49.html b/page/49.html index 831464d8a..f4e22f898 100644 --- a/page/49.html +++ b/page/49.html @@ -13,80 +13,95 @@ - - + + -

    · 약 6분

    책 정보

    -
    -

    객체지향의 사실과 오해
    -조영호

    -
    -

    읽고 나서

    -

    조영호님의 오브젝트를 읽고 나서 다시 한 번 읽어보았다.
    -아직 이해가 안되는 부분이 많지만, 그래도 항상 새로움을 느낀다.
    -더할 나위 없이 휼륭한 객체지향 책이고, 조금 더 공부하고 다시 읽어봐야될 것 같다.

    -

    커피 전문점, 지하철 노선도, 이상한 나라의 엘리스를 예시로 든 설명이 너무 좋았고
    -좋은 내용을 담고 있지만 그렇다고 너무 무겁지 않아 가볍게 읽기도 좋은 것 같다.

    -

    책임의 자율성을 강조하는 이유 p.173

    -

    협력을 단순하게 만든다.

    +

    · 약 6분

    1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
    +2단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465
    +3단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580

    +

    MVC 구현

    +

    Reflection을 이용하여 Spring MVC와 유사한 기능을 구현하는 미션이었다.
    +미션의 목표는 다음과 같았다.

      -
    • 의도를 명확하게 표현 → 협력의 복잡함 저하
    • -
    • 책임의 추상화
    • +
    • MVC 프레임워크를 구현하면서 내부 동작 원리를 학습한다.
    • +
    • 점진적인 리팩토링을 경험한다.
    -

    외부와 내부를 명확하게 분리한다.

    -
      -
    • 요청하는 객체가 몰라도 되는 부분이 캡슐화됨으로 인터페이스와 구현의 분리
    • -
    -

    책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않는다.

    -
      -
    • 변경의 파급효과를 객체 내부로 캡슐화 → 메시지를 보내는 객체와의 결합도 저하
    • -
    -

    협력의 대상을 다양하게 선택할 수 있는 유연성을 제공한다.

    -
      -
    • 유연한 설계 → 재사용성 증가
    • -
    -

    객체의 역할을 이해하기 쉬워진다.

    -
      -
    • 응집도를 높은 상태로 유지
    • -
    -

    밑줄 친 문장들

    -
    -

    객체지향의 목표는 실세계를 모방하는 것이 아니다. -오히려 새로운 세계를 창조하는 것이다. -소프트웨어 개발자의 역할은 단순히 실세계를 소프트웨어 안으로 옮겨 담는 것이 아니라 고객과 사용자를 만족시킬 수 있는 신세계를 창조하는 것이다. -p.21

    -
    -
    -

    과거의 전통적인 개발 방법은 데이터와 프로세스를 엄격하게 구분한다. -이에 반해 객체지향에서는 데이터와 프로세스를 객체라는 하나의 틀 안에 함께 묶어 놓음으로써 객체의 자율성을 보장한다. -자율적인 객체로 구성된 공동체는 유지 보수가 쉽고 재사용이 용이한 시스템을 구축할 수 있는 가능성을 제시한다. -p.33

    -
    -
    -

    객체지향의 본질

    -

    시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법

    -

    자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.

    -

    객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.

    -

    객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다. -p.35

    -
    -
    -

    클래스의 구조와 메서드가 아니라 객체의 역할, 책임, 협력에 집중하라. -객체지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다. -p.38

    -
    -
    -

    객체지향에서 중요한 것은 동적으로 변하는 객체의 ‘상태’와 상태를 변경하는 ‘행위’다. -클래스는 타입을 구현하기 위해 프로그래밍 언어에서 제공하는 구현 메커니즘이라는 사실을 기억하라. -p.105

    -
    -
    -

    책임 주도 설계의 핵심은 어떤 행위가 필요한지를 먼저 결정한 후에 이 행위를 수행할 객체를 결정하는 것이다. -이 과정을 흔히 What/Who 사이클이라고 한다. -’어떤 행위(What)’를 수행할 것인지 결정한 후 ‘누가(who)’ 그 행위를 수행할 것인지 결정해야 한다. -여기서 ‘어떤 행위’가 바로 메시지다. -p.158

    -
    +

    미션의 목표와 더불어 각 클래스들이 역할과 책임을 적절히 가지도록 하고, 패키지의 의존 방향을 고민하면서 미션을 진행하는 것에 중점을 두었다.

    +

    애너테이션 기반 프레임워크 만들기

    +

    기존 코드에 ManualHandlerMapping이라는 서블릿을 직접 등록해서 사용하는 HandlerMapping 클래스가 있었고, 1단계에서는 애너테이션 기반의 AnnotationHandlerMapping을 구현해야 했기 때문에 @Controller, @RequestMapping을 Reflection을 이용하여 스캔하고, 핸들러 매핑을 등록하는 부분까지 진행해야 했다.
    +테오가 @GetMapping이나 @PostMapping 부분도 진행하면 재밌을 것 같다고 해서 같이 진행해 보았다.
    +추가로 미션 요구사항은 아니었지만 클래스 레벨에 적용된 @RequestMapping도 동작하도록 구현해보았다.

    + +

    다음과 같은 Flow로 Handler(실제 요청을 처리하는 메서드) 등록을 진행한다.

    +
      +
    1. @Controller가 적용된 클래스의 정보를 스캔하여 반환한다.
    2. +
    3. @Controller가 적용된 클래스의 @RequestMapping이 적용된 메서드들의 정보를 반환한다.
    4. +
    5. 각 메서드들을 순회하며 HandlerKey(uri + httpMethod 정보)와 HandlerExecution(인스턴스 + 실행하려는 메서드)을 생성하여 Map<HandlerKey, HandlerExecution>에 추가한다.
    6. +
    +

    AnnotationHandlerMapping의 initialize 메서드에서 Handler를 등록한다. 코드는 다음과 같다.

    +
    public void initialize() {
    +    if (!initialized.compareAndSet(false, true)) {
    +        return;
    +    }
    +
    +    final Map<Class<?>, ControllerInstance> controllers = annotationScanner.scanControllers();
    +    final Set<Method> methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());
    +    for (final Method method : methods) {
    +        final ControllerInstance controller = controllers.get(method.getDeclaringClass());
    +        final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);
    +        final List<HandlerKey> handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);
    +        handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));
    +    }
    +
    +    log.info("Initialized AnnotationHandlerMapping!");
    +    handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));
    +}
    +
    +

    Legacy MVC와 @MVC 통합

    +

    2단계는 Legacy MVC와 AnnotationHandlerMapping을 통합하는 부분이었다.
    +기존의 MVC와 애너테이션이 적용된 MVC 두 개를 같이 사용할 수 있어야 헀다.
    +대략적인 흐름은 다음과 같다.

    +
      +
    1. DispatcherServlet.service(request, response) 호출
    2. +
    3. HandlerMappings를 통해 입력받은 request에 해당하는 Handler 조회
    4. +
    5. HandlerAdapters를 통해 Handler를 실행시킬 수 있는 HandlerAdapter 조회
    6. +
    7. HandlerAdapter의.handle 메서드 실행
    8. +
    9. View의 render 호출
    10. +
    + +

    웹 애플리케이션 발전 과정

    +

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    +간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.

    + +

    내용이 길어져서 다음 문서에 정리했다.

    +

    추상적인 개념 학습 방법

    +

    직관적이지 않은 추상적인 개념을 학습할 때는 개념의 구현을 참고하면 학습에 도움이 된다고 한다.

    +
    개념구현
    OOPJava
    WASTomcat, Jetty
    IoCSpring BeanFactory, Servlet Container, Framework
    DISpring BeanFactory
    +

    정리

    +

    지금까지 스프링의 DispatcherServlet의 동작을 이론적으로만 알고 있었는데, 실제로 구현해 보니 조금 더 이해가 잘 가는 것 같다.
    +이번 미션에서 나의 리뷰어는 루카, 리뷰이는 헤나였다.
    +매 단계마다 꼼꼼하게 리뷰해 준 루카에게 너무 감사하고, 헤나에게 이상한 리뷰를 많이 남긴 것 같은데 꼼꼼히 반영해줘서 감사하다.
    +오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

    \ No newline at end of file diff --git a/page/5.html b/page/5.html index a20e4663e..b54d21474 100644 --- a/page/5.html +++ b/page/5.html @@ -13,69 +13,75 @@ - - + + -

    · 약 8분

    웹 애플리케이션 발전 과정

    -

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    -간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.
    -원래 회고에 작성하려고 했지만, 정리하다 보니 조금 길어져서 따로 분리했다.

    - -

    WWW(1989)

    -

    정적 페이지를 제공하는 웹 서버를 시작으로 동적 페이지가 필요했기 때문에 CGI가 등장했다.

    -

    CGI(1993)

    -

    CGI는 동적 콘텐츠를 제공하기 위한 규약으로, 해당 인터페이스를 구현한 스크립트를 이용해서 매 요청마다 프로세스를 실행시켜 정보를 반환하도록 한다. 하지만 매 요청마다 프로세스를 실행시키기 때문에 서버에 많은 부하가 발생할 수 있다. 따라서 이러한 단점을 극복하기 위해 나온 것이 Servlet이다.

    -

    Servlet(1996)

    -

    Servlet은 웹 서버에서 실행되는 자바 프로그램으로 HTTP를 이용하여 웹 클라이언트의 요청을 수신하고 응답한다. CGI와 다르게 매 요청마다 프로세스가 아닌 스레드를 생성하여 응답한다.
    -하지만 View 영역의 코드를 작성하기 위해 Servlet의 소스 코드를 알아야 하는 등 복잡도가 너무 높았다. 따라서 해당 문제를 해결하기 위해 JSP가 등장했다.

    -

    JSP(1999)

    -

    JSP는 HTML에 자바 코드를 작성하여 동적 웹 페이지를 생성하는 기술로, 유사한 기술로는 ASP, PHP가 있다.
    -JSP만 사용하여 프로그래밍한다면 Model 1, 아래 구성도와 같이 JSP가 View 영역만 담당한다면 Model 2라고 한다.

    - -

    MVC(2000)

    -

    위 JSP의 구성도를 보면 현재 MVC와 매우 유사한데, Govind Seshadri라는 사람이 JSP Model 2를 MVC 패턴으로 공식화를 제안했다.

    -
    -

    I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern.
    -Govind Seshadri

    -
    -

    이때 MVC 패턴이 처음 탄생한 것은 아니고, 서버 측 구현이라고 하는 것을 보니 MVC가 처음 등장한 건 아닌 것 같다.
    -해당 문서를 보면 MVC라는 용어의 등장은 1978년에 등장한 것으로 보인다.

    -

    Spring Framework(2003)

    -

    Spring은 복잡했던 J2EE을 대체하기 위해 2003년에 등장했다.
    -J2EE는 웹 기반의 엔터프라이즈 애플리케이션을 구축하기 위한 플랫폼으로 위에서 설명한 Servlet, JSP, EJB 등의 기술을 포함하고 있다.
    -하지만 이중 EJB라는 기술이 J2EE의 핵심 기술이었는데, 해당 기술이 매우 복잡했기 때문에 사용에 문제가 많았다고 한다.
    -2002년에 Rod Johnson이 EJB를 사용하지 않고 J2EE 애플리케이션을 구축하는 방법에 대해 저술한 Expert One-to-One J2EE Development라는 책을 발행했고, 출간 후 Juergen Hoeller, Yann Caroff가 Rod Johnson에게 오픈소스 제안을 하여 스프링이 탄생했다고 한다.

    -

    스프링은 엔터프라이즈 서비스 기능을 POJO에 제공하며, 이 덕분에 스프링을 사용하여 비즈니스 로직에 집중할 수 있다.

    -

    WebFlux 이전 Servlet 3.0(2009), 3.1(2013)

    -

    Tomcat의 NIO 동작 방식을 보면 Poller가 소켓 커넥션을 들고 있다가 처리가 가능할 때 스레드를 할당하는 식으로 처리를 한다. 하지만 할당 후 Servlet과 통신하는 부분은 블로킹 방식으로 요청이 끝날 때까지 스레드를 점유하고 있었고, 스레드 점유로 인해 요청이 max thread에 도달하면 요청을 처리할 수 없었다.
    -그래서 비동기 방식의 Servlet이 Servlet 3.0에 등장했다. 하지만 전통적인 I/O 방식을 사용하는 부분은 블로킹 방식으로 동작했다. Servlet 3.1에서 논블로킹 I/O가 추가되었지만, 많이 사용되지 않았다고 한다.

    -

    Spring WebFlux(2017)

    -

    적은 수의 스레드로 동시성을 처리하고, 적은 리소스로 확장이 가능한 논블로킹 방식의 웹 기술이 필요했고, 기존의 Servlet의 경우 비동기를 지원한다 해도 동기식 API들이 많이 남아있었기 때문에 이러한 Servlet에 영향을 받지 않는 기술이 필요했다. 또한 기존에 Netty와 같이 비동기, 논블로킹 방식 서버로 자리를 잘 잡은 서버를 위해 Spring WebFlux가 등장했다.
    -추가로 데이터 접근을 위해 사용하는 JDBC의 경우 Blocking API라, Spring Webflux에서는 R2DBC를 사용한다고 한다.

    -

    마치며

    -

    해당 정리 내용의 경우 Async, Non Blocking 관련된 내용을 깊게 공부한 적이 없어서 정확하지 않을 수 있다.
    -그래도 기술의 등장 배경이나 과정을 알고 있다면 조금 더 깊이 있는 학습에 도움이 된다고 생각한다.

    +

    · 약 5분

    nullable 타입

    +

    코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
    +이는 실행 시점이 아닌 컴파일 시 미리 오류가 발생할 가능성이 있는 부분을 미리 감지하여 NPE 발생의 가능성을 줄여준다.

    +

    코틀린의 경우 nullable 타입을 다음과 같이 표현한다.

    +
    val number: Int?
    +
    +

    타입 뒤에 ?를 붙여 해당 값이 null이 될 수 있다는 것을 의미한다.
    +만약 ?를 붙이지 않을 때 null을 받는 경우 컴파일 시 오류가 발생한다.

    +

    ?. Safe Calls 연산자

    +

    자바에서 NPE를 발생시키지 않기 위해 null을 처리하는 가장 간단한 방법으로는 분기를 사용하는 방법이 있다.

    +

    코틀린은 안전한 호출 연산자인 ?. 연산자를 지원한다.
    +따라서 참조 값이 null이 아닐 경우에만 메서드 호출을 할 수 있다.
    +참조 값이 null인 경우 메서드 호출이 무시되고, null을 반환한다.

    +
    public String repeat(String word) {
    +    if (word == null) {
    +        return null;
    +    }
    +    return word.repeat(2);
    +}
    +
    +

    ?: 엘비스 연산자

    +

    참조하려는 값이 null일 경우 기본 값을 반환하고 싶을 때는 어떻게 해야 할까?
    +코틀린은 null이 아닌 경우 기본 값을 지정할 때 사용할 수 있는 엘비스 연산자를 지원한다.

    +
    public String stringSafe(String word) {
    +    if (word == null) {
    +        return "";
    +    }
    +    return word;
    +}
    +
    +

    코틀린에서는 throw도 식이기 때문에 엘비스 연산자를 이용하여 예외를 던질 수 있다.
    +예를 들어 사용자 정보가 있는 저장소에 찾는 사용자가 없는 경우 아래와 같이 사용할 수 있다.

    +
    userRepository.findByName(name) ?: throw IllegalArgumentException()
    +
    +

    !! 널 아님 단언 연산자

    +

    !! 연산자를 이용한다면 강제로 어떤 값이든 non-nullable 타입으로 변경할 수 있다.
    +하지만 null인 값에 사용한다면 NPE가 발생하게 된다.
    +일반적인 경우에는 !! 연산자를 사용하는 것은 위험하다.
    +사용하기 쉽지만, 리스크가 크고 혹시나 해당 값이 추후에는 null이 될 수 있기 때문에 지양해야 된다고 생각한다.

    +
    val length: Int = word!!.length
    +
    +

    as? 안전한 캐스팅

    +

    타입 변환을 할 때 지정한 타입으로 변경할 수 없다면 ClassCastException이 발생한다.
    +코틀린에서는 as 뒤에 ?를 붙여 안전하게 타입 변환을 할 수 있다.
    +따라서 미리 변환 가능한 타입인지 확인하지 않고, 안전하게 타입을 변환 할 수 있다.

    +

    타입 변환이 불가능 할 경우 예외를 발생시키지 않고 null을 반환한다.

    +
    val value: Int? = something as? Int
    +
    +

    List에서의 null 처리

    +

    List에는 null이 아닌 값만 반환하는 filterNotNull 유틸리티 메서드를 제공한다.

    +
    val foodsWithNull: List<String?> = listOf("Pizza", "Cheese", null, "Potato")
    +val foods = foodsWithNull.filterNotNull()
    +

    참고 자료

    -

    웹 애플리케이션의 발전 과정, 구구 강의
    -Dynamic Content with CGI, Apache Tutorial
    -History of Spring and the Spring Framework, Spring
    -Understanding JavaServer Pages Model 2 architecture, Govind Seshadri
    -MVC, XEROX PARC
    -Expert One-to-One J2EE Development, Rod Johnson
    -배달의민족 최전방 시스템! ‘가게노출 시스템’을 소개합니다, 배달의민족
    -Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu -WebFlux Overview, Spring -Spring WebFlux와 Armeria를 이용하여 Microservice에 필요한 Reactive + RPC 동시에 잡기, Naver D2
    -Spring WebFlux란 무엇일까

    +
    \ No newline at end of file diff --git a/page/50.html b/page/50.html index a4659c216..0c4e007dd 100644 --- a/page/50.html +++ b/page/50.html @@ -13,37 +13,93 @@ - - + + -

    · 약 4분

    적당한 전환점, 2022년을 돌아보며

    -

    전역

    -

    약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
    -조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

    -

    조금 더 미래에 대한 생각을 해볼걸 그랬다.
    -전역을 했지만 뭐 하나 제대로 할 줄 아는 것도 없으니 넓은 바닷속에 덩그러니 놓아진 기분이 괜히 들었었다.
    -일찍 생각을 정리하여 방향을 잡지 못했기에 아쉬움이 많이 남았다.

    -

    자바

    -

    전역을 하고 진로를 고민하다 향로님의 자바 공화국 포스팅을 읽고 나서 자바 공부를 시작했다.
    -유명한 인프런의 김영한님의 스프링 강의도 있고, 좋은 자바 개발 서적이 많아서 독학하기로 결정했다.
    -하다 보니 자바와 스프링을 공부하면서 “왜 진작하지 않았지”라는 생각도 많이 들었다.
    -양질의 자료도 많았기 때문에, 예전에 노드로 개발했을 때 풀지 못했던 답답함을 많이 해소했던 것 같다.

    -

    23년에는 조금 더 깊게 자바를 공부해볼 생각이다.
    -언어를 하나 깊게 공부하는 건 많은 도움이 되는 것 같다.

    -

    스터디

    -

    김영한님의 강의를 거의 다 들었을 때쯤, 항상 강의에서 언급되는 토비의 스프링을 읽어보고 싶어졌고
    -혼자 공부하기에는 동기부여도 부족했기 때문에 스터디를 시작했다.
    -다른 사람에게 설명을 해야 했기 때문에 더욱 꼼꼼하게 공부를 할 수 있어서 좋았지만 나에게는 내용이 꽤나 어려워서 시간을 많이 소비했다.
    -같이 스터디하시는 분과 7개월 동안 스터디를 꾸준히 이어나가 총 3권의 책을 읽을 수 있었다.

    -

    우아한 테크코스

    -

    군 복무 중일 때 지원했다 떨어진 우아한 테크코스를 다시 지원했다.
    -이번 연도에 취업을 하는 게 목표였지만 내가 가지고 있는 특별한 무기가 없다는 걸 깨달았다.
    -적지 않은 시간을 투자해 준비를 했고, 감사하게도 이번에는 최종 합격을 했다.

    -

    난 사람들과 소통하고, 협업하는 능력이 부족하다고 생각을 많이 했다.
    -우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

    -

    2023년에는

    -

    마음의 여유가 없었던 2022년이었던 것 같다.
    -하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

    +

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
    +2단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358
    +3단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448
    +4단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515

    +

    Jdbc 구현

    +

    이번 미션은 Jdbc 라이브러리를 구현하고, Transaction 경계 설정과 동기화하는 부분을 구현해 보는 미션이었다.
    +미션 목표는 다음과 같다.

    +
      +
    • JDBC 라이브러리를 구현하면서 중복을 제거하는 연습을 한다.
    • +
    • 데이터베이스에 대한 이해도를 높인다.
    • +
    +

    최대한 Java가 제공하는 기능을 사용하여 리팩터링 하는 방향으로 코드를 작성했다.

    +

    JdbcTemplate

    +

    JdbcTemplate은 Connection을 이용하여 PreparedStatement를 생성하는 부분, 그리고 PreparedStatement가 어떻게 동작하는지에 대한 부분을 분리했다.
    +템플릿 콜백 패턴을 적절하게 적용하여 중복을 비교적 간단하게 제거할 수 있었다.
    +예전에도 미션을 진행하면서 JdbcTemplate을 구현한 적이 있었는데, 이번에는 자원 할당과 해제 부분에 대한 중복도 제거했다.

    +
    public class JdbcTemplate {
    +
    +    private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);
    +
    +    private final DataSource dataSource;
    +    private final StatementCreator statementCreator;
    +    private final StatementExecutor statementExecutor;
    +
    +    public JdbcTemplate(final DataSource dataSource) {
    +        this(dataSource, new StatementCreator(), new StatementExecutor());
    +    }
    +
    +    JdbcTemplate(
    +            final DataSource dataSource,
    +            final StatementCreator statementCreator,
    +            final StatementExecutor statementExecutor
    +    ) {
    +        this.dataSource = dataSource;
    +        this.statementCreator = statementCreator;
    +        this.statementExecutor = statementExecutor;
    +    }
    +
    +    private <T> T query(
    +            final String sql,
    +            final PreparedStatementCallback<T> preparedStatementCallback,
    +            final Object... parameters
    +    ) {
    +        final Connection connection = DataSourceUtils.getConnection(dataSource);
    +        try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {
    +            return preparedStatementCallback.execute(preparedStatement);
    +        } catch (final SQLException e) {
    +            log.error(e.getMessage(), e);
    +            throw new DataAccessException(e);
    +        } finally {
    +            DataSourceUtils.releaseConnection(connection, dataSource);
    +        }
    +    }
    +
    +    public void update(final String sql, final Object... parameters) {
    +        query(sql, PreparedStatement::executeUpdate, parameters);
    +    }
    +
    +    public <T> Optional<T> queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
    +        final List<T> results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
    +        if (results.size() > 1) {
    +            throw new DataAccessException("2개 이상의 결과를 반환할 수 없습니다.");
    +        }
    +        return results.stream().findAny();
    +    }
    +
    +    public <T> List<T> queryForList(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
    +        return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
    +    }
    +}
    +
    +

    트랜잭션 적용

    +

    3, 4단계는 기존의 코드에 트랜잭션을 시작하고 끝나는 부분인 트랜잭션 경계를 설정하고 ThreadLocal을 이용하여 트랜잭션 동기화(Transaction synchronization)를 적용하는 미션이었다.
    +트랜잭션 동기화란 트랜잭션을 시작하기 위한 Connection 객체를 ThreadLocal과 같은 공간에 따로 저장 후, 필요할 때 저장된 Connection을 가져다 사용하는 방식이다.
    +아래와 같은 구조로 미션을 진행했는데, ThreadLocal에 Connection 객체가 아닌, Connection 객체와 Transaction이 진행 중인지 확인할 수 있는 flag를 가지고 있는 클래스를 저장해서 사용하도록 했다.

    + +

    마무리

    +

    Jdbc 미션을 진행하면서 AOP나 Transactional에 대한 학습 테스트도 진행하고, 약간 알찬 미션이었던 것 같다.
    +꼼꼼히 코드를 봐준 리뷰어 호이 그리고 연휴 동안 계속 티키타카 하면서 재밌게 리뷰한 민트에게 감사하다.
    +회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

    \ No newline at end of file diff --git a/page/51.html b/page/51.html index 9ce48ff8a..761ea74e8 100644 --- a/page/51.html +++ b/page/51.html @@ -13,49 +13,65 @@ - - + + -

    · 약 5분

    책 정보

    -
    -

    글, 우리도 잘 쓸 수 있습니다.
    -박솔미

    -
    -

    읽고 나서

    -

    저자의 경험과 함께 글쓰기에 대한 가벼운 조언이 담겨있어 가볍게 읽기 좋았다.
    -글을 잘 작성해 보고 싶을 때 적용해 볼 수 있는 정보가 많아서 도움이 되었다.

    -

    우아한 테크코스의 프리코스를 진행할 때 후기를 작성하고 나면 항상 글이 딱딱하다는 느낌을 받았다.
    -다른 지원자들의 읽기 편하고, 밝은 느낌을 주는 글을 보면 부러운 마음을 가지기도 했다.
    -이 책을 읽었으니 2023년에는 조금 더 글을 잘 적어보려고 한다.

    -

    밑줄 친 문장들

    -
    -

    문장이 심심하고 지루하다면 -내용을 일목요연하게 정리했고, 글의 의도도 삐뚤지 않고, 단어도 적절한 것으로 골랐는데… 그런데도 어딘가가 심심하고 지루하다면? 축축 처지고 따분하다면? 말꼬리를 모조리 ‘~다’로 통일한 건 아닌지 점검해 보세요.

    -
    -
    -

    말꼬리를 잘 갖고 놀아야 합니다. 문장의 마지막 글자를 매번 다르게 고쳐쓰는 것만으로도 글에 활기를 더할 수 있죠. 때론 문장을 다 마치지 않고, 단어로만 끝맺는 것도 방법. 문장과 문장 사이에 쉼표가 들어서며 글 전체에 활기가 돌게 돼요. 문장의 길이도 다채로워지는 덕분에 덤으로 얻게 되는 것도 있습니다. 바로, 글의 리듬.

    -
    -
    -

    이전 문장에서 끝난 글자로, 다음 문장을 끝맺지 않기. 한두 문단마다 단어 수준의 아주 짧은 문장 배치하기.

    -
    -
    -

    글의 진짜 이유, 글의 진짜 목적, 글의 진짜 대상을 찾으려고 애썼습니다. 지금처럼 틀을 떠올린다거나, 눈치를 본다거나, 정치적인 셈도 하지 않았어요.

    -
    -
    -

    제목은 짧게, 보기 쉽게, 읽기 쉽게, 발음이 비슷하게, 순서를 바꿔서

    -
    -
    -

    글을 마지막으로 다듬을 때, 노래에 가까워질 방법은 없을지 고민해봅니다. 감히 가 닿을 수 없는 목표이겠지만, 할 수 있는 최소한의 리듬이라도 붙여주고 싶어요.

    -
    -
    -

    여는 말과 마지막 말에 작정하고 마음을 담는 연습을 해봅시다. 글의 어느 구석이라도 뻔한 글자는 남기지 않겠노라 다짐하며 써보는 겁니다. 나만이 가진 유일한 메시지에 집중하면서요. 그럼 생각이 달라지고, 고르는 단어도 달라지고, 남긴 문장도 달라져요. 결국에는 글을 쓴 사람인 나 자신도 남달라질 겁니다.

    -
    -
    -

    맞춤법은 중요합니다. 하지만 맞춤법보다 더 중요한 건 거기에 담긴 마음입니다. 내 마음을 글에 담아 실어 보내기 전, 맞춤법을 점검하는 이유 역시 그겁니다. 오직 내 마음이 남에게 읽히는 동안 방해가 되지 않기를 바라기 때문이죠. 내가 쓴 글도, 남이 쓴 글도. 언제나 그 안에 담긴 마음이 먼저입니다.

    -
    -
    -

    글을 쓴다고 글이 완성되는 게 아니에요. 글과 닮은 모습으로 살 때, 글은 비로소 완성됩니다.

    -
    +

    · 약 9분

    1단계: https://github.com/woowacourse/jwp-refactoring/pull/465
    +2단계: https://github.com/woowacourse/jwp-refactoring/pull/547
    +3단계: https://github.com/woowacourse/jwp-refactoring/pull/610
    +4단계: https://github.com/woowacourse/jwp-refactoring/pull/721

    +

    리팩터링 미션

    +

    요구사항 작성 → 테스트를 통한 코드 보호 → 리팩터링 → 의존성 리팩터링 → 멀티모듈 순서로 미션을 진행했다.
    +미션에 온전히 집중하고 싶었지만, 프로젝트와 병행하면서 진행했기에 어느정도 타협보고 진행한 부분이 많아서 아쉬웠다.

    +

    1, 2단계

    +

    1단계는 요구사항을 작성하고, 테스트 코드를 작성하여 추후에 리팩터링 할 때 안정감 있게 진행할 수 있도록 준비하는 과정이었다. +요구사항을 작성할 때 제공된 용어 사전을 최대한 활용하면서 기존의 코드를 보면서 요구사항을 정리했다. +테스트는 시간 관계상 API, 서비스 둘 중 하나만 통합 테스트를 진행해야겠다는 생각이 들었다.

    +

    최종적으로 서비스 기준으로 통합 테스트를 작성했는데 약간 후회되는 결정이었던 것 같다.
    +리팩터링 과정에서 API 명세가 바뀌지 않아야 한다는 것을 기준을 잡고 이번 미션을 한다고 가정했을 때 API 기준으로 테스트를 작성하고, 리팩터링을 진행하는 것이 더 안정감 있다고 생각한다.

    +

    2단계는 작성된 테스트 기반으로 리팩터링 하는 미션이었다.
    +서비스에서 도메인을 직접 반환하는 구조였는데, 도메인에 JPA를 적용하면 기존 명세와 달라질 것을 우려해서 DTO로 수정하는 작업을 먼저 진행했다. +DTO 이후에 서비스에 있는 로직을 도메인으로 이동시키고, 최종적으로 JPA를 적용하는 순서로 리팩터링을 진행했다. +이 과정에서 의존성 방향이 양방향인 부분도 생겨났다.

    +

    소프트웨어의 복잡성을 다루는 지혜

    +

    중간에 소프트웨어 복잡성을 다루는 지혜에 관한 제이슨의 강의가 있었다.
    +소프트웨어의 복잡성을 다루는 지혜는 에릭 에반스의 저서 도메인 주도 설계의 부제이다.

    +

    도메인 주도 설계는 유비쿼터스 언어, 전략적 설계, 전술적 설계가 중요하다고 한다.
    +유비쿼터스 언어, 전략적 설계가 전체의 90%에 해당할 정도로 중요하다고 한다. 또한 전술적 설계만 하는 경우를 DDD Lite 라고 한다.

    +

    간단히 도메인 주도 설계에서 나오는 단어를 정리한다면 다음과 같다.

    +
    단어설명
    도메인소프트웨어로 해결하고자 하는 문제 영역
    바운디드 컨텍스트해결 영역, 관심사를 분리하고 격리하여 문제 해결에 집중할 범위
    유비쿼터스 언어프로젝트에 이해관계자들의 공통된 언어로, 서로의 의사소통 비용을 줄이기 위해 사용하는 언어
    전략적 설계도메인 전문가와 개발자가 함께 유비쿼터스 언어를 이용하여 도메인과 관련된 지식을 이해하고 이를 바탕으로 경계를 나눠 바운디드 컨텍스트를 정의하고, 컨텍스트 맵을 생성하는 것을 포함하는 과정
    전술적 설계전략적 설계에서 정의한 바운디드 컨텍스트와 도메인을 이용하여 애그리거트, Entity와 VO, Repository 등을 구현하는 과정
    +

    이 외에도 다양한 내용들이 나왔지만, 지식을 제대로 흡수하지는 못했다.

    +

    3, 4단계

    +

    제이슨의 강의를 듣고, 조영호님의 우아한객체지향 유튜브 영상을 본 다음 3, 4단계를 진행했다.

    +

    3단계는 의존성 리팩터링에 관한 내용이었다. 클래스 간 방향, 패키지 간 방향을 단방향이 되도록 리팩터링을 진행해야 했었다. +함께 생성되고 삭제되는 객체들을 묶고, 결합도를 낮추기 위해 생명주기가 다르다면 id를 이용하여 참조하도록 변경했다.

    +

    의존성을 분리하기 위해 이벤트도 사용해보았다. 이벤트는 현재 기준으로 과거에 벌어진 것을 표현하기 때문에 이벤트명은 과거 시제가 되어야하는 것을 알았다. +처음에는 애플리케이션 이벤트를 사용했지만, 서비스 로직을 최대한 간단하게 하기 위해 도메인 이벤트도 사용해보았다.

    +

    4단계는 멀티모듈로 분리하는 미션이었는데 3단계에서 분리해둔 패키지 그대로 분리하지는 않았다.
    +3단계에서는 함께 생성되고 삭제되는 객체 기준으로 분리했다. 4단계에서는 내가 인식하기 편한 기준으로 분리를 했다. +아직 분리한 기준에 대한 근거가 모호했고, 이에 대한 공부를 조금 더 해야겠다고 생각했다.

    + +

    추가로 테스트 격리를 위한 직접 작성한 @ServiceTest 커스텀 애너테이션이 있었는데, 상위 모듈의 테스트에서 만든 클래스를 하위 모듈에서는 사용할 수 없었다. +따라서 TestFixtures를 사용하여 해결했다.

    +

    마무리

    +

    우아한테크코스의 마지막 미션이니 만큼, 가장 흥미로운 미션이었고 배울점도 많았던 것 같다.
    +바쁜 기간이라 많은 리뷰를 남기지 못했던 리뷰이 호이에게 미안하고, 코멘트 꼼꼼하게 달아주고 미션에 대한 이야기도 오프라인으로 많이 나눈 리뷰어 테오에게 너무 감사하다.

    +

    참고 자료

    +

    도메인 원정대, 우아콘 2021
    +우아한객체지향, 우아한테크세미나
    +TestFixtures, 권남님

    \ No newline at end of file diff --git a/page/6.html b/page/6.html index f8011a4a4..cb4706a6a 100644 --- a/page/6.html +++ b/page/6.html @@ -13,93 +13,21 @@ - - + + -

    · 약 4분

    문제 상황

    -

    현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
    -확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

    -

    비동기 예외 발생시 로깅 설정

    -

    스프링 4.1 부터 제공되는 AsyncUncaughtExceptionHandler의 경우 반환 타입이 void인 비동기 메서드를 예외 처리하기 쉽도록 도와준다.

    -

    따라서 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 핸들링하는 클래스를 생성했다.
    -기존의 동기 예외 처리의 경우 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다.
    -비동기 예외 처리도 마찬가지로 MDC의 정보를 가져와서 로그를 출력하도록 설정했다.

    -
    @Slf4j
    -public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    -
    -    private static final String LOG_FORMAT = "[%s] %s";
    -
    -    @Override
    -    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
    -        log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
    -    }
    -}
    -
    -

    AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
    -getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

    -
    @EnableAsync
    -@Configuration
    -public class AsyncConfig implements AsyncConfigurer {
    -
    -    @Override
    -    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    -        return new AsyncExceptionHandler();
    -    }
    -}
    -
    -

    이제 비동기 상황에서 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아 처리한다.

    -

    MDC 정보 연동 문제

    -

    비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없는 문제가 발생했다.

    -

    ./mdc-null.png

    -

    스프링 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

    -
    public class MdcTaskDecorator implements TaskDecorator {
    -
    -    @Override
    -    public Runnable decorate(final Runnable runnable) {
    -        Map<String, String> threadContext = MDC.getCopyOfContextMap();
    -        return () -> {
    -            MDC.setContextMap(threadContext);
    -            runnable.run();
    -        };
    -    }
    -}
    -
    -

    생성한 Decorator 클래스를 설정 파일에 등록해 준다.

    -
    @RequiredArgsConstructor
    -@EnableAsync
    -@Configuration
    -public class AsyncConfig implements AsyncConfigurer {
    -
    -    private final AsyncConfigurationProperties properties;
    -
    -    @Bean
    -    public ThreadPoolTaskExecutor taskExecutor() {
    -        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    -        executor.setCorePoolSize(properties.coreSize());
    -        executor.setMaxPoolSize(properties.maxSize());
    -        executor.setQueueCapacity(properties.queueCapacity());
    -        
    -        // highlight-next-line
    -        executor.setTaskDecorator(new MdcTaskDecorator());
    -        executor.setWaitForTasksToCompleteOnShutdown(true);
    -        executor.initialize();
    -        return executor;
    -    }
    -
    -    @Override
    -    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    -        return new AsyncExceptionHandler();
    -    }
    -}
    -
    -

    설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

    -

    ./mdc-not-null.png

    -

    참고 자료

    -

    spring async, baeldung
    -@Async will not call by @ControllerAdvice for global exception
    -Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
    -TaskDecorator, Spring docs
    -AsyncUncaughtExceptionHandler

    +

    · 약 1분

    Import 자동 적용

    +

    Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

    +

    auto-import

    +

    저장시 동작

    +

    Prefrences > Tools > Actions on Save

    +

    actions-on-save

    +

    Reformat Code: Code Reformmating

    +

    Optimize imports: 사용하지 않는 Import 제거

    +

    Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

    +

    메소드 추출, 변수 추출시 final 적용

    +

    Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

    +

    final-modifier

    \ No newline at end of file diff --git a/page/7.html b/page/7.html index b7b19caf8..88e3c4e13 100644 --- a/page/7.html +++ b/page/7.html @@ -13,209 +13,99 @@ - - + + -

    · 약 13분

    1, 2단계: https://github.com/woowacourse/jwp-dashboard-http/pull/302
    -3, 4단계: https://github.com/woowacourse/jwp-dashboard-http/pull/431

    -

    톰캣 구현

    -

    우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
    -그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

    -

    이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
    -톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

    -

    다이어그램

    -

    Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
    -사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
    -또한 적절하게 인터페이스를 사용하여 의존성 방향을 단방향으로 하려고 노력했다.

    - -

    코드 리뷰

    -

    크루 중 한 명이 나의 리뷰어가 되고, 내가 다른 크루의 리뷰어가 되는 형태로 진행이 되었다.
    -나의 리뷰어는 디노, 리뷰이는 필립이었다.

    -

    디노(매의 눈이 아닌 공룡의 눈?)가 매우 꼼꼼하게 코드 리뷰를 해주어서 조금 더 나은 코드를 작성할 수 있었고, 필립의 코드에서는 꼼꼼하게 예외처리 하는 부분을 배울 수 있었다.
    -한 가지 아쉬운 점은 필립에게 작성한 나의 코멘트들이 미션을 진행하면서 경험 기반으로 작성한 내용이 많아 근거가 조금 부족했고, 정리되지 않은 부분이 많았던 것 같다.
    -다음 미션부터 리뷰할 때 조금 더 시간을 투자해서 더 좋은 내용을 크루들과 공유할 수 있도록 노력해야겠다.

    -

    SessionConfig

    -

    미션을 진행 중 catalina 패키지의 Session 관련 부분을 보면서 중복 로직을 개선해 볼 수 있을 것 같아 컨트리뷰트를 시도했다.
    -세션 쿠키의 이름을 가져오는 Util 클래스의 코드를 수정했는데 기본 값은 JSESSIONID 지만 설정에 따라서 세션 쿠키명을 다르게 사용할 수 있기 때문에 해당 로직이 있는 것으로 생각했다.
    -기존의 코드는 명시된 주석의 내용과 코드의 흐름이 일치하지 않아서 약간 이해하기 어려웠다.

    -

    초기에 요청했던 PR은 기존의 코드보다 전체적으로 비교 연산을 한 번 줄일 수 있었고, context가 null인 경우 바로 기본 값을 반환함으로써 성능 개선의 효과가 있을 거라고 생각했다.
    -메인테이너인 Mark Thomas 형이 해당 로직의 경우 컴파일러가 해당 부분을 최적화 할 수 있을 거라고 기대한다고 했고, 가독성을 개선시켜보라고 조언해주셨다.
    -컴파일러 최적화는 고려해보지 못한 부분인데, 앞으로 학습해야 할 부분이 산더미라고 생각했다.

    -

    남겨준 코멘트에 따라 최종적으로는 중복된 코드를 줄이는 방향으로 코드를 수정했다.
    -결과적으로 기존 로직 대비 비교 연산을 한 번 줄일 수 있었고, 명시된 주석의 내용과 유사한 흐름의 코드를 작성하여 좋은 방향으로 리팩터링을 했다고 생각한다.

    - - -
    public static String getSessionCookieName(Context context) {
    -
    -    String result = getConfiguredSessionCookieName(context);
    -
    -    if (result == null) {
    -        result = DEFAULT_SESSION_COOKIE_NAME;
    -    }
    -
    -    return result;
    -}
    -
    -public static String getSessionUriParamName(Context context) {
    -
    -    String result = getConfiguredSessionCookieName(context);
    -
    -    if (result == null) {
    -        result = DEFAULT_SESSION_PARAMETER_NAME;
    -    }
    -
    -    return result;
    +

    · 약 4분

    테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
    +이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

    +

    Argument Sources

    +

    @ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
    +JUnit이 제공하는 다양한 Source가 있기 때문에, 테스트에 맞춰 다양하게 사용할 수 있다.

    +

    Value Source

    +

    값을 이용하여 제공하는 형태로, 다음과 같은 타입의 값을 매개변수로 제공할 수 있다.

    +
      +
    • short, int, long, float, double
    • +
    • byte, char, boolean, String, Class
    • +
    +
    @ParameterizedTest
    +@ValueSource(ints = {1, 100, Integer.MAX_VALUE})
    +void valueTest(final int value) {
    +    Assertions.assertThat(value).isPositive();
     }
    -
    -private static String getConfiguredSessionCookieName(Context context) {
    -
    -    // Priority is:
    -    // 1. Cookie name defined in context
    -    // 2. Cookie name configured for app
    -    // 3. Default defined by spec
    -    if (context != null) {
    -        String cookieName = context.getSessionCookieName();
    -        if (cookieName != null && cookieName.length() > 0) {
    -            return cookieName;
    -        }
    -
    -        SessionCookieConfig scc =
    -            context.getServletContext().getSessionCookieConfig();
    -        cookieName = scc.getName();
    -        if (cookieName != null && cookieName.length() > 0) {
    -            return cookieName;
    -        }
    -    }
    -
    -    return null;
    +
    +

    Null & Empty Source

    +

    null 값, 빈 값을 제공한다.
    +Empty Source의 경우 다음과 같은 타입에 한해 매개변수로 제공할 수 있다.

    +
      +
    • String
    • +
    • java.util.List, java.util.Set, java.util.Map
    • +
    • primitive arrays — ex) int[]
    • +
    • object arrays — ex) String[]
    • +
    +
    @ParameterizedTest
    +@NullAndEmptySource
    +void nullAndEmptyTest(final String value) {
    +    Assertions.assertThat(value).isNullOrEmpty();
     }
    -
    -

    HTTP 수업

    -

    미션 중간에 진행되었던 HTTP 수업에는 HTTP를 적절하게 활용하는 부분에 대해 학습했다.
    -항상 성능 개선을 위해 애플리케이션 단에서 최적화해보려고 노력을 했지만, 더 적은 시간을 투자해서 효율적으로 성능을 개선할 수 있는 방법에 대해 알 수 있었던 수업이었다.
    -HTTP 압축, HTTP 캐싱, 리소스 최적화 기법에 대해 학습했다.

    -

    스프링 부트에서는 다음 옵션을 설정하여 http의 송수신의 압축을 진행할 수 있다.

    -
    server:
    -  compression:
    -    enabled: true
     
    -

    수업 중 해당 압축 성능이 좋다면 왜 스프링 부트에서는 기본 값으로 설정을 하지 않았는지 궁금해졌다.
    -궁금증을 해소하지 못했는데 말랑이 잡담 채널에 다음과 같은 issue를 찾아주었다.
    -내용을 요약해 보자면 WAS 별로 압축을 하기 위해 설정해야 하는 것이 다르고, 무조건 압축을 하는 것이 최적의 경우가 아닐 수 있기 때문에 기본값으로 설정하지 않는 것 같다.

    -
    -

    If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.

    -
    -

    Phil Webb 형님의 말에 따르면 일반적인 애플리케이션을 개발하는 경우 gzip 압축을 사용하는 것이 좋지만, MSA 환경 + 데이터 센터에서 사용하는 경우 오직 다른 MSA 애플리케이션과 통신하고, 고성능 네트워크가 있기 때문에 CPU 부하를 줄이는 것이 우선시 될 수도 있다는 것이었다.

    -

    이외에도 의도하지 않은 캐싱을 막기 위해 휴리스틱 캐싱을 제거하거나, 개인 정보 유출을 막기 위해 응답 헤더에 private을 설정, ETag도 학습했다.

    -

    ETag HTTP 응답 헤더는 특정 버전의 리소스를 식별하는 식별자다.
    -웹 서버가 내용을 확인하고 변하지 않았으면, 웹 서버로 full 요청을 보내지 않기 때문에, 캐시가 더 효율적이게 된다.
    -MDN

    -

    Thread 수업

    -

    스레드에 대한 수업을 들었지만, 복잡한 내용도 워낙 많았기 때문에 설명하라고 하면 잘 못할 것 같은 느낌이 든다.
    -현재 프로젝트, 미션, 테코톡 준비를 병행해야 해서 세부적인 내용은 시간 날 때 복습하려고 한다.

    -

    스레드를 이해하고, WAS에 스레드 설정 관련한 실습이 있었는데 테오와 같이 1시간 정도 페어로 Thread 실습을 진행해 보았다.
    -학습한 내용은 다음과 같다.

    -

    threads.max: Tomcat의 최대 스레드 개수
    -max-connections: Tomcat이 유지할 수 있는 최대 커넥션 개수
    -accept-count: 최대 연결 수에 도달했을 때 연결 요청에 대해 운영 체제에서 제공하는 대기열의 최대 길이. 해당 Queue에 요청이 쌓이는 것은 Tomcat이 더 이상 요청을 받을 수 없다는 뜻이다. accpet-count queue에도 요청이 가득차면 그 이후에 오는 요청은 거부된다.

    - -

    마치며

    -

    시간은 너무 빠르게 가고 할 일은 많은 것 같다.
    -우선순위를 잘 정하고 학습을 진행해야겠다.
    -현재 데이터 다루는 부분(DB)에 대한 학습이 많이 부족한 것 같다. 해당 부분은 테코톡이 끝나는대로 채워야겠다.

    -

    참고 자료

    -

    RFC 2616
    -ETag, mdn
    -Apache Tomcat 8 Configuration Reference
    -Apache Tomcat Tuning, Terry Cho
    -maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

    +

    ETC.

    +

    위에서 언급한 방법 이외에도 다양한 방법으로 매개변수를 제공할 수 있다.

    +
      +
    • CSV 파일을 이용한 CsvFileSource
    • +
    • ArgumentsProvider 구현한 클래스를 이용하는 ArgumentsSource
    • +
    +

    참고 자료

    +
    \ No newline at end of file diff --git a/page/8.html b/page/8.html index b5e1ff22d..8d0aca282 100644 --- a/page/8.html +++ b/page/8.html @@ -13,49 +13,89 @@ - - + + -

    · 약 6분

    성능 테스트

    -

    API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

    -

    시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
    -다양한 상황에 대비해서 성능 테스트를 해야한다.

    -

    ./test.png

    -

    스모크 테스트(Smoke Test)

    -

    최소한의 부하를 주어 시스템이 정상적으로 동작하는지 확인하는 테스트

    -

    VU를 최소한으로 두고, 짧은 시간을 가지고 테스트한다.
    -다른 테스트를 시작하기 전에 스모크 테스트를 함으로써 테스트 스크립트에 오류가 없는지 확인할 수 있고, 성능 지표가 정상적으로 수집, 모니터링 되고 있는지 확인할 수 있다.

    -

    가상 사용자는 서버 애플리케이션에 대해 특정 테스트를 실행한다.
    -이는 다른 가상 사용자와 독립적으로 실행되며, 여러 가상 사용자를 사용하여 동시 연결을 할 수 있다.
    -스레드라고 생각하면 된다.

    -

    스파이크 테스트(Spike Test)

    -

    사용량이 급증하는 상황에서 시스템이 견디고 성능에 문제가 없는지 확인하는 테스트

    -

    티켓 발급, 할인 쿠폰 발급과 같은 이벤트를 하는 경우 대규모 트래픽이 들어온다.
    -스파이크 테스트를 통해 급증하는 부하 상황에서 시스템이 어떻게 동작하고, 부하를 잘 버티는지 확인할 수 있다.

    -

    부하 테스트(Load Test)

    -

    목푯값에 해당되는 부하를 견딜 수 있을지 확인하는 테스트

    -

    일반적인 부하 상황에서 시스템이 어떻게 동작하는지 확인하는 테스트다.
    -램프업 또는 묙푯값에 해당하는 부하 기간동안 성능이 문제가 있는지 확인하고, 시스템 변경 후에도 부하 테스트를 돌려 동일하게 목푯값을 처리하는지 확인할 수 있다.

    -

    부하 테스트를 위해 설정한 가상 사용자 수에 도달하는 데 걸리는 시간

    -

    스트레스 테스트(Stress Test)

    -

    시스템의 최대치에 해당되는 부하를 받았을 때 시스템이 어떻게 동작하는지 확인하는 테스트

    -

    그래프를 봤을 때 부하 테스트와 유사한 형태로 보이지만, 부하량이 다르다.
    -일반적으로 평균적인 목푯값 대비 작게는 50% 이상, 필요의 경우 그 이상으로 부하를 준다.
    -스트레스 테스트는 부하 테스트를 실행한 후에만 실행해야 한다. 부하 테스트가 이루어지지 않은 상황에서 스트레스 테스트를 실행하는 경우에는 병목 지점이나 문제 상황을 찾기 어려워진다.
    -또한 부하 테스트에서 사용한 스크립트를 VU값(스레드 수)만 수정하여 재사용하는 것이 좋다.

    -

    내구 테스트(Endurance Test)

    -

    평균 사용률로 일정 부하를 지속적으로 주며 시스템이 문제되는 지점을 확인하는 테스트

    -

    흡수 테스트(Soak Test)라고도 하며, 기본적인 부하 테스트의 변형이라고 볼 수 있다.
    -다른 테스트와 달리 긴 시간동안 테스트를 하는 것이 특징이며, 메모리 누수 문제와 같이 장시간 애플리케이션을 실행할 때 시스템의 문제가 발생하는 부분을 확인하는 것이 목적이다.

    -

    중단점 테스트(Breakpoint Test)

    -

    임계 지점을 찾기 위해 부하를 점진적으로 증가시키며 진행하는 테스트

    -

    문제되는 부분을 더 빨리 찾기 위해 다른 테스트를 통과한 다음에 중단점 테스트를 진행하고, 이 때 점진적으로 부하를 늘려나가는 것이 좋다.
    -스트레스 테스트를 성능 튜닝과 반복해서 진행한다면, 시스템을 더욱 발전시킬 수 있다.
    -다만 Auto Scaling이 적용된 클라우드 환경에서는 진행하지 않아야 한다.

    -

    참고 자료

    -

    Load test types, k6
    -자바 최적화 - 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드
    -아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

    +

    · 약 8분

    1단계: https://github.com/woowacourse/java-racingcar/pull/510
    +2단계: https://github.com/woowacourse/java-racingcar/pull/538

    +

    자동차 경주

    +

    자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
    +우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

    +

    첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
    +시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

    +

    시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
    +mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

    +
      +
    • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
    • +
    • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.
    • +
    + +

    미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

    +

    페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
    +리팩터링을 어떻게 했는지? 이런 리뷰에 대해 어떻게 생각하는지 깊게 고민하는 시간을 가질 수 있었다.

    +

    부족했던 부분

    +

    리팩터링이 끝난 후 메서드명, 테스트시 출력하는 메시지에 대한 코멘트가 많이 달렸다.
    +객체가 어떤 책임과 역할을 가지는지 생각하는 시간을 가지고 명확한 메서드명을 작성해야겠다고 생각했다.

    +

    평소에 프로그래밍 이야기가 아닌 다른 주제로 이야기하면 잘 들으려고 하는 편이지만
    +내가 좋아하는 주제, 관심가는 주제인 프로그래밍에 대한 이야기를 할 땐 말이 많아진다.
    +다음 미션부터는 더 많은 시간을 페어의 의견과 이야기를 듣는 곳에 사용해야겠다.

    +

    새로 학습한 부분

    +

    Assertions extracting

    +

    결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
    +이전에는 필요에 따라 stream을 이용하여 검증할 값을 생성했지만, 해당 방법을 이용해서 절차를 줄일 수 있었다.

    +
    @Test
    +void extracting() {
    +    final Cars cars = new Cars(List.of("car1", "car2"));
    +
    +    assertThat(cars.getCars())
    +            .extracting(Car::getName)
    +            .containsExactly("car1", "car2");
    +}
    +
    +
    +

    아래는 리뷰어님과 대화를 나누면서 얻은 답변 + 나의 의견이다.

    +

    제어할 수 없는 부분에 대한 테스트

    +

    테스트 대상이 검증된 것이라면 작성하지 않거나, 제어할 수 있는 부분에 대한 테스트를 더욱 꼼꼼하게 작성한다.
    +이건 개인적인 생각이지만 내가 안정감이 들 수 있을 정도로 출력 범위 내의 결과를 반환하는지 정도 테스트할 수 있지 않을까?

    +

    단순 위임을 하는 메서드에 대한 테스트

    +

    위임이라는 것은 역할과 책임을 넘겨준다는 것이다.
    +호출 횟수를 검증하는 것보다 결과에 대한 테스트하는 것이 좋다.
    +단순히 위임만 하는 테스트의 경우 결과를 검증한다면 테스트가 중복되지 않을까 생각했었다.
    +따라서 중복된 테스트를 줄이기 위해 내부의 메서드를 호출하는지 검증하는 방법도 있다는 것을 알게 되었지만
    +안정적으로 결과를 테스트 하는 것이 더 좋은 방법인 것 같다.

    +

    테스트를 위한 getter 사용

    +

    테스트 용도로 도메인에 새로운 메서드가 생성되는 것은 좋지 못하다.
    +필요의 경우 생성해서 사용할 수 있지만, 기존에 있는 메서드들을 활용해보는 것이 더 좋은 방법이다.
    +이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

    +

    페어에게 배울 부분

    +

    질문이나 생각할 점이 있을 때 매우 깊게 고민하는 것 같았다.
    +생각을 정리한 후 자신의 의견을 명료하게 전달해주었다.
    +그렇기 때문에 지식을 효율적으로 습득한다.
    +난 생각을 잘 정리하지 않은 채로 내버려 둔 얕은 지식이 많은 것 같다. (이런 것도 아는 것이라고 할 수 있을까?)
    +앞으로 조금 더 머릿속에서 정리하고, 문제에 대해 깊게 고민하는 시간을 늘려야겠다.

    +

    개발에 열정을 가진 게 느껴진다.
    +나도 개발을 좋아하지만, 최근에는 의지가 약해졌었다.
    +열정이 가득한 사람을 만나니 나도 열정적인 사람이 되는 것 같다.

    +

    칭찬을 많이 해준다. 단순히 많이 해주는 것이 아니라, 진심을 담긴 칭찬을 해줬다.
    +칭찬은 고래도 춤추게 하던가?
    +그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

    +

    어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
    +이건 바로 배울 수 없지만.
    +나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

    \ No newline at end of file diff --git a/page/9.html b/page/9.html index bb9d1151a..d01aca8bf 100644 --- a/page/9.html +++ b/page/9.html @@ -13,439 +13,149 @@ - - + + -

    · 약 21분

    복제(Replication)

    -

    한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
    -원본 데이터를 가지는 서버를 Primary 또는 Source 라고 부르고, 복제된 데이터를 가지는 서버를 Secondary 또는 Replica 라고 부른다.

    -

    복제를 하는 이유

    -

    1. 스케일 아웃

    -

    사용자의 트래픽이 증가하는 경우, 데이터베이스에 가해지는 부하도 자연스럽게 증가한다.
    -이를 처리하기 위해 복제를 통한 스케일 아웃을 적용하여 애플리케이션에서 사용하는 쿼리들을 각각의 데이터베이스로 분산 시킬 수 있다.

    -

    2. 데이터 백업

    -

    실제 운영되는 서비스가 사용하고 있는 DB에서 백업을 진행하는 경우, 서비스에 영향을 미칠 수 있다.
    -따라서 실제 서비스에 영향이 가지 않도록 복제를 통해 Replica 서버를 구축하여, Replica 서버에서 복제를 진행하는 방법으로 영향을 최소화 할 수 있다.

    -

    3. 데이터 분석

    -

    백업과 마찬가지로 복잡하고 무거운 분석용 쿼리의 서비스에 영향을 미칠 수 있다.
    -마찬가지로 복제를 사용해 분석용 쿼리를 사용할 수 있는 환경을 만들 수 있다.

    -

    4. 데이터의 지리적 분산

    -

    빠른 응답을 위해 애플리케이션 서버에 가깝게 서버를 구성하거나, 고가용성(High Availability)을 위해서도 사용된다.

    -

    바이너리 로그 파일 위치 기반 복제

    -

    MySQL 서버에서 발생하는 변경사항에 대한 로그 파일을 바이너리 로그라고 한다.
    -바이너리 로그를 통해 데이터 변경, 테이블 구조 변경, 계정이나 권한 변경에 대한 정보가 저장된다.
    -MySQL의 복제는 바이너리 로그 기반으로 구현되어 있다. 이를 Replica 서버로 전달하고 바이너리 로그 기반으로 데이터를 변경 사항을 반영한다.

    - -

    Binary Log Dump Thread: 바이너리 로그의 내용을 Replica 서버로 전달
    -Replication I/O Thread: Binary 로그 이벤트를 가져와 로컬 서버의 파일(Relay Log)로 저장
    -Replication SQL Thread: 릴레이 로그 파일의 이벤트를 읽고 실행

    -

    바이너리 로그 방식의 문제점

    -

    바이너리 로그 방식은 서버에 장애가 발생했을 때 복제 토폴로지 변경이 까다롭다.
    -토폴로지란 네트워크의 요소들을 물리적으로 연결해 놓은 것, 또는 그 연결 방식을 말한다.

    - -

    위와 같이 Source 서버, Replica 2대가 존재하고, C 서버에 복제 지연이 되었을 때 문제가 발생한다.

    +

    · 약 11분

    1단계: https://github.com/woowacourse/java-ladder/pull/97
    +2단계: https://github.com/woowacourse/java-ladder/pull/234

    +

    사다리 타기

    +

    사다리 타기 미션에서는 우가와 페어가 매칭되었다.
    +이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

    +

    우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

    +

    2단계에서는 2가지 방법으로 구현해봤다.

    +
      +
    1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
    2. +
    3. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법
    4. +
    +

    Position 기준으로 사다리 게임을 진행하는 방법

    +

    사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
    +구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
    +또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

    -

    A 서버에서 장애가 발생한다면 B 서버를 Source 서버로 승격하고, C에게 조회 쿼리를 분산시킨다.
    -하지만 여기서 C 서버에는 A 서버와 동기화가 안되었으니 조회 시 문제가 발생한다.
    -뒤늦게 B 서버와 동기화를 하려고 해도, 어떤 바이너리 로그, 어떤 위치와 동기화해야하는지 알기 어렵다.

    -

    글로벌 트랜잭션 아이디(GTID) 기반 복제

    -

    GTID 방식을 사용하여 참여한 모든 데이터베이스가 발생한 이벤트에 고유한 식별값을 부여한다면, 동기화에 대한 문제를 간단하게 해결할 수 있다.
    -위의 예시와 같이 복제 지연과 함께 장애가 발생한다해도 특정 GTID 부터 복제를 재개하면 된다.

    -

    복제 토폴로지에 참여한 모든 서버에서 고유하도록 각 이벤트에 부여된 식별값
    -[source_id]:[transaction_id]로 구성되며, source_id는 서버를 식별하기 위한 값이고 transaction_id는 커밋된 트랜잭션을 식별하기 위한 값으로 1씩 증가하는 형태로 발급된다.

    -

    복제 토폴로지

    -

    싱글 레플리카 복제 구성

    -

    가장 간단한 구성으로 제일 많이 사용하는 형태다.
    -replica 서버를 읽기 전용, 예비 서버, 백업 용도로 많이 사용한다.

    - -

    멀티 레플리카 복제 구성

    -

    2개의 replica 서버를 사용하는 형태다.
    -하나의 replica는 예비 용도로 남겨두는 형태다.
    -추후에 트래픽이 증가하는 경우 예비 용도의 replica를 사용함으로 읽기 요청의 부하 분산을 할 수 있다.

    - -

    체인 복제 구성

    -

    replica 서버가 많은 경우 바이너리 로그를 전달하는 작업 자체가 부하가 될 수 있다.
    -따라서 1:M:M 구조로 체인 복제 구성을 고려할 수 있다.

    - -

    듀얼 소스 복제 구성

    -

    2개의 MySQL 서버 모두 읽기와 쓰기가 가능하도록 하는 구성이다.
    -각 서버에서 변경된 데이터는 다른 서버에 반영된다.
    -목적에 따라 ACTIVE-ACTIVE 형태 또는 ACTIVE-PASSIVE 형태로 사용할 수 있다.
    -ACTIVE-PASSIVE 형태인 경우 싱글 레플리카 복제 구성과 동일해보이지만, ACTIVE 서버에서 문제가 발생하면 설정의 변경없이 PASSIVE 서버로 쓰기 작업을 전환할 수 있다는 것이 장점이다.

    - -

    ACTIVE-ACTIVE: 2개의 서버 모두 쓰기 작업을 수행하는 형태
    -ACTIVE-PASSIVE: 하나의 서버에서만 쓰기 작업을 수행하는 형태

    -

    멀티 소스 복제 구성

    -

    여러개의 source 서버와 하나의 replica 서버를 사용하는 구성이다.
    -이는 source 서버의 데이터를 한 곳에 백업하는 용도로 사용, 여러 서버에 존재하는 데이터를 통합, 샤딩되어있는 테이블 데이터를 통합할 때 사용한다.

    - -

    바이너리 로그 방식 Replication 구성하기

    -

    mysql 2대를 이용하여 replication을 구성하고, spring boot application으로 source, replica 데이터베이스에 접근해보는 예제이다.
    -https://github.com/bbiac/db-replication

    -

    MySQL 환경 구성

    -

    MySQL 버전은 8.1을 사용했다.
    -13306, 13307 포트를 사용해서 MySQL 서버 2대를 띄웠다.
    -또한 사실 IP 대역으로 통신할 수 있도록 커스텀 네트워크를 추가했다.

    -
    version: '3.8'
    -
    -services:
    -  source:
    -    platform: linux/x86_64
    -    image: mysql:latest
    -    restart: always
    -    container_name: mysql-source
    -    environment:
    -      TZ: 'Asia/Seoul'
    -      MYSQL_DATABASE: 'db'
    -      MYSQL_USER: 'user'
    -      MYSQL_PASSWORD: 'password'
    -      MYSQL_ROOT_PASSWORD: 'password'
    -    ports:
    -      - "13306:3306"
    -    volumes:
    -      - db-source:/var/lib/mysql
    -      - db-source:/var/lib/mysql-files
    -      - ./docker/source.cnf:/etc/mysql/my.cnf
    -    networks:
    -      - mysql_network
    -
    -  replica:
    -    platform: linux/x86_64
    -    image: mysql:latest
    -    restart: always
    -    container_name: mysql-replica
    -    environment:
    -      TZ: 'Asia/Seoul'
    -      MYSQL_DATABASE: 'db'
    -      MYSQL_USER: 'user'
    -      MYSQL_PASSWORD: 'password'
    -      MYSQL_ROOT_PASSWORD: 'password'
    -    ports:
    -      - "13307:3306"
    -    volumes:
    -      - db-replica:/var/lib/mysql
    -      - db-replica:/var/lib/mysql-files
    -      - ./docker/replica.cnf:/etc/mysql/my.cnf
    -    networks:
    -      - mysql_network
    -
    -volumes:
    -  db-source:
    -  db-replica:
    -
    -networks:
    -  mysql_network:
    -    driver: bridge
    -
    -

    또한 source, replica 각각 다음과 같이 db 설정을 했다.

    -
    설정설명
    server_id각각의 mysql 마다 고유한 값을 가져야 한다.
    log_bin바이너리 로그 파일 경로 설정으로 절대경로를 사용하지 않는다면 /var/lib/mysql 아래 해당 log_bin에 설정된 값으로 로그가 생성된다.
    sync_binlogN개의 트랜잭션 당 바이너리 로그를 디스크와 동기화 작업을 하도록 한다. 1은 기본값으로 안정적이지만, 가장 느리다.
    relay_log릴레이 로그 파일 경로 설정
    relay_log_purge필요 없는 릴레이 로그 파일을 자동으로 삭제하는 옵션
    read_only읽기 전용 설정
    log_replica_updatesReplication SQL Thread로 인해 실행되는 정보를 바이너리 로그에 기록 추후에 소스 서버로 승격되는 경우를 고려하면 설정하는 것이 좋다.
    - - -
    [mysqld]
    -server_id=1
    -log_bin=mysql-bin
    -sync_binlog=1
    -
    -

    도커 실행

    -

    docker-compose up 명령어로 docker-compose 설정으로 docker를 띄운다.
    --d 옵션을 붙이면 백그라운드 모드로 실행된다.

    -
    docker-compose up -d
    -
    -

    replication slave 권한 설정

    -

    REPLICATION SLAVE 권한이 설정되어 있어야 replica 서버에서 source 서버에 접근하여 로그를 읽어올 수 있다.
    -source 서버에 접근하여 user 계정에 해당 권한을 설정해준다.

    -

    SOURCE 접속

    -
    docker exec -it mysql-source mysql -u root -p
    -
    -

    user 계정에 REPLICATION SLAVE 권한 추가

    -
    GRANT REPLICATION SLAVE ON *.* TO 'user'@'%';
    -FLUSH PRIVILEGES;
    -
    -

    SOURCE DB 정보 확인

    -

    replica 설정에 필요한 source db의 바이너리 로그 파일명과 Position을 확인한다.
    -Position 값은 실제 파일의 바이트 수를 의미한다.
    -확인한 File(SOURCE_LOG_FILE)과 Position(SOURCE_LOG_POS) 값은 replica 설정에서 사용한다.

    -
    SHOW MASTER STATUS;
    -
    -+------------------+----------+--------------+------------------+-------------------+
    -| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    -+------------------+----------+--------------+------------------+-------------------+
    -| mysql-bin.000003 |     1082 |              |                  |                   |
    -+------------------+----------+--------------+------------------+-------------------+
    -
    -

    SOURCE ip 주소 확인

    -

    docker inspect -f 옵션을 사용하면 해당 컨테이너의 세부 정보를 확인할 수 있다.
    -다음 명령어를 이용해 docker-compose 파일에 설정해둔 mysql_network에서 사용되는 사설 아이피 주소를 확인한다.

    -
    docker inspect -f "{{with index .NetworkSettings.Networks \"db-replication_mysql_network\"}}{{.IPAddress}}{{end}}" mysql-source
    -
    -

    ip 주소가 나오지 않는 경우 docker inspect mysql-source로 확인한다.
    -확인한 IP주소(SOURCE_HOST) 값은 replica 설정에서 사용한다.

    -

    replica mysql 접속

    -

    source db에 접속했던 방법과 동일하게 replica db에 접속한다.

    -
    docker exec -it mysql-replica mysql -u root -p
    -
    -

    replica 설정

    -

    이전에 source db에서 얻었던 정보들을 사용하여 replica 설정을 진행한다.
    -실제 DB 서버에서 복제하는 경우 추가적으로 source DB의 파일을 복제해야하지만 현재 복제할 데이터가 없기 때문에 해당 부분은 생략했다.
    -SOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS 를 적절히 변경한다.

    -
    STOP REPLICA;
     
    -CHANGE REPLICATION SOURCE TO 
    -SOURCE_HOST='172.29.0.2', 
    -SOURCE_USER='user', 
    -SOURCE_PASSWORD='password', 
    -SOURCE_LOG_FILE='mysql-bin.000001', 
    -SOURCE_LOG_POS=0, 
    -GET_SOURCE_PUBLIC_KEY=1;
    +    LadderGameController --> LadderGame
    +    LadderGame --> Ladder
    +    LadderGame --> Players
    +    LadderGame --> Items
     
    -START REPLICA;
    -
    -

    설정 확인

    -
    SHOW REPLICA STATUS;
    +    Ladder --> Line
    +    Line --> LineStatus
     
    -+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
    -| Replica_IO_State                 | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File  | Read_Source_Log_Pos | Relay_Log_File         | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID                          | Source_Info_File        | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State                                | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |
    -+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
    -| Waiting for source to send event | 172.25.0.3  | user        |        3306 |            60 | mysql-bin.000003 |                1082 | mysql-relay-bin.000002 |           868 | mysql-bin.000003      | Yes                | Yes                 |                 |                     |                    |                        |                         |                             |          0 |            |            0 |                1082 |            1078 | None            |                |             0 | No                 |                    |                    |                 |                   |                |                     0 | No                            |             0 |               |              0 |                |                             |                1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info |         0 |                NULL | Replica has read all relay log; waiting for more updates |              86400 |             |                         |                          |                |                    |                    |                   |             0 |                      |              |                    |                        |                     1 |                   |
    -+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
    -
    -

    Replica_IO_Running, Replica_SQL_Running 값이 YES라면 정상적으로 replication 구성이 완료된 것이다.

    -

    설정을 마친 후 source db에 다음과 같이 create table 명령어를 입력한다.
    -replica db에 동일한 member table이 생성된 것을 확인할 수 있다.

    -
    CREATE TABLE member
    -(
    -    id   BIGINT PRIMARY KEY AUTO_INCREMENT,
    -    name VARCHAR(255)
    -);
    -
    -

    스프링 부트로 DB 접근하기

    -

    일반적인 트랜잭션의 경우 source, 읽기 전용 트랜잭션인 경우 replica로 요청이 가도록 구성해보자.

    -

    Environment 설정

    -

    다음과 같이 source, replica로 구분하여 설정한다.

    -
    spring:
    -  datasource:
    -    source:
    -      username: user
    -      password: password
    -      driver-class-name: com.mysql.cj.jdbc.Driver
    -      jdbc-url: jdbc:mysql://localhost:13306/db
    -    replica:
    -      username: user
    -      password: password
    -      driver-class-name: com.mysql.cj.jdbc.Driver
    -      jdbc-url: jdbc:mysql://localhost:13307/db
    -
    -

    DataSourceType 설정

    -

    단순 문자열로도 구분할 수 있지만, enum을 이용해서 트랜잭션을 구분하도록 생성한다.
    -Key는 추후에 빈 설정에 사용한다.

    -
    public enum DataSourceType {
    -    SOURCE(SOURCE_NAME),
    -    REPLICA(REPLICA_NAME),
    -    ;
    +    LadderGame --> Position
    +    Ladder --> Position
    +    Items --> Position
    +    Line --> Position
    +    Players --> Position
     
    -    private final String key;
    +    LadderGame --> LadderGameResult
     
    -    DataSourceType(String key) {
    -        this.key = key;
    -    }
    +    Items --> Item
    +    Players --> Player
     
    -    public static class Key {
    -        public static final String ROUTING_NAME = "ROUTING";
    -        public static final String SOURCE_NAME = "SOURCE";
    -        public static final String REPLICA_NAME = "REPLICA";
    +    LadderGameController --> InputView
    +    LadderGameController --> OutputView
    +">
    +
    public LadderGameResult play() {
    +    final Map<Player, Item> result = new LinkedHashMap<>();
    +    // 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
    +    for (Position position : Position.range(players.count())) {
    +        final Position resultPosition = ladder.play(position);
    +        result.put(players.get(position), items.get(resultPosition));
         }
    +    return new LadderGameResult(result);
     }
     
    -

    AbstractRoutingDataSource 설정

    -

    스프링이 지원해주는 AbstractRoutingDataSource를 상속받아 트랜잭션의 읽기 여부에 따라 다른 DataSource를 향하도록 설정한다.

    -

    정적 팩터리 메서드는 Map<DataSourceKey, DataSource>에 해당하는 값을 받아 데이터 소스를 설정한다.

    -
      -
    • setDefaultTargetDataSource: 기본 데이터 소스를 설정한다.
    • -
    • setTargetDataSources: 맵 형태로 받은 데이터 소스 값들을 설정한다.
    • -
    -

    determineCurrentLookupKey를 오버라이딩하여 트랜잭션의 읽기 여부에 따라 다른 DataSourceType을 반환하도록 설정한다.

    -
      -
    • isCurrentTransactionReadOnly() 메서드를 통해 트랜잭션이 읽기 전용인지 확인할 수 있다.
    • -
    • DataSourceType을 반환하도록 설정하고, 반환한 값에 해당하는 데이터 소스가 사용된다.
    • -
    -
    public class RoutingDataSource extends AbstractRoutingDataSource {
    +

    Player에게 Ladder를 전달하여 게임을 진행하는 방법

    +

    Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
    +이 방법이 사다리 게임을 위해서 객체들이 긴밀하게 협력하고, 조금 더 책임의 분배가 잘 되어있다고 생각이 되었다.

    +DataSource 설정 -

    위에서부터 순서대로 Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy 설정이다.
    -스프링은 트랜잭션 시작시에 커넥션의 사용여부와 상관없이 커넥션을 확보한다.
    -따라서 readOnly 트랜잭션이 설정된 메서드를 사용하더라도 미리 확보된 커넥션을 사용하기 때문에 replica db로 요청을 하지 않고 source db로 요청을 한다.

    -

    TransactionSynchronizationManager.isCurrentTransactionReadOnly() 메서드 호출 시 currentTransactionReadOnly라는 ThreadLocal<Boolean>에 설정된 값을 반환하는데 readOnly 설정이 되면 이 값을 true로 설정한다. 하지만 determineCurrentLookupKey를 호출하여 key 값을 가져오는 부분보다 이후에 설정되기 때문에 determineCurrentLookupKey 메서드에서 항상 DataSourceType.SOURCE가 반환되어 source db로 요청을 한다.

    -

    LazyConnectionDataSourceProxy를 설정하는 경우 실제 DataSource를 사용하는 시점에 커넥션을 획득해서 사용하기 때문에 설정한대로 replica db로 조회 요청을 한다.

    -
    @Configuration
    -public class DataSourceConfiguration {
    +    Item --> Position
    +    Player --> Position
     
    -    @Bean
    -    @Qualifier(SOURCE_NAME)
    -    @ConfigurationProperties(prefix = "spring.datasource.source")
    -    public DataSource sourceDataSource() {
    -        return DataSourceBuilder.create().build();
    -    }
     
    -    @Bean
    -    @Qualifier(REPLICA_NAME)
    -    @ConfigurationProperties(prefix = "spring.datasource.replica")
    -    public DataSource replicaDataSource() {
    -        return DataSourceBuilder.create().build();
    -    }
    +    LadderGame --> LadderGameResult
     
    -    @Bean
    -    @Qualifier(ROUTING_NAME)
    -    public DataSource routingDataSource(
    -            @Qualifier(SOURCE_NAME) DataSource sourceDataSource,
    -            @Qualifier(REPLICA_NAME) DataSource replicaDataSource
    -    ) {
    -        return RoutingDataSource.from(Map.of(
    -                DataSourceType.SOURCE, sourceDataSource,
    -                DataSourceType.REPLICA, replicaDataSource
    -        ));
    -    }
    +    Items --> Item --> ItemName
    +    Players --> Player --> PlayerName
     
    -    @Bean
    -    @Primary
    -    public DataSource dataSource(
    -            @Qualifier(ROUTING_NAME) DataSource routingDataSource
    -    ) {
    -        return new LazyConnectionDataSourceProxy(routingDataSource);
    -    }
    -}
    -
    -

    최종적으로 DataSource 빈은 다음과 같은 형태가 된다.

    - -

    동작 확인

    -

    간단하게 테스트를 작성해서 설정한대로 동작이 되는지 확인해보았다.
    -save 메서드의 경우 @Transactional, findById 메서드의 경우 @Transactional(readOnly = true)가 설정되어있다.
    -로그를 통해 save의 경우 source db로 findById의 경우 replica db로 요청을 하는 것을 알 수 있다.

    -
    @SpringBootTest
    -class MemberServiceTest {
    -
    -    @Autowired
    -    private MemberService memberService;
    +    LadderGameController --> InputView
    +    LadderGameController --> OutputView
     
    -    @Test
    -    void 사용자를_저장한다() {
    -        // RoutingDataSource log: readOnly = false
    -        memberService.save("bbiac");
    -    }
    +    OutputView --> LadderMessageGenerator">
    +
    public LadderGameResult play() {
    +    // 참가자들에게 사다리를 전달해서 사다리에게 메시지를 보내도록 한다.
    +    final Map<Player, Position> playResult = players.play(ladder);
     
    -    @Test
    -    void 사용자를_조회한다() {
    -        // RoutingDataSource log: readOnly = true
    -        assertThatThrownBy(() -> memberService.findById(MAX_VALUE))
    -                .isInstanceOf(NoSuchElementException.class);
    +    final Map<Player, Item> result = new LinkedHashMap<>();
    +    for (Player player : playResult.keySet()) {
    +        result.put(player, toItem(playResult.get(player)));
         }
    +    return new LadderGameResult(result);
     }
     
    -

    DB에서는 확인하려면 root 계정으로 접속한 후 general log를 활성화 시킨다.

    -
    SET GLOBAL log_output = 'table';
    -SET GLOBAL general_log = 1;
    -
    -

    general log를 활성화 한 후 읽기 전용 메서드를 실행한다.
    -server_id, 실행한 쿼리문을 확인할 수 있다.

    -
    SELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like '%select%';
    -
    -+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+
    -| user_host                  | thread_id | server_id | convert(argument using utf8)                                                |
    -+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+
    -| user[user] @  [172.25.0.1] |       277 |         2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |
    -+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+
    -
    -

    확인 후 general log를 비활성화 한 후 비활성화 되었는지 확인한다.

    -
    SET GLOBAL general_log = 0;
    -SHOW VARIABLES LIKE '%general%';
    -
    -+------------------+---------------------------------+
    -| Variable_name    | Value                           |
    -+------------------+---------------------------------+
    -| general_log      | OFF                             |
    -| general_log_file | /var/lib/mysql/4b6b9db98290.log |
    -+------------------+---------------------------------+
    -
    -

    참고 자료

    -

    16장 복제, Real MySQL 8.0 - 백은빈, 이성욱
    -Replication, MySQL Docs
    -MySql - Master Slave Replication 구조 만들어보기
    -Spring 레플리케이션 트랜잭션 처리 방식
    -replication-datasource
    -Simplified Guide to MySQL Replication with Docker Compose
    -Dockerfile에서 자주 쓰이는 명령어
    -CHANGE REPLICATION SOURCE TO Statement
    -LazyConnectionDataSourceProxy
    -데이터베이스 레플리케이션을 통한 쿼리 성능 개선 (feat. Mysql, SpringBoot)
    -부하 분산을 위한 MySQL Replication 구성 및 쿼리 요청 분기
    -Use Docker Compose, Docker

    +

    부족했던 부분

    +

    유비쿼터스 언어에 시간을 들이기
    +유비쿼터스 언어를 정하는데 시간을 조금 더 들여야겠다고 생각했다.
    +사다리 타기의 실행 결과를 Item으로 짓다니.. 뭔가 만족스럽지 않다.
    +이전 미션과 마찬가지로, 명명하는 부분에서 부족함을 많이 느꼈다.

    +

    페어와 조금 더 친해지기
    +첫날은 페어와 친해지는 시간을 조금 더 가져야겠다고 생각했다.
    +우가랑 회고할 때 내가 시작하자마자 컨벤션 정하자고 해서 많이 당황스러웠다고 한다. 우가 미안.. 🥲

    +

    README를 조금 더 꼼꼼하게
    +이상하게 코딩에 집중하면 README를 업데이트하면서 같이 커밋 하는 걸 항상 까먹는다.
    +다음 미션에는 조금 더 신경 써야겠다.

    +

    좋은 질문을 생각하기
    +첫 PR때 리뷰어에게 질문을 남기지 못했다.
    +리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

    +

    PR 후에도 꼼꼼하게 확인하기
    +분명 알고 있는 부분이지만, 놓친 부분이 많은 것 같았다.
    +PR 하기 전에도 계속 확인을 했지만, 아무래도 IntelliJ에서 보니 코드에 익숙해져서 그런지 변경해야 할 부분이 잘 안보였다.
    +github pr에서는 전체 변경사항을 확인할 수 있으니 PR 후에도 꼭 확인해야겠다.

    +

    적극적으로 나의 의견을 말하기
    +의견을 적극적으로 내는 부분에 대해서 페어의 의견이 괜찮다고 생각하면 수용 후 개선을 하는 방향으로 진행을 했었는데, 조금 더 개선할 수 있는 방향이 있다면 나도 적극적으로 의견을 말해야겠다고 생각이 든다.
    +나도 설득하는 힘을 기르고, 페어도 좋은 방향을 알 수 있고, 결과물도 좋은 방향으로 나오지 않을까? (고민 들어주신 리뷰어 터틀🐢 감사합니다.)

    +

    새로 학습한 부분

    +

    객체의 생성 책임
    +Players가 Position을 생성하고 Player의 생성자에 넣어주었다. 하지만 이 부분에 대해서 생성 책임에 관련된 코멘트가 달렸다. +시간을 가지고 생각해 보니 Position을 가지고 있는 건 Player기 때문에 생성 책임을 Player가 담당하는 것이 좋다고 생각되었다.

    +

    생성 책임에 관한 패턴으로 GRASP의 Creator 패턴이 있는데 다음의 요소를 최대한 만족하는 클래스에 생성 책임을 할당하는 것이 좋다.

    +
      +
    • B가 A 객체를 포함 또는 참조한다.
    • +
    • B가 A 객체를 기록한다.
    • +
    • B가 A를 긴밀하게 사용한다.
    • +
    • B가 A의 초깃값을 가지고 있다.
    • +
    +

    실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

    +

    패키지 분리 기준
    +패키지 분리에 대한 나만의 기준이 아직 명확하지 않아 질문이 들어와도 명확하게 답변을 하지 못했다.
    +마지막 제출 전에 도메인 패키지 내부를 분리해 봤는데, 기준이 명확하지 않았기 때문에 좋지 않은 선택이었던 것 같다. +현재 진행하는 미션의 애플리케이션 크기가 그렇게 크지 않으니, domain 패키지에서 세부 패키지로 분리하지 않아도 될 것 같다.

    +

    사용하는 쪽에서 생각하기 & 예측가능한 코드 작성하기
    +Position에서 다음 위치나 이전 위치를 반환하는 메서드를 허용 범위(019)가 벗어난다면, 의미 없는 값이 들어간 Position을 반환하도록 했다.
    +이건 Position을 사용하는 입장을 고려하지 못한 코딩이었는데, 사용하는 입장에서는 0
    19의 값이 보장되어 있다고 생각할 것이기 때문이다.
    +따라서 hasNext, hasPrevious라는 이전 값, 이후 값이 범위 내에 있는지 확인하는 메서드를 추가하고, 기존의 값을 가져오는 메서드는 범위가 벗어나면 예외를 던지는 방향으로 해결하였다.

    +

    페어에게 배울 부분

    +

    밝은 기운을 가지고 있고 다른 사람들과 친화력이 좋은 것 같았다.
    +이번에 페어 할 때 컨디션 관리를 제대로 못해서 많이 미안했다. 다음에는 최상의 컨디션으로 페어를 준비해 봐야겠다.
    +그리고 우가랑 페어를 하고 나서, 나도 다른 사람들과 더 잘 지내봐야겠다는 생각이 들어 조금 더 용기를 내 잡담 중이다!

    +

    의견을 적극적으로 내줘서 페어프로그래밍 진행이 잘 되었다.
    +또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
    +페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

    +

    항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
    +웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

    \ No newline at end of file diff --git a/parameterized-tests.html b/parameterized-tests.html index 1c9fbf8a0..8d264c554 100644 --- a/parameterized-tests.html +++ b/parameterized-tests.html @@ -13,11 +13,11 @@ - - + + -

    Parameterized Tests

    · 약 4분

    테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
    +

    Parameterized Tests

    · 약 4분

    테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
    이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

    Argument Sources

    @ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
    @@ -82,7 +82,7 @@

    CSV Source

    Method Source

    복잡한 타입의 값을 전달할 때 사용한다.
    메서드명을 입력하여 매개변수를 제공하는 메서드를 지정할 수 있다.
    -메서드명을 따로 입력하지 않으면 테스트명과 동일한 static 메서드가 지정된다.

    +메서드명을 따로 입력하지 않으면 테스트명과 동일한 static 메서드가 지정된다.

    @ParameterizedTest
     @MethodSource
     void methodTest(final List<Integer> numbers, final int count) {
    @@ -106,6 +106,6 @@ 

    ETC.

    참고 자료

    +
    \ No newline at end of file diff --git a/performance-test-type.html b/performance-test-type.html index dd9deac1c..5559fa09f 100644 --- a/performance-test-type.html +++ b/performance-test-type.html @@ -13,11 +13,11 @@ - - + + -

    성능 테스트 종류

    · 약 6분

    성능 테스트

    +

    성능 테스트 종류

    · 약 6분

    성능 테스트

    API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

    시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
    다양한 상황에 대비해서 성능 테스트를 해야한다.

    @@ -28,7 +28,7 @@

    스모크 테스트(Smoke Test)

    다른 테스트를 시작하기 전에 스모크 테스트를 함으로써 테스트 스크립트에 오류가 없는지 확인할 수 있고, 성능 지표가 정상적으로 수집, 모니터링 되고 있는지 확인할 수 있다.

    가상 사용자는 서버 애플리케이션에 대해 특정 테스트를 실행한다.
    이는 다른 가상 사용자와 독립적으로 실행되며, 여러 가상 사용자를 사용하여 동시 연결을 할 수 있다.
    -스레드라고 생각하면 된다.

    +스레드라고 생각하면 된다.

    스파이크 테스트(Spike Test)

    사용량이 급증하는 상황에서 시스템이 견디고 성능에 문제가 없는지 확인하는 테스트

    티켓 발급, 할인 쿠폰 발급과 같은 이벤트를 하는 경우 대규모 트래픽이 들어온다.
    @@ -43,8 +43,8 @@

    스트레스 테스트(Stress Test)그래프를 봤을 때 부하 테스트와 유사한 형태로 보이지만, 부하량이 다르다.
    일반적으로 평균적인 목푯값 대비 작게는 50% 이상, 필요의 경우 그 이상으로 부하를 준다.
    스트레스 테스트는 부하 테스트를 실행한 후에만 실행해야 한다. 부하 테스트가 이루어지지 않은 상황에서 스트레스 테스트를 실행하는 경우에는 병목 지점이나 문제 상황을 찾기 어려워진다.
    -또한 부하 테스트에서 사용한 스크립트를 VU값(스레드 수)만 수정하여 재사용하는 것이 좋다.

    -

    내구 테스트(Endurance Test)

    +또한 부하 테스트에서 사용한 스크립트를 VU값(스레드 수)만 수정하여 재사용하는 것이 좋다.

    +

    내구 테스트(Endurance Test)

    평균 사용률로 일정 부하를 지속적으로 주며 시스템이 문제되는 지점을 확인하는 테스트

    흡수 테스트(Soak Test)라고도 하며, 기본적인 부하 테스트의 변형이라고 볼 수 있다.
    다른 테스트와 달리 긴 시간동안 테스트를 하는 것이 특징이며, 메모리 누수 문제와 같이 장시간 애플리케이션을 실행할 때 시스템의 문제가 발생하는 부분을 확인하는 것이 목적이다.

    @@ -56,6 +56,6 @@

    중단점 테스트(Breakpoint Test)

    참고 자료

    Load test types, k6
    자바 최적화 - 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드
    -아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

    +아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

    \ No newline at end of file diff --git a/racing-car-retrospective.html b/racing-car-retrospective.html index 5147f5c9d..b8c8e934e 100644 --- a/racing-car-retrospective.html +++ b/racing-car-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    자동차 경주 미션 회고

    · 약 8분

    1단계: https://github.com/woowacourse/java-racingcar/pull/510
    +

    자동차 경주 미션 회고

    · 약 8분

    1단계: https://github.com/woowacourse/java-racingcar/pull/510
    2단계: https://github.com/woowacourse/java-racingcar/pull/538

    자동차 경주

    자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
    @@ -56,7 +56,7 @@

    부족했던 부분

    다음 미션부터는 더 많은 시간을 페어의 의견과 이야기를 듣는 곳에 사용해야겠다.

    새로 학습한 부분

    Assertions extracting

    -

    결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
    +

    결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
    이전에는 필요에 따라 stream을 이용하여 검증할 값을 생성했지만, 해당 방법을 이용해서 절차를 줄일 수 있었다.

    @Test
     void extracting() {
    @@ -81,7 +81,7 @@ 

    새로 학습한 부분

    테스트를 위한 getter 사용

    테스트 용도로 도메인에 새로운 메서드가 생성되는 것은 좋지 못하다.
    필요의 경우 생성해서 사용할 수 있지만, 기존에 있는 메서드들을 활용해보는 것이 더 좋은 방법이다.
    -이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

    +이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

    페어에게 배울 부분

    질문이나 생각할 점이 있을 때 매우 깊게 고민하는 것 같았다.
    생각을 정리한 후 자신의 의견을 명료하게 전달해주었다.
    @@ -96,6 +96,6 @@

    페어에게 배울 부분

    그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

    어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
    이건 바로 배울 수 없지만.
    -나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

    +나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

    \ No newline at end of file diff --git a/refactoring-retrospective.html b/refactoring-retrospective.html index c9ee0ae24..e26c87812 100644 --- a/refactoring-retrospective.html +++ b/refactoring-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    레거시 코드 리팩터링 미션 회고

    · 약 9분

    1단계: https://github.com/woowacourse/jwp-refactoring/pull/465
    +

    레거시 코드 리팩터링 미션 회고

    · 약 9분

    1단계: https://github.com/woowacourse/jwp-refactoring/pull/465
    2단계: https://github.com/woowacourse/jwp-refactoring/pull/547
    3단계: https://github.com/woowacourse/jwp-refactoring/pull/610
    4단계: https://github.com/woowacourse/jwp-refactoring/pull/721

    @@ -25,7 +25,7 @@

    리팩터링 미션

    요구사항 작성 → 테스트를 통한 코드 보호 → 리팩터링 → 의존성 리팩터링 → 멀티모듈 순서로 미션을 진행했다.
    미션에 온전히 집중하고 싶었지만, 프로젝트와 병행하면서 진행했기에 어느정도 타협보고 진행한 부분이 많아서 아쉬웠다.

    1, 2단계

    -

    1단계는 요구사항을 작성하고, 테스트 코드를 작성하여 추후에 리팩터링 할 때 안정감 있게 진행할 수 있도록 준비하는 과정이었다. +

    1단계는 요구사항을 작성하고, 테스트 코드를 작성하여 추후에 리팩터링 할 때 안정감 있게 진행할 수 있도록 준비하는 과정이었다. 요구사항을 작성할 때 제공된 용어 사전을 최대한 활용하면서 기존의 코드를 보면서 요구사항을 정리했다. 테스트는 시간 관계상 API, 서비스 둘 중 하나만 통합 테스트를 진행해야겠다는 생각이 들었다.

    최종적으로 서비스 기준으로 통합 테스트를 작성했는데 약간 후회되는 결정이었던 것 같다.
    @@ -39,7 +39,7 @@

    소프트웨어의 복 소프트웨어의 복잡성을 다루는 지혜는 에릭 에반스의 저서 도메인 주도 설계의 부제이다.

    도메인 주도 설계는 유비쿼터스 언어, 전략적 설계, 전술적 설계가 중요하다고 한다.
    유비쿼터스 언어, 전략적 설계가 전체의 90%에 해당할 정도로 중요하다고 한다. 또한 전술적 설계만 하는 경우를 DDD Lite 라고 한다.

    -

    간단히 도메인 주도 설계에서 나오는 단어를 정리한다면 다음과 같다.

    +

    간단히 도메인 주도 설계에서 나오는 단어를 정리한다면 다음과 같다.

    단어설명
    도메인소프트웨어로 해결하고자 하는 문제 영역
    바운디드 컨텍스트해결 영역, 관심사를 분리하고 격리하여 문제 해결에 집중할 범위
    유비쿼터스 언어프로젝트에 이해관계자들의 공통된 언어로, 서로의 의사소통 비용을 줄이기 위해 사용하는 언어
    전략적 설계도메인 전문가와 개발자가 함께 유비쿼터스 언어를 이용하여 도메인과 관련된 지식을 이해하고 이를 바탕으로 경계를 나눠 바운디드 컨텍스트를 정의하고, 컨텍스트 맵을 생성하는 것을 포함하는 과정
    전술적 설계전략적 설계에서 정의한 바운디드 컨텍스트와 도메인을 이용하여 애그리거트, Entity와 VO, Repository 등을 구현하는 과정

    이 외에도 다양한 내용들이 나왔지만, 지식을 제대로 흡수하지는 못했다.

    3, 4단계

    @@ -48,7 +48,7 @@

    3, 4단계

    함께 생성되고 삭제되는 객체들을 묶고, 결합도를 낮추기 위해 생명주기가 다르다면 id를 이용하여 참조하도록 변경했다.

    의존성을 분리하기 위해 이벤트도 사용해보았다. 이벤트는 현재 기준으로 과거에 벌어진 것을 표현하기 때문에 이벤트명은 과거 시제가 되어야하는 것을 알았다. 처음에는 애플리케이션 이벤트를 사용했지만, 서비스 로직을 최대한 간단하게 하기 위해 도메인 이벤트도 사용해보았다.

    -

    4단계는 멀티모듈로 분리하는 미션이었는데 3단계에서 분리해둔 패키지 그대로 분리하지는 않았다.
    +

    4단계는 멀티모듈로 분리하는 미션이었는데 3단계에서 분리해둔 패키지 그대로 분리하지는 않았다.
    3단계에서는 함께 생성되고 삭제되는 객체 기준으로 분리했다. 4단계에서는 내가 인식하기 편한 기준으로 분리를 했다. 아직 분리한 기준에 대한 근거가 모호했고, 이에 대한 공부를 조금 더 해야겠다고 생각했다.

    마무리

    참고 자료

    도메인 원정대, 우아콘 2021
    우아한객체지향, 우아한테크세미나
    -TestFixtures, 권남님

    +TestFixtures, 권남님

    \ No newline at end of file diff --git a/route-image-async-with-event.html b/route-image-async-with-event.html index 1c6aa2693..95113d941 100644 --- a/route-image-async-with-event.html +++ b/route-image-async-with-event.html @@ -13,11 +13,11 @@ - - + + -

    경로 이미지 생성하기 - 비동기 처리

    · 약 12분

    이전 글

    + +회원시스템 이벤트기반 아키텍처 구축하기

    \ No newline at end of file diff --git a/route-image-implementation.html b/route-image-implementation.html index f2f8c4e12..c8d809395 100644 --- a/route-image-implementation.html +++ b/route-image-implementation.html @@ -13,11 +13,11 @@ - - + + -

    경로 이미지 생성하기 - 구현

    · 약 12분

    개요

    +

    경로 이미지 생성하기 - 구현

    · 약 12분

    개요

    여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
    경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

    구현 결과

    @@ -48,7 +48,7 @@

    IMAGE_SIZE & ROUTE_SIZE

    255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

    주요 클래스

    요약

    -
    클래스명설명특이사항
    Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
    CoordinatesCoordinate의 일급 컬렉션-
    Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
    PositionsPositions의 일급 컬렉션-
    RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
    RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
    RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
    BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
    Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
    +
    클래스명설명특이사항
    Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
    CoordinatesCoordinate의 일급 컬렉션-
    Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
    PositionsPositions의 일급 컬렉션-
    RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
    RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
    RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
    BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
    Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성

    의존관계

    전체 Flow RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer에서 getter 사용)를 전달하여 이미지 저장 요청 RouteImageUploader->>RouteImageGenerator: 저장 후 저장된 이미지명(또는 url) 반환 RouteImageGenerator->>외부 클래스: 저장된 이미지명(또는 url) 반환 - ">
    + ">
    \ No newline at end of file diff --git a/route-image-intro.html b/route-image-intro.html index d2d44f319..357539306 100644 --- a/route-image-intro.html +++ b/route-image-intro.html @@ -13,11 +13,11 @@ - - + + -

    경로 이미지 생성하기 - 기술 선택

    · 약 6분

    ./route.png

    +

    경로 이미지 생성하기 - 기술 선택

    · 약 6분

    ./route.png

    이미지 생성의 책임

    위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
    따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

    @@ -46,7 +46,7 @@

    Python & Matplotlib

    Java AWT 이외의 라이브러리

    Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

    -
    라이브러리설명제외 이유
    SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
    JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
    simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
    matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
    +
    라이브러리설명제외 이유
    SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
    JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
    simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
    matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음

    Java & AWT(Abstract Window Toolkit)

    그래픽과 이미지를 그리기 위한 도구
    이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

    @@ -67,6 +67,6 @@

    유지 보수

    레벨 3를 마무리하며 내용 추가

    기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
    -AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

    +AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

    \ No newline at end of file diff --git a/route-image-python.html b/route-image-python.html index f750f8108..05092baa6 100644 --- a/route-image-python.html +++ b/route-image-python.html @@ -13,11 +13,11 @@ - - + + -

    경로 이미지 생성하기 - 파이썬

    · 약 7분

    개요

    +

    경로 이미지 생성하기 - 파이썬

    · 약 7분

    개요

    이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

    사용 기술

    언어: Python 3.10
    @@ -41,7 +41,7 @@

    요구사항

    이미지 출력 방식

      -
    1. 위경도를 처리한 값으로 직접 경로를 그린 다음 이미지 형태로 저장
    2. +
    3. 위경도를 처리한 값으로 직접 경로를 그린 다음 이미지 형태로 저장
    4. 플롯을 그려주는 라이브러리 사용하여 이미지 형태로 저장

    이미지 출력 방식의 경우 1번과 2번을 고민했었다.
    @@ -188,6 +188,6 @@

    참고 자료

    Lambda Layer
    Python Lambda 함수에 대한 .zip 파일 아카이브 작업
    No module named 'numpy.core._multiarray_umath'
    -사례별로 알아본 안전한 S3 사용 가이드

    +사례별로 알아본 안전한 S3 사용 가이드

    \ No newline at end of file diff --git a/rss.xml b/rss.xml index 04b6b8447..d81b64b74 100644 --- a/rss.xml +++ b/rss.xml @@ -4,2608 +4,1815 @@ GG Blog https://greeng00se.github.io/ GG Blog - Tue, 31 Oct 2023 00:00:00 GMT + Sun, 01 Jan 2023 00:00:00 GMT https://validator.w3.org/feed/docs/rss2.html https://github.com/jpmonette/feed ko - <![CDATA[레거시 코드 리팩터링 미션 회고]]> - https://greeng00se.github.io/refactoring-retrospective - https://greeng00se.github.io/refactoring-retrospective - Tue, 31 Oct 2023 00:00:00 GMT - -

    1단계: https://github.com/woowacourse/jwp-refactoring/pull/465
    -2단계: https://github.com/woowacourse/jwp-refactoring/pull/547
    -3단계: https://github.com/woowacourse/jwp-refactoring/pull/610
    -4단계: https://github.com/woowacourse/jwp-refactoring/pull/721

    -

    리팩터링 미션

    -

    요구사항 작성 → 테스트를 통한 코드 보호 → 리팩터링 → 의존성 리팩터링 → 멀티모듈 순서로 미션을 진행했다.
    -미션에 온전히 집중하고 싶었지만, 프로젝트와 병행하면서 진행했기에 어느정도 타협보고 진행한 부분이 많아서 아쉬웠다.

    -

    1, 2단계

    -

    1단계는 요구사항을 작성하고, 테스트 코드를 작성하여 추후에 리팩터링 할 때 안정감 있게 진행할 수 있도록 준비하는 과정이었다. -요구사항을 작성할 때 제공된 용어 사전을 최대한 활용하면서 기존의 코드를 보면서 요구사항을 정리했다. -테스트는 시간 관계상 API, 서비스 둘 중 하나만 통합 테스트를 진행해야겠다는 생각이 들었다.

    -

    최종적으로 서비스 기준으로 통합 테스트를 작성했는데 약간 후회되는 결정이었던 것 같다.
    -리팩터링 과정에서 API 명세가 바뀌지 않아야 한다는 것을 기준을 잡고 이번 미션을 한다고 가정했을 때 API 기준으로 테스트를 작성하고, 리팩터링을 진행하는 것이 더 안정감 있다고 생각한다.

    -

    2단계는 작성된 테스트 기반으로 리팩터링 하는 미션이었다.
    -서비스에서 도메인을 직접 반환하는 구조였는데, 도메인에 JPA를 적용하면 기존 명세와 달라질 것을 우려해서 DTO로 수정하는 작업을 먼저 진행했다. -DTO 이후에 서비스에 있는 로직을 도메인으로 이동시키고, 최종적으로 JPA를 적용하는 순서로 리팩터링을 진행했다. -이 과정에서 의존성 방향이 양방향인 부분도 생겨났다.

    -

    소프트웨어의 복잡성을 다루는 지혜

    -

    중간에 소프트웨어 복잡성을 다루는 지혜에 관한 제이슨의 강의가 있었다.
    -소프트웨어의 복잡성을 다루는 지혜는 에릭 에반스의 저서 도메인 주도 설계의 부제이다.

    -

    도메인 주도 설계는 유비쿼터스 언어, 전략적 설계, 전술적 설계가 중요하다고 한다.
    -유비쿼터스 언어, 전략적 설계가 전체의 90%에 해당할 정도로 중요하다고 한다. 또한 전술적 설계만 하는 경우를 DDD Lite 라고 한다.

    -

    간단히 도메인 주도 설계에서 나오는 단어를 정리한다면 다음과 같다.

    -
    단어설명
    도메인소프트웨어로 해결하고자 하는 문제 영역
    바운디드 컨텍스트해결 영역, 관심사를 분리하고 격리하여 문제 해결에 집중할 범위
    유비쿼터스 언어프로젝트에 이해관계자들의 공통된 언어로, 서로의 의사소통 비용을 줄이기 위해 사용하는 언어
    전략적 설계도메인 전문가와 개발자가 함께 유비쿼터스 언어를 이용하여 도메인과 관련된 지식을 이해하고 이를 바탕으로 경계를 나눠 바운디드 컨텍스트를 정의하고, 컨텍스트 맵을 생성하는 것을 포함하는 과정
    전술적 설계전략적 설계에서 정의한 바운디드 컨텍스트와 도메인을 이용하여 애그리거트, Entity와 VO, Repository 등을 구현하는 과정
    -

    이 외에도 다양한 내용들이 나왔지만, 지식을 제대로 흡수하지는 못했다.

    -

    3, 4단계

    -

    제이슨의 강의를 듣고, 조영호님의 우아한객체지향 유튜브 영상을 본 다음 3, 4단계를 진행했다.

    -

    3단계는 의존성 리팩터링에 관한 내용이었다. 클래스 간 방향, 패키지 간 방향을 단방향이 되도록 리팩터링을 진행해야 했었다. -함께 생성되고 삭제되는 객체들을 묶고, 결합도를 낮추기 위해 생명주기가 다르다면 id를 이용하여 참조하도록 변경했다.

    -

    의존성을 분리하기 위해 이벤트도 사용해보았다. 이벤트는 현재 기준으로 과거에 벌어진 것을 표현하기 때문에 이벤트명은 과거 시제가 되어야하는 것을 알았다. -처음에는 애플리케이션 이벤트를 사용했지만, 서비스 로직을 최대한 간단하게 하기 위해 도메인 이벤트도 사용해보았다.

    -

    4단계는 멀티모듈로 분리하는 미션이었는데 3단계에서 분리해둔 패키지 그대로 분리하지는 않았다.
    -3단계에서는 함께 생성되고 삭제되는 객체 기준으로 분리했다. 4단계에서는 내가 인식하기 편한 기준으로 분리를 했다. -아직 분리한 기준에 대한 근거가 모호했고, 이에 대한 공부를 조금 더 해야겠다고 생각했다.

    - -

    추가로 테스트 격리를 위한 직접 작성한 @ServiceTest 커스텀 애너테이션이 있었는데, 상위 모듈의 테스트에서 만든 클래스를 하위 모듈에서는 사용할 수 없었다. -따라서 TestFixtures를 사용하여 해결했다.

    -

    마무리

    -

    우아한테크코스의 마지막 미션이니 만큼, 가장 흥미로운 미션이었고 배울점도 많았던 것 같다.
    -바쁜 기간이라 많은 리뷰를 남기지 못했던 리뷰이 호이에게 미안하고, 코멘트 꼼꼼하게 달아주고 미션에 대한 이야기도 오프라인으로 많이 나눈 리뷰어 테오에게 너무 감사하다.

    -

    참고 자료

    -

    도메인 원정대, 우아콘 2021
    -우아한객체지향, 우아한테크세미나
    -TestFixtures, 권남님

    ]]>
    - Woowahan Techcourse + <![CDATA[[책] 글, 우리도 잘 쓸 수 있습니다.]]> + https://greeng00se.github.io/book-writer + https://greeng00se.github.io/book-writer + Sun, 01 Jan 2023 00:00:00 GMT + + 책 정보 +
    +

    글, 우리도 잘 쓸 수 있습니다.
    +박솔미

    +
    +

    읽고 나서

    +

    저자의 경험과 함께 글쓰기에 대한 가벼운 조언이 담겨있어 가볍게 읽기 좋았다.
    +글을 잘 작성해 보고 싶을 때 적용해 볼 수 있는 정보가 많아서 도움이 되었다.

    +

    우아한 테크코스의 프리코스를 진행할 때 후기를 작성하고 나면 항상 글이 딱딱하다는 느낌을 받았다.
    +다른 지원자들의 읽기 편하고, 밝은 느낌을 주는 글을 보면 부러운 마음을 가지기도 했다.
    +이 책을 읽었으니 2023년에는 조금 더 글을 잘 적어보려고 한다.

    +

    밑줄 친 문장들

    +
    +

    문장이 심심하고 지루하다면 +내용을 일목요연하게 정리했고, 글의 의도도 삐뚤지 않고, 단어도 적절한 것으로 골랐는데… 그런데도 어딘가가 심심하고 지루하다면? 축축 처지고 따분하다면? 말꼬리를 모조리 ‘~다’로 통일한 건 아닌지 점검해 보세요.

    +
    +
    +

    말꼬리를 잘 갖고 놀아야 합니다. 문장의 마지막 글자를 매번 다르게 고쳐쓰는 것만으로도 글에 활기를 더할 수 있죠. 때론 문장을 다 마치지 않고, 단어로만 끝맺는 것도 방법. 문장과 문장 사이에 쉼표가 들어서며 글 전체에 활기가 돌게 돼요. 문장의 길이도 다채로워지는 덕분에 덤으로 얻게 되는 것도 있습니다. 바로, 글의 리듬.

    +
    +
    +

    이전 문장에서 끝난 글자로, 다음 문장을 끝맺지 않기. 한두 문단마다 단어 수준의 아주 짧은 문장 배치하기.

    +
    +
    +

    글의 진짜 이유, 글의 진짜 목적, 글의 진짜 대상을 찾으려고 애썼습니다. 지금처럼 틀을 떠올린다거나, 눈치를 본다거나, 정치적인 셈도 하지 않았어요.

    +
    +
    +

    제목은 짧게, 보기 쉽게, 읽기 쉽게, 발음이 비슷하게, 순서를 바꿔서

    +
    +
    +

    글을 마지막으로 다듬을 때, 노래에 가까워질 방법은 없을지 고민해봅니다. 감히 가 닿을 수 없는 목표이겠지만, 할 수 있는 최소한의 리듬이라도 붙여주고 싶어요.

    +
    +
    +

    여는 말과 마지막 말에 작정하고 마음을 담는 연습을 해봅시다. 글의 어느 구석이라도 뻔한 글자는 남기지 않겠노라 다짐하며 써보는 겁니다. 나만이 가진 유일한 메시지에 집중하면서요. 그럼 생각이 달라지고, 고르는 단어도 달라지고, 남긴 문장도 달라져요. 결국에는 글을 쓴 사람인 나 자신도 남달라질 겁니다.

    +
    +
    +

    맞춤법은 중요합니다. 하지만 맞춤법보다 더 중요한 건 거기에 담긴 마음입니다. 내 마음을 글에 담아 실어 보내기 전, 맞춤법을 점검하는 이유 역시 그겁니다. 오직 내 마음이 남에게 읽히는 동안 방해가 되지 않기를 바라기 때문이죠. 내가 쓴 글도, 남이 쓴 글도. 언제나 그 안에 담긴 마음이 먼저입니다.

    +
    +
    +

    글을 쓴다고 글이 완성되는 게 아니에요. 글과 닮은 모습으로 살 때, 글은 비로소 완성됩니다.

    +
    ]]>
    + Book +
    + + <![CDATA[2022년 회고]]> + https://greeng00se.github.io/2022-retrospective + https://greeng00se.github.io/2022-retrospective + Mon, 02 Jan 2023 00:00:00 GMT + + 적당한 전환점, 2022년을 돌아보며

    +

    전역

    +

    약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
    +조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

    +

    조금 더 미래에 대한 생각을 해볼걸 그랬다.
    +전역을 했지만 뭐 하나 제대로 할 줄 아는 것도 없으니 넓은 바닷속에 덩그러니 놓아진 기분이 괜히 들었었다.
    +일찍 생각을 정리하여 방향을 잡지 못했기에 아쉬움이 많이 남았다.

    +

    자바

    +

    전역을 하고 진로를 고민하다 향로님의 자바 공화국 포스팅을 읽고 나서 자바 공부를 시작했다.
    +유명한 인프런의 김영한님의 스프링 강의도 있고, 좋은 자바 개발 서적이 많아서 독학하기로 결정했다.
    +하다 보니 자바와 스프링을 공부하면서 “왜 진작하지 않았지”라는 생각도 많이 들었다.
    +양질의 자료도 많았기 때문에, 예전에 노드로 개발했을 때 풀지 못했던 답답함을 많이 해소했던 것 같다.

    +

    23년에는 조금 더 깊게 자바를 공부해볼 생각이다.
    +언어를 하나 깊게 공부하는 건 많은 도움이 되는 것 같다.

    +

    스터디

    +

    김영한님의 강의를 거의 다 들었을 때쯤, 항상 강의에서 언급되는 토비의 스프링을 읽어보고 싶어졌고
    +혼자 공부하기에는 동기부여도 부족했기 때문에 스터디를 시작했다.
    +다른 사람에게 설명을 해야 했기 때문에 더욱 꼼꼼하게 공부를 할 수 있어서 좋았지만 나에게는 내용이 꽤나 어려워서 시간을 많이 소비했다.
    +같이 스터디하시는 분과 7개월 동안 스터디를 꾸준히 이어나가 총 3권의 책을 읽을 수 있었다.

    +

    우아한 테크코스

    +

    군 복무 중일 때 지원했다 떨어진 우아한 테크코스를 다시 지원했다.
    +이번 연도에 취업을 하는 게 목표였지만 내가 가지고 있는 특별한 무기가 없다는 걸 깨달았다.
    +적지 않은 시간을 투자해 준비를 했고, 감사하게도 이번에는 최종 합격을 했다.

    +

    난 사람들과 소통하고, 협업하는 능력이 부족하다고 생각을 많이 했다.
    +우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

    +

    2023년에는

    +

    마음의 여유가 없었던 2022년이었던 것 같다.
    +하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

    ]]>
    Retrospective
    - <![CDATA[Jdbc 라이브러리 구현 미션 회고]]> - https://greeng00se.github.io/jdbc-retrospective - https://greeng00se.github.io/jdbc-retrospective - Tue, 10 Oct 2023 00:00:00 GMT - -

    1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
    -2단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358
    -3단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448
    -4단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515

    -

    Jdbc 구현

    -

    이번 미션은 Jdbc 라이브러리를 구현하고, Transaction 경계 설정과 동기화하는 부분을 구현해 보는 미션이었다.
    -미션 목표는 다음과 같다.

    + <![CDATA[[책] 객체지향의 사실과 오해]]> + https://greeng00se.github.io/the-essence-of-object-orientation + https://greeng00se.github.io/the-essence-of-object-orientation + Sat, 07 Jan 2023 00:00:00 GMT + + 책 정보 +
    +

    객체지향의 사실과 오해
    +조영호

    +
    +

    읽고 나서

    +

    조영호님의 오브젝트를 읽고 나서 다시 한 번 읽어보았다.
    +아직 이해가 안되는 부분이 많지만, 그래도 항상 새로움을 느낀다.
    +더할 나위 없이 휼륭한 객체지향 책이고, 조금 더 공부하고 다시 읽어봐야될 것 같다.

    +

    커피 전문점, 지하철 노선도, 이상한 나라의 엘리스를 예시로 든 설명이 너무 좋았고
    +좋은 내용을 담고 있지만 그렇다고 너무 무겁지 않아 가볍게 읽기도 좋은 것 같다.

    +

    책임의 자율성을 강조하는 이유 p.173

    +

    협력을 단순하게 만든다.

      -
    • JDBC 라이브러리를 구현하면서 중복을 제거하는 연습을 한다.
    • -
    • 데이터베이스에 대한 이해도를 높인다.
    • +
    • 의도를 명확하게 표현 → 협력의 복잡함 저하
    • +
    • 책임의 추상화
    -

    최대한 Java가 제공하는 기능을 사용하여 리팩터링 하는 방향으로 코드를 작성했다.

    -

    JdbcTemplate

    -

    JdbcTemplate은 Connection을 이용하여 PreparedStatement를 생성하는 부분, 그리고 PreparedStatement가 어떻게 동작하는지에 대한 부분을 분리했다.
    -템플릿 콜백 패턴을 적절하게 적용하여 중복을 비교적 간단하게 제거할 수 있었다.
    -예전에도 미션을 진행하면서 JdbcTemplate을 구현한 적이 있었는데, 이번에는 자원 할당과 해제 부분에 대한 중복도 제거했다.

    -
    public class JdbcTemplate {
    -
    -    private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);
    -
    -    private final DataSource dataSource;
    -    private final StatementCreator statementCreator;
    -    private final StatementExecutor statementExecutor;
    -
    -    public JdbcTemplate(final DataSource dataSource) {
    -        this(dataSource, new StatementCreator(), new StatementExecutor());
    -    }
    -
    -    JdbcTemplate(
    -            final DataSource dataSource,
    -            final StatementCreator statementCreator,
    -            final StatementExecutor statementExecutor
    -    ) {
    -        this.dataSource = dataSource;
    -        this.statementCreator = statementCreator;
    -        this.statementExecutor = statementExecutor;
    -    }
    -
    -    private <T> T query(
    -            final String sql,
    -            final PreparedStatementCallback<T> preparedStatementCallback,
    -            final Object... parameters
    -    ) {
    -        final Connection connection = DataSourceUtils.getConnection(dataSource);
    -        try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {
    -            return preparedStatementCallback.execute(preparedStatement);
    -        } catch (final SQLException e) {
    -            log.error(e.getMessage(), e);
    -            throw new DataAccessException(e);
    -        } finally {
    -            DataSourceUtils.releaseConnection(connection, dataSource);
    -        }
    -    }
    -
    -    public void update(final String sql, final Object... parameters) {
    -        query(sql, PreparedStatement::executeUpdate, parameters);
    -    }
    -
    -    public <T> Optional<T> queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
    -        final List<T> results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
    -        if (results.size() > 1) {
    -            throw new DataAccessException("2개 이상의 결과를 반환할 수 없습니다.");
    -        }
    -        return results.stream().findAny();
    +

    외부와 내부를 명확하게 분리한다.

    +
      +
    • 요청하는 객체가 몰라도 되는 부분이 캡슐화됨으로 인터페이스와 구현의 분리
    • +
    +

    책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않는다.

    +
      +
    • 변경의 파급효과를 객체 내부로 캡슐화 → 메시지를 보내는 객체와의 결합도 저하
    • +
    +

    협력의 대상을 다양하게 선택할 수 있는 유연성을 제공한다.

    +
      +
    • 유연한 설계 → 재사용성 증가
    • +
    +

    객체의 역할을 이해하기 쉬워진다.

    +
      +
    • 응집도를 높은 상태로 유지
    • +
    +

    밑줄 친 문장들

    +
    +

    객체지향의 목표는 실세계를 모방하는 것이 아니다. +오히려 새로운 세계를 창조하는 것이다. +소프트웨어 개발자의 역할은 단순히 실세계를 소프트웨어 안으로 옮겨 담는 것이 아니라 고객과 사용자를 만족시킬 수 있는 신세계를 창조하는 것이다. +p.21

    +
    +
    +

    과거의 전통적인 개발 방법은 데이터와 프로세스를 엄격하게 구분한다. +이에 반해 객체지향에서는 데이터와 프로세스를 객체라는 하나의 틀 안에 함께 묶어 놓음으로써 객체의 자율성을 보장한다. +자율적인 객체로 구성된 공동체는 유지 보수가 쉽고 재사용이 용이한 시스템을 구축할 수 있는 가능성을 제시한다. +p.33

    +
    +
    +

    객체지향의 본질

    +

    시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법

    +

    자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.

    +

    객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.

    +

    객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다. +p.35

    +
    +
    +

    클래스의 구조와 메서드가 아니라 객체의 역할, 책임, 협력에 집중하라. +객체지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다. +p.38

    +
    +
    +

    객체지향에서 중요한 것은 동적으로 변하는 객체의 ‘상태’와 상태를 변경하는 ‘행위’다. +클래스는 타입을 구현하기 위해 프로그래밍 언어에서 제공하는 구현 메커니즘이라는 사실을 기억하라. +p.105

    +
    +
    +

    책임 주도 설계의 핵심은 어떤 행위가 필요한지를 먼저 결정한 후에 이 행위를 수행할 객체를 결정하는 것이다. +이 과정을 흔히 What/Who 사이클이라고 한다. +’어떤 행위(What)’를 수행할 것인지 결정한 후 ‘누가(who)’ 그 행위를 수행할 것인지 결정해야 한다. +여기서 ‘어떤 행위’가 바로 메시지다. +p.158

    +
    ]]> + Book + + + <![CDATA[JSR-310]]> + https://greeng00se.github.io/jsr-310 + https://greeng00se.github.io/jsr-310 + Sun, 08 Jan 2023 00:00:00 GMT + + 이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    +ISO-8601을 기반으로 작성
    +설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

    +

    날짜와 시간에 관련된 데이터를 다루는 국제 표준

    +

    LocalDate, LocalTime, LocalDateTime

    +

    날짜와 시간을 표현하는 클래스

    +

    Instant

    +

    유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
    +기계의 관점에서 시간 표현

    +

    Duration, Period

    +

    간격을 표현하는 클래스

    +

    TemporalAdjusters

    +

    복잡한 날짜 조정이 필요할 때 사용
    +필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

    +
    @FunctionalInterface
    +public interface TemporalAdjuster {
    +    Temporal adjustInto(Temporal temporal);
    +}
    +
    +

    DateTimeFormatter

    +

    날짜와 시간 포맷 클래스
    +특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

    +

    ZoneId, ZoneOffset

    +

    ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
    +ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

    +
    Instant instant = Instant.now();
    +LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
    +
    +

    참고 자료

    +]]>
    + Java + Time +
    + + <![CDATA[Kotlin에서 null을 다루는 방법]]> + https://greeng00se.github.io/kotlin-null + https://greeng00se.github.io/kotlin-null + Mon, 16 Jan 2023 00:00:00 GMT + + nullable 타입 +

    코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
    +이는 실행 시점이 아닌 컴파일 시 미리 오류가 발생할 가능성이 있는 부분을 미리 감지하여 NPE 발생의 가능성을 줄여준다.

    +

    코틀린의 경우 nullable 타입을 다음과 같이 표현한다.

    +
    val number: Int?
    +
    +

    타입 뒤에 ?를 붙여 해당 값이 null이 될 수 있다는 것을 의미한다.
    +만약 ?를 붙이지 않을 때 null을 받는 경우 컴파일 시 오류가 발생한다.

    +

    ?. Safe Calls 연산자

    +

    자바에서 NPE를 발생시키지 않기 위해 null을 처리하는 가장 간단한 방법으로는 분기를 사용하는 방법이 있다.

    +

    코틀린은 안전한 호출 연산자인 ?. 연산자를 지원한다.
    +따라서 참조 값이 null이 아닐 경우에만 메서드 호출을 할 수 있다.
    +참조 값이 null인 경우 메서드 호출이 무시되고, null을 반환한다.

    +
    public String repeat(String word) {
    +    if (word == null) {
    +        return null;
         }
    -
    -    public <T> List<T> queryForList(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
    -        return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
    +    return word.repeat(2);
    +}
    +
    +

    ?: 엘비스 연산자

    +

    참조하려는 값이 null일 경우 기본 값을 반환하고 싶을 때는 어떻게 해야 할까?
    +코틀린은 null이 아닌 경우 기본 값을 지정할 때 사용할 수 있는 엘비스 연산자를 지원한다.

    +
    public String stringSafe(String word) {
    +    if (word == null) {
    +        return "";
         }
    +    return word;
    +}
    +
    +

    코틀린에서는 throw도 식이기 때문에 엘비스 연산자를 이용하여 예외를 던질 수 있다.
    +예를 들어 사용자 정보가 있는 저장소에 찾는 사용자가 없는 경우 아래와 같이 사용할 수 있다.

    +
    userRepository.findByName(name) ?: throw IllegalArgumentException()
    +
    +

    !! 널 아님 단언 연산자

    +

    !! 연산자를 이용한다면 강제로 어떤 값이든 non-nullable 타입으로 변경할 수 있다.
    +하지만 null인 값에 사용한다면 NPE가 발생하게 된다.
    +일반적인 경우에는 !! 연산자를 사용하는 것은 위험하다.
    +사용하기 쉽지만, 리스크가 크고 혹시나 해당 값이 추후에는 null이 될 수 있기 때문에 지양해야 된다고 생각한다.

    +
    val length: Int = word!!.length
    +
    +

    as? 안전한 캐스팅

    +

    타입 변환을 할 때 지정한 타입으로 변경할 수 없다면 ClassCastException이 발생한다.
    +코틀린에서는 as 뒤에 ?를 붙여 안전하게 타입 변환을 할 수 있다.
    +따라서 미리 변환 가능한 타입인지 확인하지 않고, 안전하게 타입을 변환 할 수 있다.

    +

    타입 변환이 불가능 할 경우 예외를 발생시키지 않고 null을 반환한다.

    +
    val value: Int? = something as? Int
    +
    +

    List에서의 null 처리

    +

    List에는 null이 아닌 값만 반환하는 filterNotNull 유틸리티 메서드를 제공한다.

    +
    val foodsWithNull: List<String?> = listOf("Pizza", "Cheese", null, "Potato")
    +val foods = foodsWithNull.filterNotNull()
     
    -

    트랜잭션 적용

    -

    3, 4단계는 기존의 코드에 트랜잭션을 시작하고 끝나는 부분인 트랜잭션 경계를 설정하고 ThreadLocal을 이용하여 트랜잭션 동기화(Transaction synchronization)를 적용하는 미션이었다.
    -트랜잭션 동기화란 트랜잭션을 시작하기 위한 Connection 객체를 ThreadLocal과 같은 공간에 따로 저장 후, 필요할 때 저장된 Connection을 가져다 사용하는 방식이다.
    -아래와 같은 구조로 미션을 진행했는데, ThreadLocal에 Connection 객체가 아닌, Connection 객체와 Transaction이 진행 중인지 확인할 수 있는 flag를 가지고 있는 클래스를 저장해서 사용하도록 했다.

    - -

    마무리

    -

    Jdbc 미션을 진행하면서 AOP나 Transactional에 대한 학습 테스트도 진행하고, 약간 알찬 미션이었던 것 같다.
    -꼼꼼히 코드를 봐준 리뷰어 호이 그리고 연휴 동안 계속 티키타카 하면서 재밌게 리뷰한 민트에게 감사하다.
    -회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

    ]]>
    - Woowahan Techcourse - Retrospective +

    참고 자료

    +]]> + Kotlin +
    + + <![CDATA[IntelliJ 설정]]> + https://greeng00se.github.io/intellij-settings + https://greeng00se.github.io/intellij-settings + Mon, 30 Jan 2023 00:00:00 GMT + + Import 자동 적용 +

    Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

    +

    auto-import

    +

    저장시 동작

    +

    Prefrences > Tools > Actions on Save

    +

    actions-on-save

    +

    Reformat Code: Code Reformmating

    +

    Optimize imports: 사용하지 않는 Import 제거

    +

    Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

    +

    메소드 추출, 변수 추출시 final 적용

    +

    Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

    +

    final-modifier

    ]]>
    + IntelliJ
    - <![CDATA[MVC 구현 미션 회고]]> - https://greeng00se.github.io/mvc-retrospective - https://greeng00se.github.io/mvc-retrospective - Sat, 07 Oct 2023 00:00:00 GMT - -

    1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
    -2단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465
    -3단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580

    -

    MVC 구현

    -

    Reflection을 이용하여 Spring MVC와 유사한 기능을 구현하는 미션이었다.
    -미션의 목표는 다음과 같았다.

    + <![CDATA[Parameterized Tests]]> + https://greeng00se.github.io/parameterized-tests + https://greeng00se.github.io/parameterized-tests + Sun, 12 Feb 2023 00:00:00 GMT + + 테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
    +이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

    +

    Argument Sources

    +

    @ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
    +JUnit이 제공하는 다양한 Source가 있기 때문에, 테스트에 맞춰 다양하게 사용할 수 있다.

    +

    Value Source

    +

    값을 이용하여 제공하는 형태로, 다음과 같은 타입의 값을 매개변수로 제공할 수 있다.

      -
    • MVC 프레임워크를 구현하면서 내부 동작 원리를 학습한다.
    • -
    • 점진적인 리팩토링을 경험한다.
    • +
    • short, int, long, float, double
    • +
    • byte, char, boolean, String, Class
    -

    미션의 목표와 더불어 각 클래스들이 역할과 책임을 적절히 가지도록 하고, 패키지의 의존 방향을 고민하면서 미션을 진행하는 것에 중점을 두었다.

    -

    애너테이션 기반 프레임워크 만들기

    -

    기존 코드에 ManualHandlerMapping이라는 서블릿을 직접 등록해서 사용하는 HandlerMapping 클래스가 있었고, 1단계에서는 애너테이션 기반의 AnnotationHandlerMapping을 구현해야 했기 때문에 @Controller, @RequestMapping을 Reflection을 이용하여 스캔하고, 핸들러 매핑을 등록하는 부분까지 진행해야 했다.
    -테오가 @GetMapping이나 @PostMapping 부분도 진행하면 재밌을 것 같다고 해서 같이 진행해 보았다.
    -추가로 미션 요구사항은 아니었지만 클래스 레벨에 적용된 @RequestMapping도 동작하도록 구현해보았다.

    - -

    다음과 같은 Flow로 Handler(실제 요청을 처리하는 메서드) 등록을 진행한다.

    -
      -
    1. @Controller가 적용된 클래스의 정보를 스캔하여 반환한다.
    2. -
    3. @Controller가 적용된 클래스의 @RequestMapping이 적용된 메서드들의 정보를 반환한다.
    4. -
    5. 각 메서드들을 순회하며 HandlerKey(uri + httpMethod 정보)와 HandlerExecution(인스턴스 + 실행하려는 메서드)을 생성하여 Map<HandlerKey, HandlerExecution>에 추가한다.
    6. -
    -

    AnnotationHandlerMapping의 initialize 메서드에서 Handler를 등록한다. 코드는 다음과 같다.

    -
    public void initialize() {
    -    if (!initialized.compareAndSet(false, true)) {
    -        return;
    -    }
    -
    -    final Map<Class<?>, ControllerInstance> controllers = annotationScanner.scanControllers();
    -    final Set<Method> methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());
    -    for (final Method method : methods) {
    -        final ControllerInstance controller = controllers.get(method.getDeclaringClass());
    -        final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);
    -        final List<HandlerKey> handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);
    -        handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));
    -    }
    -
    -    log.info("Initialized AnnotationHandlerMapping!");
    -    handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));
    +
    @ParameterizedTest
    +@ValueSource(ints = {1, 100, Integer.MAX_VALUE})
    +void valueTest(final int value) {
    +    Assertions.assertThat(value).isPositive();
     }
     
    -

    Legacy MVC와 @MVC 통합

    -

    2단계는 Legacy MVC와 AnnotationHandlerMapping을 통합하는 부분이었다.
    -기존의 MVC와 애너테이션이 적용된 MVC 두 개를 같이 사용할 수 있어야 헀다.
    -대략적인 흐름은 다음과 같다.

    -
      -
    1. DispatcherServlet.service(request, response) 호출
    2. -
    3. HandlerMappings를 통해 입력받은 request에 해당하는 Handler 조회
    4. -
    5. HandlerAdapters를 통해 Handler를 실행시킬 수 있는 HandlerAdapter 조회
    6. -
    7. HandlerAdapter의.handle 메서드 실행
    8. -
    9. View의 render 호출
    10. -
    -Null & Empty Source +

    null 값, 빈 값을 제공한다.
    +Empty Source의 경우 다음과 같은 타입에 한해 매개변수로 제공할 수 있다.

    +
      +
    • String
    • +
    • java.util.List, java.util.Set, java.util.Map
    • +
    • primitive arrays — ex) int[]
    • +
    • object arrays — ex) String[]
    • +
    +
    @ParameterizedTest
    +@NullAndEmptySource
    +void nullAndEmptyTest(final String value) {
    +    Assertions.assertThat(value).isNullOrEmpty();
    +}
    +
    +

    Enum Source

    +

    EnumSource를 이용하여 Enum 또한 매개변수로 제공할 수 있다.

    +
    enum Day {
    +    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
    +}
     
    -	HMS --> HandlerMapping
    -	subgraph HandlerMapping
    -		direction BT
    -		AHM[AnnotationHandlerMapping] --> HM[HandlerMapping]
    -		MHM[ManualHandlerMapping] --> HM
    -	end
    +@ParameterizedTest
    +@EnumSource(Day.class)
    +void enumTest(final Day day) {
    +    assertThat(day).isInstanceOf(Day.class);
    +}
    +
    +

    다음과 같이 mode 값을 이용하여 특징 Enum을 제외하거나, 포함시킬 수 있다. (default: Mode.Include)

    +
    @ParameterizedTest
    +@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)
    +void enumTest(final Day day) {
    +    // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
    +    assertThat(day).isInstanceOf(Day.class);
    +}
    +
    +

    CSV Source

    +

    csv 형식의 값을 이용하여 매개변수를 제공한다.
    +구분자의 기본값은 쉼표(,)로 구분자를 변경하고 싶을 땐 delimeter 값을 따로 전달하여 사용할 수 있다. +개인적으로 2개 정도의 값을 매개변수로 전달하는 경우 CsvSource를 사용한다.

    +
    @ParameterizedTest
    +@CsvSource({"1,1", "2,4", "3,9", "4,16"})
    +void csvTest(final int number, final int result) {
    +    assertThat(number * number).isEqualTo(result);
    +}
    +
    +

    Method Source

    +

    복잡한 타입의 값을 전달할 때 사용한다.
    +메서드명을 입력하여 매개변수를 제공하는 메서드를 지정할 수 있다.
    +메서드명을 따로 입력하지 않으면 테스트명과 동일한 static 메서드가 지정된다.

    +
    @ParameterizedTest
    +@MethodSource
    +void methodTest(final List<Integer> numbers, final int count) {
    +    assertThat(numbers).hasSize(count);
    +}
     
    -	HAS --> HandlerAdapter
    -	subgraph HandlerAdapter
    -		direction BT
    -		HEHA[HandlerExecutionHandlerAdapter] --> HA[HandlerAdapter]
    -		CHA[ControllerHandlerAdapter] --> HA
    -	end">
    -

    웹 애플리케이션 발전 과정

    -

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    -간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.

    - -

    내용이 길어져서 다음 문서에 정리했다.

    -

    추상적인 개념 학습 방법

    -

    직관적이지 않은 추상적인 개념을 학습할 때는 개념의 구현을 참고하면 학습에 도움이 된다고 한다.

    -
    개념구현
    OOPJava
    WASTomcat, Jetty
    IoCSpring BeanFactory, Servlet Container, Framework
    DISpring BeanFactory
    -

    정리

    -

    지금까지 스프링의 DispatcherServlet의 동작을 이론적으로만 알고 있었는데, 실제로 구현해 보니 조금 더 이해가 잘 가는 것 같다.
    -이번 미션에서 나의 리뷰어는 루카, 리뷰이는 헤나였다.
    -매 단계마다 꼼꼼하게 리뷰해 준 루카에게 너무 감사하고, 헤나에게 이상한 리뷰를 많이 남긴 것 같은데 꼼꼼히 반영해줘서 감사하다.
    -오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

    ]]> - Woowahan Techcourse - Retrospective +private static Stream<Arguments> methodTest() { + return Stream.of( + Arguments.of(List.of(1), 1), + Arguments.of(List.of(1, 2), 2), + Arguments.of(List.of(1, 2, 3), 3) + ); +} +
    +

    ETC.

    +

    위에서 언급한 방법 이외에도 다양한 방법으로 매개변수를 제공할 수 있다.

    +
      +
    • CSV 파일을 이용한 CsvFileSource
    • +
    • ArgumentsProvider 구현한 클래스를 이용하는 ArgumentsSource
    • +
    +

    참고 자료

    +]]> + Java - <![CDATA[스프링 테스트 격리]]> - https://greeng00se.github.io/spring-test-isolation - https://greeng00se.github.io/spring-test-isolation - Tue, 03 Oct 2023 00:00:00 GMT - - 테스트 격리 -

    테스트의 순서에 따라 성공 실패 여부가 결정되는 비결정적인(non-determinism) 테스트가 되어서는 안되고, 테스트는 항상 순서에 상관없이 독립적으로 수행되도록 보장되어야 한다. 일반적으로 자원의 공유, 외부 API, 시간 등으로 비결정적인 테스트가 된다. 이를 해결하기 위해 테스트 대역을 사용하거나, 컨텍스트를 재실행하는 @DirtiesContext, 자원을 초기화하기 위해 테스트 이후에 테이블을 롤백 하는 @Transactional등 다양한 방법이 있다.
    -해당 글에서는 스프링에서 데이터베이스 자원의 공유를 방지하기 위해 테스트 격리를 수행하는 부분에 대해 설명한다.

    -

    테스트끼리 서로 의존하면 안 된다.
    -서로 의존하게 된다면 하나의 테스트가 실패할 때, 또 다른 하나의 테스트가 실패할 수 있다.
    -다른 테스트에 의존하지 않고, 독립적으로 실행 가능한 테스트가 좋은 테스트다.

    -

    TestExecutionListener

    -

    스프링에서는 TextExecutionListner를 이용하여 각 테스트 실행 단계에서 이벤트를 수신할 수 있다.
    -이를 이용하면 JUnit의 @BeforeEach를 사용하는 것과 유사하게, 테스트의 생명주기 이전 또는 이후에 필요한 작업을 실행시킬 수 있다.

    -
    public interface TestExecutionListener {
    -    default void beforeTestClass(TestContext testContext) throws Exception {}
    -    default void prepareTestInstance(TestContext testContext) throws Exception {}
    -    default void beforeTestMethod(TestContext testContext) throws Exception {}
    -    default void beforeTestExecution(TestContext testContext) throws Exception {}
    -    default void afterTestExecution(TestContext testContext) throws Exception {}
    -    default void afterTestMethod(TestContext testContext) throws Exception {}
    -    default void afterTestClass(TestContext testContext) throws Exception {}
    +            <![CDATA[자동차 경주 미션 회고]]>
    +            https://greeng00se.github.io/racing-car-retrospective
    +            https://greeng00se.github.io/racing-car-retrospective
    +            Tue, 14 Feb 2023 00:00:00 GMT
    +            
    +            

    1단계: https://github.com/woowacourse/java-racingcar/pull/510
    +2단계: https://github.com/woowacourse/java-racingcar/pull/538

    +

    자동차 경주

    +

    자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
    +우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

    +

    첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
    +시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

    +

    시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
    +mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

    +
      +
    • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
    • +
    • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.
    • +
    + +

    미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

    +

    페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
    +리팩터링을 어떻게 했는지? 이런 리뷰에 대해 어떻게 생각하는지 깊게 고민하는 시간을 가질 수 있었다.

    +

    부족했던 부분

    +

    리팩터링이 끝난 후 메서드명, 테스트시 출력하는 메시지에 대한 코멘트가 많이 달렸다.
    +객체가 어떤 책임과 역할을 가지는지 생각하는 시간을 가지고 명확한 메서드명을 작성해야겠다고 생각했다.

    +

    평소에 프로그래밍 이야기가 아닌 다른 주제로 이야기하면 잘 들으려고 하는 편이지만
    +내가 좋아하는 주제, 관심가는 주제인 프로그래밍에 대한 이야기를 할 땐 말이 많아진다.
    +다음 미션부터는 더 많은 시간을 페어의 의견과 이야기를 듣는 곳에 사용해야겠다.

    +

    새로 학습한 부분

    +

    Assertions extracting

    +

    결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
    +이전에는 필요에 따라 stream을 이용하여 검증할 값을 생성했지만, 해당 방법을 이용해서 절차를 줄일 수 있었다.

    +
    @Test
    +void extracting() {
    +    final Cars cars = new Cars(List.of("car1", "car2"));
    +
    +    assertThat(cars.getCars())
    +            .extracting(Car::getName)
    +            .containsExactly("car1", "car2");
     }
     
    -

    AbstractTestExecutionListener 상속하여 구현

    -

    AbstractTestExecutionListener를 상속받아 테스트 격리 환경을 만들어주는 클래스로, 인터페이스인 TextExecutionListner와 달리 Ordered가 구현되어 있어 해당 클래스를 상속받아 구현한 클래스는 프레임워크가 제공하는 리스너 다음에 실행시키도록 해준다.
    -다음과 같이 데이터베이스에서 각각의 테이블에 해당하는 Truncate 쿼리를 만들어서 조회하고, Test 메서드가 끝날때 마다 해당 쿼리를 실행하여 테이블을 초기화시키도록 설정한다.

    -
    
    -public class DatabaseCleaner extends AbstractTestExecutionListener {
    +
    +

    아래는 리뷰어님과 대화를 나누면서 얻은 답변 + 나의 의견이다.

    +

    제어할 수 없는 부분에 대한 테스트

    +

    테스트 대상이 검증된 것이라면 작성하지 않거나, 제어할 수 있는 부분에 대한 테스트를 더욱 꼼꼼하게 작성한다.
    +이건 개인적인 생각이지만 내가 안정감이 들 수 있을 정도로 출력 범위 내의 결과를 반환하는지 정도 테스트할 수 있지 않을까?

    +

    단순 위임을 하는 메서드에 대한 테스트

    +

    위임이라는 것은 역할과 책임을 넘겨준다는 것이다.
    +호출 횟수를 검증하는 것보다 결과에 대한 테스트하는 것이 좋다.
    +단순히 위임만 하는 테스트의 경우 결과를 검증한다면 테스트가 중복되지 않을까 생각했었다.
    +따라서 중복된 테스트를 줄이기 위해 내부의 메서드를 호출하는지 검증하는 방법도 있다는 것을 알게 되었지만
    +안정적으로 결과를 테스트 하는 것이 더 좋은 방법인 것 같다.

    +

    테스트를 위한 getter 사용

    +

    테스트 용도로 도메인에 새로운 메서드가 생성되는 것은 좋지 못하다.
    +필요의 경우 생성해서 사용할 수 있지만, 기존에 있는 메서드들을 활용해보는 것이 더 좋은 방법이다.
    +이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

    +

    페어에게 배울 부분

    +

    질문이나 생각할 점이 있을 때 매우 깊게 고민하는 것 같았다.
    +생각을 정리한 후 자신의 의견을 명료하게 전달해주었다.
    +그렇기 때문에 지식을 효율적으로 습득한다.
    +난 생각을 잘 정리하지 않은 채로 내버려 둔 얕은 지식이 많은 것 같다. (이런 것도 아는 것이라고 할 수 있을까?)
    +앞으로 조금 더 머릿속에서 정리하고, 문제에 대해 깊게 고민하는 시간을 늘려야겠다.

    +

    개발에 열정을 가진 게 느껴진다.
    +나도 개발을 좋아하지만, 최근에는 의지가 약해졌었다.
    +열정이 가득한 사람을 만나니 나도 열정적인 사람이 되는 것 같다.

    +

    칭찬을 많이 해준다. 단순히 많이 해주는 것이 아니라, 진심을 담긴 칭찬을 해줬다.
    +칭찬은 고래도 춤추게 하던가?
    +그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

    +

    어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
    +이건 바로 배울 수 없지만.
    +나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

    ]]> + Woowahan Techcourse + Retrospective + + + <![CDATA[사다리 타기 미션 회고]]> + https://greeng00se.github.io/ladder-retrospective + https://greeng00se.github.io/ladder-retrospective + Sun, 26 Feb 2023 00:00:00 GMT + +

    1단계: https://github.com/woowacourse/java-ladder/pull/97
    +2단계: https://github.com/woowacourse/java-ladder/pull/234

    +

    사다리 타기

    +

    사다리 타기 미션에서는 우가와 페어가 매칭되었다.
    +이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

    +

    우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

    +

    2단계에서는 2가지 방법으로 구현해봤다.

    +
      +
    1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
    2. +
    3. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법
    4. +
    +

    Position 기준으로 사다리 게임을 진행하는 방법

    +

    사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
    +구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
    +또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

    + LadderGame + LadderGame --> Ladder + LadderGame --> Players + LadderGame --> Items - @Override - public void afterTestMethod(TestContext testContext) { - JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext); - List<String> truncateTableQueries = getTruncateTableQueries(jdbcTemplate); - truncateTables(jdbcTemplate, truncateTableQueries); - } + Ladder --> Line + Line --> LineStatus - private JdbcTemplate getJdbcTemplate(TestContext testContext) { - return testContext.getApplicationContext().getBean(JdbcTemplate.class); - } + LadderGame --> Position + Ladder --> Position + Items --> Position + Line --> Position + Players --> Position - private List<String> getTruncateTableQueries(JdbcTemplate jdbcTemplate) { - return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class); - } + LadderGame --> LadderGameResult + + Items --> Item + Players --> Player - private void truncateTables(JdbcTemplate jdbcTemplate, List<String> truncateTableQueries) { - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); - truncateTableQueries.forEach(jdbcTemplate::execute); - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); + LadderGameController --> InputView + LadderGameController --> OutputView +"> +
    public LadderGameResult play() {
    +    final Map<Player, Item> result = new LinkedHashMap<>();
    +    // 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
    +    for (Position position : Position.range(players.count())) {
    +        final Position resultPosition = ladder.play(position);
    +        result.put(players.get(position), items.get(resultPosition));
         }
    +    return new LadderGameResult(result);
     }
    -
     
    -

    Listener 등록

    -

    @TestExecutionListeners를 이용하여 사용자 정의 리스너를 등록할 수 있다.
    -mergeMode의 기본값은 REPLACE_DEFAULTS로 리스너가 이미 존재하는 경우 등록된 리스너로 변경된다.
    -MERGE_WITH_DEFAULTS로 설정한다면 Ordered 기준으로 순서가 결정된다.
    -이후 격리가 필요한 테스트들은 다음의 추상 클래스를 상속하여 사용하면 된다.

    -
    
    -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    -@TestExecutionListeners(
    -        value = DatabaseCleaner.class,
    -        mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
    -)
    -public abstract class AcceptanceTest {
    +

    Player에게 Ladder를 전달하여 게임을 진행하는 방법

    +

    Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
    +이 방법이 사다리 게임을 위해서 객체들이 긴밀하게 협력하고, 조금 더 책임의 분배가 잘 되어있다고 생각이 되었다.

    + +
    public LadderGameResult play() {
    +    // 참가자들에게 사다리를 전달해서 사다리에게 메시지를 보내도록 한다.
    +    final Map<Player, Position> playResult = players.play(ladder);
    +
    +    final Map<Player, Item> result = new LinkedHashMap<>();
    +    for (Player player : playResult.keySet()) {
    +        result.put(player, toItem(playResult.get(player)));
         }
    +    return new LadderGameResult(result);
     }
    -
     
    -

    참고 자료

    -

    The Spring TestExecutionListener, Baeldung
    -인수테스트에서 테스트 격리하기, 테코블
    -Eradicating Non-Determinism in Tests, martin fowler
    -@SpringBootTest의 테스트 격리시키기, MangKyu

    ]]> - test +

    부족했던 부분

    +

    유비쿼터스 언어에 시간을 들이기
    +유비쿼터스 언어를 정하는데 시간을 조금 더 들여야겠다고 생각했다.
    +사다리 타기의 실행 결과를 Item으로 짓다니.. 뭔가 만족스럽지 않다.
    +이전 미션과 마찬가지로, 명명하는 부분에서 부족함을 많이 느꼈다.

    +

    페어와 조금 더 친해지기
    +첫날은 페어와 친해지는 시간을 조금 더 가져야겠다고 생각했다.
    +우가랑 회고할 때 내가 시작하자마자 컨벤션 정하자고 해서 많이 당황스러웠다고 한다. 우가 미안.. 🥲

    +

    README를 조금 더 꼼꼼하게
    +이상하게 코딩에 집중하면 README를 업데이트하면서 같이 커밋 하는 걸 항상 까먹는다.
    +다음 미션에는 조금 더 신경 써야겠다.

    +

    좋은 질문을 생각하기
    +첫 PR때 리뷰어에게 질문을 남기지 못했다.
    +리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

    +

    PR 후에도 꼼꼼하게 확인하기
    +분명 알고 있는 부분이지만, 놓친 부분이 많은 것 같았다.
    +PR 하기 전에도 계속 확인을 했지만, 아무래도 IntelliJ에서 보니 코드에 익숙해져서 그런지 변경해야 할 부분이 잘 안보였다.
    +github pr에서는 전체 변경사항을 확인할 수 있으니 PR 후에도 꼭 확인해야겠다.

    +

    적극적으로 나의 의견을 말하기
    +의견을 적극적으로 내는 부분에 대해서 페어의 의견이 괜찮다고 생각하면 수용 후 개선을 하는 방향으로 진행을 했었는데, 조금 더 개선할 수 있는 방향이 있다면 나도 적극적으로 의견을 말해야겠다고 생각이 든다.
    +나도 설득하는 힘을 기르고, 페어도 좋은 방향을 알 수 있고, 결과물도 좋은 방향으로 나오지 않을까? (고민 들어주신 리뷰어 터틀🐢 감사합니다.)

    +

    새로 학습한 부분

    +

    객체의 생성 책임
    +Players가 Position을 생성하고 Player의 생성자에 넣어주었다. 하지만 이 부분에 대해서 생성 책임에 관련된 코멘트가 달렸다. +시간을 가지고 생각해 보니 Position을 가지고 있는 건 Player기 때문에 생성 책임을 Player가 담당하는 것이 좋다고 생각되었다.

    +

    생성 책임에 관한 패턴으로 GRASP의 Creator 패턴이 있는데 다음의 요소를 최대한 만족하는 클래스에 생성 책임을 할당하는 것이 좋다.

    +
      +
    • B가 A 객체를 포함 또는 참조한다.
    • +
    • B가 A 객체를 기록한다.
    • +
    • B가 A를 긴밀하게 사용한다.
    • +
    • B가 A의 초깃값을 가지고 있다.
    • +
    +

    실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

    +

    패키지 분리 기준
    +패키지 분리에 대한 나만의 기준이 아직 명확하지 않아 질문이 들어와도 명확하게 답변을 하지 못했다.
    +마지막 제출 전에 도메인 패키지 내부를 분리해 봤는데, 기준이 명확하지 않았기 때문에 좋지 않은 선택이었던 것 같다. +현재 진행하는 미션의 애플리케이션 크기가 그렇게 크지 않으니, domain 패키지에서 세부 패키지로 분리하지 않아도 될 것 같다.

    +

    사용하는 쪽에서 생각하기 & 예측가능한 코드 작성하기
    +Position에서 다음 위치나 이전 위치를 반환하는 메서드를 허용 범위(019)가 벗어난다면, 의미 없는 값이 들어간 Position을 반환하도록 했다.
    +이건 Position을 사용하는 입장을 고려하지 못한 코딩이었는데, 사용하는 입장에서는 0
    19의 값이 보장되어 있다고 생각할 것이기 때문이다.
    +따라서 hasNext, hasPrevious라는 이전 값, 이후 값이 범위 내에 있는지 확인하는 메서드를 추가하고, 기존의 값을 가져오는 메서드는 범위가 벗어나면 예외를 던지는 방향으로 해결하였다.

    +

    페어에게 배울 부분

    +

    밝은 기운을 가지고 있고 다른 사람들과 친화력이 좋은 것 같았다.
    +이번에 페어 할 때 컨디션 관리를 제대로 못해서 많이 미안했다. 다음에는 최상의 컨디션으로 페어를 준비해 봐야겠다.
    +그리고 우가랑 페어를 하고 나서, 나도 다른 사람들과 더 잘 지내봐야겠다는 생각이 들어 조금 더 용기를 내 잡담 중이다!

    +

    의견을 적극적으로 내줘서 페어프로그래밍 진행이 잘 되었다.
    +또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
    +페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

    +

    항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
    +웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

    ]]> + Woowahan Techcourse + Retrospective - <![CDATA[웹 애플리케이션 발전 과정]]> - https://greeng00se.github.io/web-application-evolution - https://greeng00se.github.io/web-application-evolution - Sat, 30 Sep 2023 00:00:00 GMT - - 웹 애플리케이션 발전 과정 -

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    -간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.
    -원래 회고에 작성하려고 했지만, 정리하다 보니 조금 길어져서 따로 분리했다.

    - -

    WWW(1989)

    -

    정적 페이지를 제공하는 웹 서버를 시작으로 동적 페이지가 필요했기 때문에 CGI가 등장했다.

    -

    CGI(1993)

    -

    CGI는 동적 콘텐츠를 제공하기 위한 규약으로, 해당 인터페이스를 구현한 스크립트를 이용해서 매 요청마다 프로세스를 실행시켜 정보를 반환하도록 한다. 하지만 매 요청마다 프로세스를 실행시키기 때문에 서버에 많은 부하가 발생할 수 있다. 따라서 이러한 단점을 극복하기 위해 나온 것이 Servlet이다.

    -

    Servlet(1996)

    -

    Servlet은 웹 서버에서 실행되는 자바 프로그램으로 HTTP를 이용하여 웹 클라이언트의 요청을 수신하고 응답한다. CGI와 다르게 매 요청마다 프로세스가 아닌 스레드를 생성하여 응답한다.
    -하지만 View 영역의 코드를 작성하기 위해 Servlet의 소스 코드를 알아야 하는 등 복잡도가 너무 높았다. 따라서 해당 문제를 해결하기 위해 JSP가 등장했다.

    -

    JSP(1999)

    -

    JSP는 HTML에 자바 코드를 작성하여 동적 웹 페이지를 생성하는 기술로, 유사한 기술로는 ASP, PHP가 있다.
    -JSP만 사용하여 프로그래밍한다면 Model 1, 아래 구성도와 같이 JSP가 View 영역만 담당한다면 Model 2라고 한다.

    - -

    MVC(2000)

    -

    위 JSP의 구성도를 보면 현재 MVC와 매우 유사한데, Govind Seshadri라는 사람이 JSP Model 2를 MVC 패턴으로 공식화를 제안했다.

    + <![CDATA[블랙잭 미션 회고]]> + https://greeng00se.github.io/blackjack-retrospective + https://greeng00se.github.io/blackjack-retrospective + Tue, 14 Mar 2023 00:00:00 GMT + +

    1단계: https://github.com/woowacourse/java-blackjack/pull/427
    +2단계: https://github.com/woowacourse/java-blackjack/pull/537

    +

    블랙잭

    +

    블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
    +이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

    +

    블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
    +후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

    +

    미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
    +"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

    +

    곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
    +중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
    +부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

    +

    이 부분에 대해 생각이 많아져서 전 리뷰어인 터틀🐢과도 대화를 나누었다.
    +터틀은 제어할 수 없는 부분보다 제어할 수 있는 부분(궁극적인 목표인 좋은 코드를 작성하는 것)에 집중해보라고 하셨다.

    +

    좋은 코드, 좋은 페어에 대한 부분을 일단 지속적으로 생각해봐야겠다.

    +

    부족했던 부분

    +

    페어 신경쓰기
    +이번 페어할 때 적극적으로 의견을 내보도록 했다. 그렇기에 너무 의견을 강하게 밀어붙인 느낌이 들어서 미안했다.
    +후추가 압박을 느꼈을 수도 있을 것 같다는 생각이 든다.
    +중간 중간 작은 회고를 진행해보는 것이 좋을까?

    +

    체력 관리
    +요즘 잘 못먹는 것 같다.
    +앞으로 살 날이 많은데 잘 챙겨먹고, 힘내야겠다.

    +

    중간 중간 돌아보기
    +이번 미션과 관련된 내용은 아니지만 우테코를 잘 활용 하고 있는지 생각을 해봐야겠다.
    +내가 우테코에 지원한 이유를 항상 잊지 않아야겠다.

    +

    새로 학습한 부분

    +

    상태 패턴
    +객체의 내부 상태에 따라 스스로 행동을 변경하도록 하는 패턴으로 if/else/switch와 같은 조건문을 효과적으로 제거할 수 있다.
    +블랙잭 미션을 진행하면서 상태 패턴에 대한 부분을 처음 적용해보았다.
    +처음 적용하기 전에는 별로라고 생각했는데, 생각보다 괜찮은 것 같다.

    +

    일관성, 가독성, 추상화
    +이번 리뷰어는 검프🍫 였다!
    +검프의 리뷰는 간결함에 관련된 내용이 많았다.
    +일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
    +읽기 좋고, 간결한 방향으로 코드를 작성하는 방법을 배운 것 같다.
    +코드를 바라보는 시점이 하나 늘어난 기분이다!(앞으로 적용하는 것은 나의 몫이지만)

    +

    페어에게 배울 부분

    +

    생각 정리
    +중간 중간 현재 상황에 대해 그림을 그리거나, 글을 적으면서 정리한다.
    +페어와 동일한 부분을 이해하고 있는지 확인한다.
    +진행하는데 매우 도움이 되었던 것 같다.
    +나도 다음 페어때부터 펜이랑 종이를 준비해야겠다.

    +

    가감없이 의견을 말해주는 부분
    +진행 상황에 대한 부분, 진행 속도, 지금 자신이 이해하고 있는 부분을 말해줘서 편했다.
    +회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

    +

    도메인 언어에 신경쓰는 부분
    +클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
    +요구사항 정리도 깔끔하게 잘하는 것 같다.

    +

    후추 최고 👍

    ]]>
    + Woowahan Techcourse + Retrospective +
    + + <![CDATA[일반적인 책임 할당을 위한 패턴]]> + https://greeng00se.github.io/grasp + https://greeng00se.github.io/grasp + Thu, 30 Mar 2023 00:00:00 GMT + + GRASP(General Responsibility Assignment Software Pattern) +

    크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

    +

    각 패턴마다 Solution과 Problem로 구성되어 있다.

    +

    정보 전문가 패턴(Information Expert)

    +

    Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

    +

    A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

    +

    정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

    +

    필요한 정보를 가진 객체들로 책임이 분산된다.

    +

    창조자 패턴(Creator)

    +

    Q: 누가 객체 A를 생성하는가?

    +

    A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

    +
      +
    • B가 A 객체를 포함 또는 참조한다.
    • +
    • B가 A 객체를 기록한다.
    • +
    • B가 A 객체를 긴밀하게 사용한다.
    • +
    • B가 A 객체의 초기값을 가지고 있다.
    • +
    +

    생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

    +

    낮은 결합도 패턴(Low Coupling)

    +

    Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

    +

    A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

    +
    +

    결합도(Coupling) +객체 사이의 의존성이 과한 경우 결합도가 높다고 말한다.

    +
    +
      +
    • 오브젝트 p.17
    • +
    +
    +
    +

    결합도를 낮춘다면 다음과 같은 이점이 있다.

    +
      +
    • 다른 구성 요소의 변화에 영향을 받지 않는다.
    • +
    • 재사용이 편리해진다.
    • +
    • 해당 클래스에 대한 이해가 쉬워진다. (의존하는 클래스가 적기 때문에)
    • +
    +

    높은 응집도 패턴(High Cohesion)

    +

    Q. 객체를 관리하기 쉽게 하려면 어떻게 해야 할까?

    +

    A. 높은 응집도를 유지할 수 있게 책임을 할당해야 한다.

    +
    +

    응집도(Cohesion) +연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도가 높다고 말한다.

    +
    +
      +
    • 오브젝트 p.26
    • +
    -

    I provide an in-depth look at how you can gain optimal separation of presentation from content by using the JSP Model 2 architecture. This model can also be seen as a server-side implementation of the popular Model-View-Controller (MVC) design pattern.
    -Govind Seshadri

    -

    이때 MVC 패턴이 처음 탄생한 것은 아니고, 서버 측 구현이라고 하는 것을 보니 MVC가 처음 등장한 건 아닌 것 같다.
    -해당 문서를 보면 MVC라는 용어의 등장은 1978년에 등장한 것으로 보인다.

    -

    Spring Framework(2003)

    -

    Spring은 복잡했던 J2EE을 대체하기 위해 2003년에 등장했다.
    -J2EE는 웹 기반의 엔터프라이즈 애플리케이션을 구축하기 위한 플랫폼으로 위에서 설명한 Servlet, JSP, EJB 등의 기술을 포함하고 있다.
    -하지만 이중 EJB라는 기술이 J2EE의 핵심 기술이었는데, 해당 기술이 매우 복잡했기 때문에 사용에 문제가 많았다고 한다.
    -2002년에 Rod Johnson이 EJB를 사용하지 않고 J2EE 애플리케이션을 구축하는 방법에 대해 저술한 Expert One-to-One J2EE Development라는 책을 발행했고, 출간 후 Juergen Hoeller, Yann Caroff가 Rod Johnson에게 오픈소스 제안을 하여 스프링이 탄생했다고 한다.

    -

    스프링은 엔터프라이즈 서비스 기능을 POJO에 제공하며, 이 덕분에 스프링을 사용하여 비즈니스 로직에 집중할 수 있다.

    -

    WebFlux 이전 Servlet 3.0(2009), 3.1(2013)

    -

    Tomcat의 NIO 동작 방식을 보면 Poller가 소켓 커넥션을 들고 있다가 처리가 가능할 때 스레드를 할당하는 식으로 처리를 한다. 하지만 할당 후 Servlet과 통신하는 부분은 블로킹 방식으로 요청이 끝날 때까지 스레드를 점유하고 있었고, 스레드 점유로 인해 요청이 max thread에 도달하면 요청을 처리할 수 없었다.
    -그래서 비동기 방식의 Servlet이 Servlet 3.0에 등장했다. 하지만 전통적인 I/O 방식을 사용하는 부분은 블로킹 방식으로 동작했다. Servlet 3.1에서 논블로킹 I/O가 추가되었지만, 많이 사용되지 않았다고 한다.

    -

    Spring WebFlux(2017)

    -

    적은 수의 스레드로 동시성을 처리하고, 적은 리소스로 확장이 가능한 논블로킹 방식의 웹 기술이 필요했고, 기존의 Servlet의 경우 비동기를 지원한다 해도 동기식 API들이 많이 남아있었기 때문에 이러한 Servlet에 영향을 받지 않는 기술이 필요했다. 또한 기존에 Netty와 같이 비동기, 논블로킹 방식 서버로 자리를 잘 잡은 서버를 위해 Spring WebFlux가 등장했다.
    -추가로 데이터 접근을 위해 사용하는 JDBC의 경우 Blocking API라, Spring Webflux에서는 R2DBC를 사용한다고 한다.

    -

    마치며

    -

    해당 정리 내용의 경우 Async, Non Blocking 관련된 내용을 깊게 공부한 적이 없어서 정확하지 않을 수 있다.
    -그래도 기술의 등장 배경이나 과정을 알고 있다면 조금 더 깊이 있는 학습에 도움이 된다고 생각한다.

    +

    변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

    +
      +
    • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
    • +
    • 유지보수가 쉬워진다.
    • +
    • 낮은 결합도 또한 지원한다.
    • +
    • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.
    • +
    +

    컨트롤러 패턴(Controller)

    +

    Q. 사용자의 요청을 처리하는 것은 누가 담당해야 하는가?

    +

    A. 사용자의 요청을 처리하는 Controller 객체를 만들어서 사용해야 한다.

    +

    어떤 서브시스템이 존재한다고 가정할 때

    +
      +
    • 직접적으로 객체에 접근하여 프로그램을 사용한다면 결합도가 상승한다.
    • +
    • 서브 시스템에 들어오는 요청을 처리해주는 컨트롤러가 있다면 사용하는 입장에서는 해당 컨트롤러만 알면 된다.
    • +
    • 만약 서브 시스템의 변경이 생겼을 때 외부에 미치는 영향도 줄어든다.
    • +
    +

    다형성 패턴(Polymorphism)

    +

    Q. 객체의 타입에 따라 행동이 바뀐다면 책임을 어떻게 할당해야 할까?

    +

    A. OOP가 지원하는 다형성을 적극적으로 활용한다. (인터페이스를 두고 행동에 대한 부분을 구현)

    +

    객체의 종류에 따라 분기하는 조건문이 아닌 다형성을 사용하는 것이 좋은 방법이다.

    +

    새로운 타입이 추가되었을 때 조건문을 사용한다면 기존의 조건문을 수정해야 하지만 다형성을 활용하면 쉽게 확장할 수 있다.

    +

    변경 보호 패턴(Protected Variations)

    +

    Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

    +

    A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

    +

    간접 참조 패턴(Indirection)

    +

    Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

    +

    A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

    +

    중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

    +

    중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

    +

    순수한 가공물 패턴(Pure Fabrication)

    +

    Q. 책임을 할당한 도메인 객체가 Low Coupling, High Cohesion, 재사용성 등의 목적을 위반한다면 어떻게 해야 할까?

    +

    A. 도메인 개념을 포함하지 않는 클래스를 하나 만들고 매우 응집된 책임을 할당할 수 있다.

    +

    행동을 추가할 때, 해당 책임을 수행할 도메인 개념이 존재하지 않는다면 도메인과 무관한 인공적인 객체를 만든다음 해당 객체에게 책임을 할당한다.

    +

    객체가 데이터베이스에 저장해야 할 값을 가지고 있다고, 정보 전문가 패턴을 적용하여 데이터베이스에 저장하라는 책임을 가지라고 하지 않는다.

    +

    예) 상점과 고객 클래스가 있고 서로 다른 통화를 사용하고 있다고 가정

    +
      +
    • 서로 다른 통화를 사용하고 있기 때문에 거래를 하려면 환전을 해야한다.
    • +
    • 두 클래스 다 환전에 대한 책임을 부여하기 애매하다면 환전을 책임하는 클래스를 추가하고 사용할 수 있다.
    • +

    참고 자료

    -

    웹 애플리케이션의 발전 과정, 구구 강의
    -Dynamic Content with CGI, Apache Tutorial
    -History of Spring and the Spring Framework, Spring
    -Understanding JavaServer Pages Model 2 architecture, Govind Seshadri
    -MVC, XEROX PARC
    -Expert One-to-One J2EE Development, Rod Johnson
    -배달의민족 최전방 시스템! ‘가게노출 시스템’을 소개합니다, 배달의민족
    -Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu -WebFlux Overview, Spring -Spring WebFlux와 Armeria를 이용하여 Microservice에 필요한 Reactive + RPC 동시에 잡기, Naver D2
    -Spring WebFlux란 무엇일까

    ]]>
    - web application +

    오브젝트 5장. 책임 할당하기, 조영호

    +

    Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman

    +

    GRASP, 한빛 네트워크

    ]]> + GRASP + OOP
    - <![CDATA[비동기 예외 로깅]]> - https://greeng00se.github.io/log-async-exception - https://greeng00se.github.io/log-async-exception - Mon, 18 Sep 2023 00:00:00 GMT - - 문제 상황 -

    현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
    -확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

    -

    비동기 예외 발생시 로깅 설정

    -

    스프링 4.1 부터 제공되는 AsyncUncaughtExceptionHandler의 경우 반환 타입이 void인 비동기 메서드를 예외 처리하기 쉽도록 도와준다.

    -

    따라서 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 핸들링하는 클래스를 생성했다.
    -기존의 동기 예외 처리의 경우 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다.
    -비동기 예외 처리도 마찬가지로 MDC의 정보를 가져와서 로그를 출력하도록 설정했다.

    -
    @Slf4j
    -public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    -
    -    private static final String LOG_FORMAT = "[%s] %s";
    -
    -    @Override
    -    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
    -        log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
    +            <![CDATA[체스 미션 회고]]>
    +            https://greeng00se.github.io/chess-retrospective
    +            https://greeng00se.github.io/chess-retrospective
    +            Fri, 31 Mar 2023 00:00:00 GMT
    +            
    +            

    1, 2단계: https://github.com/woowacourse/java-chess/pull/441
    +3, 4단계: https://github.com/woowacourse/java-chess/pull/529

    +

    체스

    +

    체스 미션에는 가비와 페어가 매칭되었다!
    +체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
    +하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
    +미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

    +

    가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
    +최종적으로 결정한 부분은 다음과 같다.

    +

    각 기물의 이동 가능여부
    +Rank와 File은 각각 위치값을 가지고 있고, 값의 차이를 이용해서 각 기물의 이동 가능 여부를 계산했다.
    +직선 → Rank와 File 차이 중 하나가 0이어야 한다.
    +대각선 → Rank와 File 차이의 절대값이 같아야 한다. ex) abs(-2) == abs(2)
    +나이트 → 차이의 절대값이 하나는 2 나머지 하나는 1이어야 한다.

    +

    도착 칸의 기물 여부
    +아군 → 이동이 불가능하다.
    +적군 → 이동이 가능하다. 적군을 잡는다.

    +

    중간에 기물 존재 여부
    +이동 경로에 기물이 존재하면 안된다.

    +

    데이터베이스 사용
    +체스 미션은 특별하게 데이터베이스와 연결하는 부분이 있었다.
    +체스 게임의 상태를 다음의 두가지 방법으로 정할 수 있다고 생각했다.

    +
      +
    • 기물 전체를 저장하는 방법
    • +
    • 기보를 저장하고 게임을 불러와 기보대로 이동시키는 방법
    • +
    +

    기물이 이동할 때마다 값을 저장하고 싶었고, 기보를 저장하는 방법을 선택했다.
    +기물 전체를 저장하지 않은 이유는 다음과 같다.

    +
      +
    • 턴과 같은 부가적인 요소를 저장해야 한다.
    • +
    • 이동을 할 때 기물이 잡히는 경우 update 쿼리(이동 기물)와 delete(잡힌 기물) 2개의 쿼리를 날려야 한다.
    • +
    • 현재 구조에서 도메인의 변경이 크게(초기 상태를 구성하는 부분) 일어나야 한다.
    • +
    +

    정리하자면 기물 전체 저장과 기보 저장은 다음과 차이가 있다.
    +보드저장: 초기상태에서 32개의 Insert 쿼리(기물의 위치) + 기물 이동 시 움직임 변경(잡히는 경우 2개의 쿼리)
    +기보저장: 초기상태 애플리케이션에서 구성 + 저장된 기보를 select 쿼리로 조회해서 사용(1회) + insert 쿼리(이동 당 1회)

    +

    추가로 기보저장이 구현도 더욱 간단하다. 👍

    +

    부가적인 부분

    +

    리뷰어인 찰리🍫가 동시에 여러 게임이 진행된다면 어떨지? 에 대한 코멘트를 남겨주셔서 다양한 시도를 해봤다.

    +
      +
    • 누누의 도움으로 ConnectionPool 구현
    • +
    • ThreadLocal 사용해서 쓰레드 별 세션 관리
    • +
    • 실제로 애플리케이션 내에서 체스 게임이 진행되는 Board를 ConcurrentHashMap으로 저장(사실 이 부분은 현재 구조에서 필요없지만 2명이 서로 게임하는 경우를 생각해서 넣어보았다.)
    • +
    +

    두 명이 서로 같은 방에 입장하여 게임을 진행한다면 출력하는 부분이 까다로워질 것 같다고 예상되어(Board에 옵저버 패턴을 사용해야되나?) 해볼 엄두가 나지 않았다.

    +

    부족했던 부분

    +

    꼼꼼하게 코드를 작성하지 못한 부분
    +DB 관련 부분을 꼼꼼하게 코딩을 하지 못했다.
    +도메인 로직에만 집중하다보니 정적 중요한 DB의 코드의 예외처리, 빈 값을 반환 하는 부분을 꼼꼼하게 처리하지 못했다.
    +하지만 찰리의 꼼꼼한 리뷰로 DB부분과 나만의 JdbcTemplate을 깔끔하게 구현할 수 있었다.

    +

    시간에 대한 부담감
    +초반에는 여유롭지만 제출 마감에 가까워질 수록 사람이 급해지는 것 같다.
    +다음 페어프로그래밍할 땐 속도를 조절하고, 마음에 여유를 가져야겠다.

    +

    새로 학습한 부분

    +

    DAO 중복 제거

    +

    프롤로그에 을 작성했다.
    +DAO를 작성하는데 try-catch-resources와 여러 코드가 중복되서 제거하고싶었다.
    +템플릿 콜백 패턴으로 깔끔하게 중복을 제거할 수 있었다.👍

    +

    페어에게 배울 부분

    +

    페어 생각하기
    +가비는 누구보다 페어를 생각하고, 배려해주는 페어였다.
    +중간 중간 당 떨어질까봐 걱정도 해주고, 나의 컨디션도 확인해줬다!

    +

    미션 몰입하기
    +최근에 미션에 잘 몰입하지 못했다.
    +가비는 페어를 진행할 때 미션에 대한 몰입도가 매우 좋았다.
    +집에가서도 체스 이동에 대한 로직을 어떻게 구현할 지 생각한 뒤 꼼꼼해서 정리해서 나에게 보내주었다.
    +덕분에 나도 가비의 생각을 알 수 있어서 미션을 진행하는데 가속도가 붙은 것 같다.
    +또한 미션을 잘 마무리하고 싶은 마음이 전달되서 그런지 나도 덩달아 열심히 미션을 할 수 있었다.😄

    +

    솔직함
    +먼저 회고하자고 말 걸어줘서 정말 고마웠다고 표현해주는 부분
    +모르는게 있으면 솔직하게 말해주는 부분
    +나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
    +솔직함은 페어할 때 중요한 부분인 것 같다.

    +

    마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

    ]]>
    + Woowahan Techcourse + Retrospective + + + <![CDATA[우아한테크코스 레벨 1 회고]]> + https://greeng00se.github.io/woowacourse-level1-retrospective + https://greeng00se.github.io/woowacourse-level1-retrospective + Sat, 01 Apr 2023 00:00:00 GMT + + 레벨 1이 끝났다.
    +우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
    +혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
    +하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

    +

    Keep

    +

    나만의 루틴 만들기

    +

    스스로가 외부의 영향을 많이 받는다고 생각한다.
    +최대한 꾸준히 할 수 있는 시간을 만드는 것이 중요하다고 생각한다.

    +

    매일 8시에 도착하여 아침에 해야 할 일을 정리하거나, 우선순위에 따라 처리하고
    +소화능력이 부족하기 때문에 점심은 도시락(그래봤자 계란2개)을 준비하고
    +항상 똑같은 컨디션을 유지하기 위해 항상 6시에 집에 간다.
    +이제 바빠질 테니 일찍 집에 가는 일은 어쩔 수 없이 줄어들겠지만😢

    +

    선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

    +

    크루들과 친하게 지내기

    +

    10명 정도의 크루의 닉네임을 외우고 친하게 지낸다면 성공적이라고 생각했었다.
    +하다 보니 더 많은 크루들의 닉네임을 외운 것 같다.
    +앞으로도 크루들과 친하게 지내고 아무 때나 말을 걸 수 있는 크루가 늘어나길 :)

    +

    글쓰기

    +

    글을 잘 쓰는 편은 아니지만 꾸준히 작성하려고 노력했다.
    +매 미션마다 회고를 작성하니 생각도 정리되고 개선점도 찾을 수 있어서 좋았다.

    +

    우아한테크코스에는 레벨마다 글쓰기를 진행하는데, 운이 좋게 글쓰기 상을 받았다.
    +사실 겉으로 드러내지 않았지만 꼭 받아보고 싶었다.
    +글쓰기 조원, 투표해 준 크루들에게 너무 감사하다.

    +

    코드 리뷰 스터디

    +

    누누, 주노, 다즐, 말랑, 박스터, 오잉, 깃짱와 코드 리뷰 스터디를 진행했다.
    +과연 도움이 될까 생각했지만 결과적으로는 코드 리뷰를 하면서 성장을 많이 한 것 같다.
    +투자한 시간 대비 가성비가 좋은 활동이었다.
    +누누가 스터디장인데 과연 꾸준히 이어나가려나?

    +

    레벨 인터뷰

    +

    인터뷰할 때 많이 떨지 않아서 좋았다.
    +남들 앞에서 이야기를 하거나, 면접을 보면 항상 엄청 떨어서 걱정했는데
    +기술적인 질문을 받았을 때 떨지 않고 잘 대답할 수 있었다.
    +우아한테크코스 생활을 하면서 다른 크루가 질문했을 때, 최대한 이해하기 쉽게 설명하려고 했던 경험이 도움이 된 것 같다.
    +이후 레벨 인터뷰를 진행할 때 다음과 같은 부분을 고려하면 더 좋을 것 같다.

    +
      +
    • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
    • +
    • 두괄식 표현
    • +
    • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
    • +
    • 설명할 수 있을만큼 시간 충분히 가지기
    • +
    • 인터뷰어의 질문 의도를 명확히 이해하지 못했다면 의도 다시 물어보기
    • +
    • 끝맺는 부분 연습하기(자신감 있게)
    • +
    • 기술적인 집착가지기
    • +
    • 기술적인 부분을 꼼꼼히 준비했으면 협업 관련 질문도 준비하기
    • +
    +

    Problem

    +

    페어프로그래밍

    +

    우아한테크코스를 진행하면서 가장 어려운 활동 중 하나라고 생각한다.
    +페어는 매번 바뀌고, 미션의 복잡도도 증가하기 때문인 것 같다.
    +소통 능력, 시간관리가 부족했고, 만족스럽지 않았다.
    +하지만 페어를 진행하고, 회고를 하다 보니 나만의 노하우가 쌓이는 느낌이다.
    +레벨 2에서는 부족했던 부분을 개선하여 함께하고 싶은 페어가 되고 싶다.

    +

    집중하는 시간⏱️ 부족

    +

    레벨 1을 진행하면서 집중하는 시간이 많이 부족했다.
    +이른 아침과 오후에 개인적으로 집중할 수 있는 공간을 예약해서 온전히 나만의 시간을 가져야겠다.

    +

    Try

    +

    허브🌿와의 티타임?

    +

    소프트 스킬을 늘릴 방법을 생각하다가 대화를 나누지 못한 다른 크루들과 깜짝 커피챗을 하면 어떨까 생각했다.
    +예를 들어 잡담방에 저와 커피챗 하실 분 :) 하면서 올릴 수 있을 것 같다.
    +참여하는 사람이 있을지, 안 좋게 보는 게 아닐지 걱정되지만 그래도 재밌을 것 같다.
    +저랑 허브티 한잔 하실래요?

    +

    기술적인 부분

    +

    우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
    +시간의 여유가 될 때 책을 조금씩 읽어야겠다.
    +블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

    +

    레벨 1을 마무리하며

    +

    시간이 빠르게 흘러갔다.
    +타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
    +또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

    ]]>
    + Woowahan Techcourse + Retrospective +
    + + <![CDATA[커스텀 JdbcTemplate 만들기]]> + https://greeng00se.github.io/custom-jdbc-template + https://greeng00se.github.io/custom-jdbc-template + Sun, 02 Apr 2023 00:00:00 GMT + + 체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
    +이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
    +템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

    +

    기존 코드

    +
    public class User {
    +    private final int id;
    +    private final String name;
    +
    +    public User(final int id, final String name) {
    +        this.id = id;
    +        this.name = name;
         }
    -}
    -
    -

    AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
    -getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

    -
    @EnableAsync
    -@Configuration
    -public class AsyncConfig implements AsyncConfigurer {
     
    -    @Override
    -    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    -        return new AsyncExceptionHandler();
    +    public int getId() {
    +        return id;
         }
    -}
    -
    -

    이제 비동기 상황에서 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아 처리한다.

    -

    MDC 정보 연동 문제

    -

    비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없는 문제가 발생했다.

    -

    ./mdc-null.png

    -

    스프링 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

    -
    public class MdcTaskDecorator implements TaskDecorator {
     
    -    @Override
    -    public Runnable decorate(final Runnable runnable) {
    -        Map<String, String> threadContext = MDC.getCopyOfContextMap();
    -        return () -> {
    -            MDC.setContextMap(threadContext);
    -            runnable.run();
    -        };
    +    public String getName() {
    +        return name;
         }
     }
    -
    -

    생성한 Decorator 클래스를 설정 파일에 등록해 준다.

    -
    @RequiredArgsConstructor
    -@EnableAsync
    -@Configuration
    -public class AsyncConfig implements AsyncConfigurer {
    +
    ]]> + JDBC + Java - <![CDATA[경로 이미지 생성하기 - 구현]]> - https://greeng00se.github.io/route-image-implementation - https://greeng00se.github.io/route-image-implementation - Wed, 02 Aug 2023 00:00:00 GMT - - 개요 -

    여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
    -경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

    -

    구현 결과

    -

    ./result.png

    -

    예시 데이터는 다음과 같다.
    -서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

    -
    List<Double> x = List.of(
    -        126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
    -        126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
    -);
    -List<Double> y = List.of(
    -        37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
    -        37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
    -);
    -List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
    -List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);
    -
    -

    IMAGE_SIZE & ROUTE_SIZE

    -
    private static final int IMAGE_SIZE = 800;
    -private static final int ROUTE_SIZE = 600;
    -
    -

    코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
    -IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
    -ROUTE_SIZE의 경우 상하좌우 100px 만큼의 간격을 위해 존재한다.
    -따라서 실제 경로 이미지의 크기는 600 * 600 사이즈로 생성된다.

    -

    ./600.png

    -

    사이즈 변경의 이유

    -

    255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

    -

    주요 클래스

    -

    요약

    -
    클래스명설명특이사항
    Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
    CoordinatesCoordinate의 일급 컬렉션-
    Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
    PositionsPositions의 일급 컬렉션-
    RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
    RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
    RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
    BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
    Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
    -

    의존관계

    - -

    Coordinates(위도, 경도의 일급 컬렉션)

    -

    List<Double> 2개(위도, 경도)인 형태로 관리하는 방법이 있었지만, 위치 점을 여러개 찍는 부분에서 로직이 복잡해 질 것 같아서 Coordinate(x, y)와 일급 컬렉션인 Coordinates로 관리하기로 했다.
    -Coordinates 클래스에는 다음 두 개의 인터페이스가 존재한다.

    -
      -
    • calculatePositions: 경로 이미지의 크기를 받아 실제 이미지 생성시 사용될 Positions를 반환
    • -
    • indexOf: 다른 Coordinates를 받아 동일한 위치점에 해당하는 인덱스를 반환하는
    • -
    -

    Positions 계산 로직은 다음과 같다.
    -위도, 경도 각각에 대한 부분을 이미지 생성시 필요한 값으로 변환한다.

    -
    // 호출
    -// List<Integer> xPositions = toPositions(xValues, maxDifference, routeImageSize);
    -// List<Integer> yPositions = toPositions(yValues, maxDifference, routeImageSize);
    -
    -private List<Integer> toPositions(List<Double> values, Double maxDifference, Integer routeImageSize) {
    -    Double minValue = Collections.min(values);
    -    return values.stream()
    -            .map(value -> normalizeCoordinate(value, maxDifference, minValue))
    -            .map(value -> mapToPosition(value, routeImageSize))
    -            .toList();
    -}
    -
    -private double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {
    -    return (coordinate - minValue) / maxDifference;
    -}
    -
    -private int mapToPosition(Double coordinate, Integer routeImageSize) {
    -    return (int) (coordinate * routeImageSize);
    +            <![CDATA[자바 클래스 파일 구조]]>
    +            https://greeng00se.github.io/java-class-file
    +            https://greeng00se.github.io/java-class-file
    +            Mon, 03 Apr 2023 00:00:00 GMT
    +            
    +            클래스 파일
    +

    자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
    +컴파일된 클래스파일은 어떤 구조로 되어있을까?

    +

    클래스 파일의 데이터 형식

    +

    8비트 바이트의 스트림으로 구성된다.
    +16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
    +멀티바이트의 경우 항상 big endian 순서로 저장된다.

    +

    u1 → unsigned 1byte
    +u2 → unsigned 2byte
    +u4 → unsigned 4byte

    +

    클래스 파일 구조

    +
    ClassFile {
    +    u4             magic;
    +    u2             minor_version;
    +    u2             major_version;
    +    u2             constant_pool_count;
    +    cp_info        constant_pool[constant_pool_count-1];
    +    u2             access_flags;
    +    u2             this_class;
    +    u2             super_class;
    +    u2             interfaces_count;
    +    u2             interfaces[interfaces_count];
    +    u2             fields_count;
    +    field_info     fields[fields_count];
    +    u2             methods_count;
    +    method_info    methods[methods_count];
    +    u2             attributes_count;
    +    attribute_info attributes[attributes_count];
     }
     
    -

    위도로 예시든 내용이다.

    -
      -
    1. Collections.min(values) → 위도 리스트의 최소값을 구한다.
    2. -
    3. normalizeCoordinate → 각각의 위도 값에서 최소값을 빼고 0 ~ 1 사이 값으로 변환 후 위경도의 최대 차이로 나눈다.
    4. -
    5. mapToPosition → 그래프 크기를 받아 0 ~ 1 사이 값을 실제 이미지를 위한 위치값으로 변환한다.
    6. -
    -

    Positions(실제 이미지 생성에 사용할 위치)

    -

    Positions 클래스에는 다음 다섯 개의 인터페이스가 존재한다.

    +

    매직넘버

    +

    모든 클래스 파일은 0xCAFEBABE라는 매직넘버로 시작한다.
    +보통 매직넘버는 파일 종류를 식별하는 용도로 사용된다.

    +

    클래스 파일 포맷 버전

    +

    클래스 파일 버전 값은 클래스로더의 호환성 보장을 위해 꼭 필요한 값이다.

      -
    • align: 이미지 사이즈와 경로 이미지 사이즈를 받아 Position 값들을 중앙 정렬한다.
    • -
    • getPositionsByIndexes: 인덱스 리스트를 받아 입력받은 인덱스에 해당하는 값들을 반환한다.
    • -
    • size: 크기를 반환한다.
    • -
    • xPositions: x 값들을 반환한다.
    • -
    • yPositions: y 값들을 반환한다.
    • +
    • Java 17 버전으로 빌드한다면 class version 61 ex) 00 00 00 3D
    -

    중앙 정렬 로직은 다음과 같다.

    -
    public Positions align(int imageSize, int routeSize) {
    -    int xOffset = calculateOffset(Position::x, imageSize);
    -    int yOffset = calculateOffset(Position::y, imageSize);
    -
    -    return items.stream()
    -            .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))
    -            .collect(collectingAndThen(toList(), Positions::new));
    -}
    -
    -private int calculateOffset(ToIntFunction<Position> positionToInteger, int imageSize) {
    -    List<Integer> positions = items.stream()
    -            .mapToInt(positionToInteger)
    -            .boxed()
    -            .toList();
    -
    -    int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;
    -    return imageSize / 2 - midValue;
    -}
    -
    -

    상하좌우 여백을 동일하게 주기 위해서 offset 값을 구해서 x, y 값에 각각 더하는 형태로 중앙 정렬을 수행했다.
    -BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

    -

    ./800.png

    -

    따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

    -

    x 값 → 계산한 offset 그대로 더한다.
    -y 값 → imageSize(800)에서 y + offset 값을 뺀다.

    -

    RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

    -

    BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
    -그림을 그리기 위해 설정한 상수들이 존재한다.

    -
    // RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
    -// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
    -// 이를 RGBA라고 부른다.
    -private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
    -// 배경 투명색
    -private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
    -// 경로를 위한 STROKE
    -private static final int LINE_STROKE_WIDTH = 7;
    -private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    -// 위치 점을 위한 STROKE
    -private static final int POINT_STROKE_WIDTH = 20;
    -private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    -// 안티앨리어싱 등 화질 개선을 위한 설정
    -private static final Map<Object, Object> renderingHints = Map.of(
    -        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
    -        RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
    -        RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
    -);
    -
    -

    RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

    +

    호환되지 않는 버전의 클래스 파일을 로딩하려고 하는 경우 런타임에 UnsupportedClassVersionError 예외가 발생한다.

    +

    class file format major versions

    +
    Java SEReleasedMajorSupported majors
    8March 20145245 .. 52
    9September 20175345 .. 53
    10March 20185445 .. 54
    11September 20185545 .. 55
    12March 20195645 .. 56
    13September 20195745 .. 57
    14March 20205845 .. 58
    15September 20205945 .. 59
    16March 20216045 .. 60
    17September 20216145 .. 61
    +

    상수 풀

    +

    2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
    +클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
    +JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

    +

    액세스 플래그

    +

    클래스, 인터페이스와 같은 파일의 속성을 표시한다.
    +예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.

      -
    • drawLine: 선을 그린다.
    • -
    • drawPoint: 점을 찍는다.
    • -
    • dispose: 자원 할당을 해제한다.
    • +
    • 계산은 다음과 같이 이루어진다. ACC_PUBLIC xor ACC_INTERFACE xor ACC_ABSTRACT
    -

    dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

    -

    이미지 생성 Flow

    -

    1. 이미지 생성 준비

    - -

    2. 선 그리기 요청

    - -

    3. 위치 점 그리기 요청

    - -

    4. 업로드 요청

    - -

    전체 Flow

    -]]>
    - image - awt - - - <![CDATA[경로 이미지 생성하기 - 파이썬]]> - https://greeng00se.github.io/route-image-python - https://greeng00se.github.io/route-image-python - Mon, 31 Jul 2023 00:00:00 GMT - - 개요 -

    이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

    -

    사용 기술

    -

    언어: Python 3.10
    -이미지 생성: matplotlib
    -서비스: AWS Lambda, AWS API Gateway
    -이미지 저장 및 URL: AWS S3, AWS CloudFront

    -

    플로우는 다음과 같다.

    - -

    요구사항

    -

    ./route.png

    -

    우측 상단의 경로 이미지를 생성하려고 한다.
    -경로 이미지 생성에 대한 요구사항은 다음과 같다.

    -
      -
    • 위도, 경도로 이루어진 배열을 입력받는다.
    • -
    • 이미지 생성
    • -
    • 선과 점 표현
    • -
    • 투명한 배경색
    • -
    • 위경도 차이가 크든 작든 제공하는 이미지 내에 경로가 다 포함되어 있어야 한다.
    • -
    -

    이미지 출력 방식

    -
      -
    1. 위경도를 처리한 값으로 직접 경로를 그린 다음 이미지 형태로 저장
    2. -
    3. 플롯을 그려주는 라이브러리 사용하여 이미지 형태로 저장
    4. -
    -

    이미지 출력 방식의 경우 1번과 2번을 고민했었다.
    -파이썬으로는 플롯을 그려주는 라이브러리인 matplotlib을 사용했다.

    -

    로컬에서 기능 구현

    -
    import time
    -
    -import matplotlib.pyplot as plt
    -
    -
    -def draw(point):
    -    start = time.time()
    -    x, y = zip(*point)
    -    pixel_x, pixel_y = convert_to_pixel_values(x, y)
    -    draw_lines(pixel_x, pixel_y)
    -    end = time.time()
    -    print(end - start)
    -    
    -def convert_to_pixel_values(x, y):
    -    max_diff = max(max(x) - min(x), max(y) - min(y))
    -    return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)
    -
    -
    -def scale_to_pixel_values(points, max_diff):
    -    min_value = min(points)
    -    scaled_coordinates = [(p - min_value) / max_diff for p in points]
    -    return scaled_coordinates
    -
    -
    -def draw_lines(x, y):
    -    figure = plt.gcf()
    -    figure.set_size_inches(5, 5)
    -    plt.plot(x, y, c = 'w',linewidth=5)
    -    plt.scatter(x[3],y[3], c = 'w', s = 125)
    -    plt.axis('off')
    -    plt.savefig('name.png', transparent=True, format='png')
    -
    -point = [
    -    [126.96352960597338, 37.590841000217125],
    -    [126.96987292787792, 37.58435564234159],
    -    [126.98128481452298, 37.58594375113966],
    -    [126.99360339342958, 37.58248524741927],
    -    [126.99867565340067, 37.56778118088622],
    -    [127.001935378366117, 37.55985240444085],
    -    [126.9831048919687, 37.548030119488665],
    -    [126.97189273528845, 37.5119879225856],
    -    [127.02689859997221, 37.48488593333883]
    -]
    -
    -draw(point)
    -
    -

    생성 결과는 아래와 같다. (예시를 위해 검은색으로 출력)

    -

    ./routeImage.png

    -

    AWS Lambda

    -

    썸네일 생성 서버를 따로 두기는 기능 대비 비용이 너무 클 것이라고 생각했다.
    -따라서 서버리스로 파일을 처리했다.
    -추가로 s3 접근은 boto3를 사용했다.

    -

    람다 S3 접근을 위한 IAM 생성

    -

    AmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy 두가지를 추가해서 Lambda 전용 역할을 만들어 사용했다.

    -

    람다 배포용 코드

    -

    기술 구현 가능 여부를 확인할 땐 위치 점을 찍는 기능을 람다에 배포하지 않았다.

    -
    
    -import io
    -import uuid
    -
    -import boto3
    -import matplotlib.pyplot as plt
    -
    -PIXEL = 255
    -BUCKET_NAME = 'image-plot'
    -S3 = 's3'
    -
    -def lambda_handler(event, context):
    -    x = event['x']
    -    y = event['y']
    -    image_name = str(uuid.uuid4())
    -
    -    img_data = draw(x, y)
    -    s3 = boto3.client(S3)
    -    s3.put_object(Body=img_data.getvalue(), ContentType='image/png', Bucket=BUCKET_NAME, Key=image_name)
    -    url = f'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}'
    -
    -    return {
    -        'statusCode': 200,
    -        'body': url
    -    }
    -
    -def draw(x, y):
    -    pixel_x, pixel_y = convert_to_pixel_values(x, y)
    -    img_data = draw_lines(pixel_x, pixel_y)
    -    plt.close()
    -    return img_data
    -
    -def convert_to_pixel_values(x, y):
    -    max_diff = max(max(x) - min(x), max(y) - min(y))
    -    return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)
    -
    -def scale_to_pixel_values(points, max_diff):
    -    min_value = min(points)
    -    scaled_coordinates = [(p - min_value) / max_diff for p in points]
    -    pixel_values = [int(p * PIXEL) for p in scaled_coordinates]
    -    return pixel_values
    -
    -def draw_lines(x, y):
    -    plt.plot(x, y, 'k-', linewidth=10)
    -    plt.axis('off')
    -    img_data = io.BytesIO()
    -    plt.savefig(img_data, transparent=True, format='png')
    -    img_data.seek(0)
    -    return img_data
    -
    -
    -

    Layer 추가를 위한 zip 파일 생성

    -

    matplotlib의 경우 외부 라이브러리기 때문에 따로 Layer를 추가해야 한다.
    -zip 파일을 만들어서 업로드해야한다.
    -이때 python의 Lambda 런타임에 대한 계층 경로는 python이다.
    -따라서 압축한 zip 파일은 다음과 같은 구조를 띄어야 한다.

    -
    pillow.zip
    -│ python/PIL
    -└ python/Pillow-5.3.0.dist-info
    -
    -

    Ubuntu 기준 다음 명령어를 입력하여 생성을 진행했다.

    -
    sudo apt update
    -sudo apt install zip
    -sudo apt install python3-pip
    -
    -mkdir python
    -pip3 install matplotlib -t python # pip3 install 설치할_패키지 -t 설치_경로
    -zip -r my_layer.zip python # zip -r 압축_파일명 압축_파일이_존재하는_경로
    -
    -

    No module named 'numpy.core._multiarray_umath' 에러

    -

    Layer 추가 후 람다 실행 시 발생한 에러였다.
    -처음에 mac에서 zip 파일을 생성해서 업로드했는데 해당 문제가 발생했다.
    -이는 lambda가 돌아가는 동일한 환경에서 layer를 위한 zip 파일을 만들지 않아서 발생하는 문제다.
    -간단하게 ec2 인스턴스를 하나 만들어서 따로 Layer를 생성하면 문제가 발생하지 않는다.

    -

    적정기술에 대한 생각

    -

    프로젝트에 Lambda와 Python을 사용하려고 했지만 아쉽게도 반려당했다.
    -AWS Lambda를 사용하는 것은 인스턴스에 해당 코드를 배포하는 것보다 더 효율적인 방법일 수 있다.
    -하지만 현재 프로젝트에서 가용 가능한 자원, 기술의 난이도, 사용하는 팀원을 고려한다면 Lambda는 적정기술이 아닐 수 있다.
    -따라서 해당 이미지 생성기를 어떻게 적용할지 조금 더 고려를 해야 될 것으로 보인다.

    -

    최종적으로 Java AWT를 사용하기로 결정했다.

    -

    참고 자료

    -

    AWS Lambda
    -Lambda Layer
    -Python Lambda 함수에 대한 .zip 파일 아카이브 작업
    -No module named 'numpy.core._multiarray_umath'
    -사례별로 알아본 안전한 S3 사용 가이드

    ]]>
    - Image - Python +

    공식문서에 들어가면 각 플래그에 대한 설명 + 플래그 설정시 동시에 설정되면 안되는 플래그와 같은 설명이 자세하게 나와있다.

    +

    Class access and property modifiers

    +
    Flag NameValueInterpretation
    ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
    ACC_FINAL0x0010Declared final; no subclasses allowed.
    ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
    ACC_INTERFACE0x0200Is an interface, not a class.
    ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
    ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
    ACC_ANNOTATION0x2000Declared as an annotation type.
    ACC_ENUM0x4000Declared as an enum type.
    ACC_MODULE0x8000Is a module, not a class or interface.
    +

    this_class

    +

    클래스명과 같은 이름을 표현하는 값으로, 상수 풀에서 클래스명과 일치하는 항목의 인덱스를 참조한다.
    +해당 인덱스의 항목은 CONSTANT_Class_infoclass 형식의 값이어야 한다.

    +

    super_class

    +

    상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
    +아무것도 상속하지 않는 클래스의 경우 java.lang.Object의 인덱스 값이 들어있다.

    +

    interface, field, method

    +

    각각의 개수와, 정보에 대한 값이 들어있다.
    +interface, field, method를 표시하는 방법이 각각 다르고, 접근자에 대한 플래그도 각각 다르다.

    +

    attributes

    +

    해당 클래스 파일에서 사용하는 추가 정보의 모음이다. 예) 소스파일명
    +정해진 클래스 파일의 구조를 확장하는 역할을 한다.

    +

    클래스 파일 확인하면서 사용한 툴

    +

    IntelliJ plugin - BinEd
    +IntelliJ plugin - jclasslib Bytecode Viewer

    +

    참고 자료

    +

    2장 JVM 이야기, 자바 최적화
    +Class file in Java, File Format
    +java se11 Class 파일 형식, Oracle
    +java se17 Class 파일 형식, Oracle

    ]]> + Java + Class
    - <![CDATA[Mockito 이용해서 static 메서드 모킹하기]]> - https://greeng00se.github.io/mock-static-method - https://greeng00se.github.io/mock-static-method - Sun, 30 Jul 2023 00:00:00 GMT - - 개요 -

    정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
    -하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

    -

    예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

    -

    프로젝트를 진행하며 ImageIo.write 메서드가 호출되는 지 검증이 필요했다.
    -해당 static 메서드를 호출하는 부분을 따로 RouteImageUploader 클래스로 최대한 분리했다.
    -이미지 저장 기능 자체가 외부로 나가는 상호작용이고, 호출 횟수를 검사하는데는 mock을 사용하는게 적절하다고 판단했다.

    -
    public void upload(BufferedImage bufferedImage) {
    -    File file = new File(파일경로);
    -    try {
    -        ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);
    -    } catch (IOException e) {
    -        throw new DrawException(IMAGE_SAVE_FAIL);
    -    }
    -}
    -
    -

    Mocking static methods

    -

    Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
    -mockStatic을 사용하면 MockedStatic<T>이 반환되는데 사용 후 꼭 close를 해줘야 한다.

    -

    JUnit의 @BeforeAll로 설정하고 @AfterAll 메서드로 종료하는 방법도 있지만 MockedStatic<T>의 상위 인터페이스인 ScopedMock이 AutoCloseable을 구현하고 있기에 try-with-resources를 사용하는 방법이 더욱 좋은 것 같다.

    -
    // given
    -BufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);
    -RouteImageUploader routeImageUploader = new RouteImageUploader();
    -
    -// expect
    -try (MockedStatic<ImageIO> imageIO = Mockito.mockStatic(ImageIO.class)) {
    -    routeImageUploader.upload(bufferedImage);
    -    imageIO.verify(
    -            () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),
    -            times(1)
    -    );
    -}
    -
    -

    마치며

    -

    정적 메서드를 모킹하는 것은 안티패턴이으로 적절한 추상화를 이용해 테스트 하기 좋은 코드를 만드는 연습을 하자.
    -하지만 추상화를 하면 할 수록 코드의 복잡도는 증가한다.
    -항상 상황을 고려하고 간결함을 포기할 만큼 중요한 부분인지 적절한 트레이드오프를 고려하자.

    + <![CDATA[테스트 대역]]> + https://greeng00se.github.io/test-double + https://greeng00se.github.io/test-double + Tue, 04 Apr 2023 00:00:00 GMT + + 테스트 대역이란? +

    모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
    +Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

    +

    테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
    +외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

    +

    테스트 대역의 타입 계층 구조

    + +

    더미(Dummy)

    +

    가장 단순하고, 원시적인 유형의 테스트 대역이다.
    +기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
    +만약 메서드가 무언가 반환을 해야하는 경우 0, null과 같은 값을 반환한다.

    +

    스텁(Stub)

    +

    시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
    +이를 통해 특정 조건에서 메서드가 예상한대로 동작하는지 확인할 수 있다.

    +

    스파이(Spy)

    +

    스텁과 유사하지만 호출 여부를 기록하거나 호출할 때 전달한 인자값을 기록할 수 있다.
    +예) 메일 전송 기능을 가진 객체를 테스트 대역으로 구현했을 때 메일 전송 횟수를 기록한다.

    +

    목, 모의 객체(Mock)

    +

    목은 더미, 스텁, 스파이를 포함한다.
    +호출 시 사전에 정의된 결과를 반환하고, 예상치 못한 호출이 있을 경우 예외를 던질 수 있다.
    +또한 호출에 대한 검증을 할 수 있다.

    +

    가짜(Fake)

    +

    DOC와 동일한 기능을 제공하지만, 더욱 간단한 방법으로 구현된 것이다.
    +예) 실제 데이터베이스와 유사하게 동작하는 가짜 객체를 만들어 테스트할 수 있다.

    +

    의존 구성 요소, DOC를 테스트 더블로 대체할 수 있다.
    +테스트 더블은 DOC와 동일한 API를 제공해야 한다.

    +

    상호작용에 따른 목과 스텁 구분

    +

    단위 테스트 p.149 에서는 테스트 대역을 크게 목과 스텁으로 구분한다.
    +목은 SUT와 관련된 상호작용을 모방하고 검사하는 반면, 스텁은 단순 모방만 한다.

    +
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색
    +

    테스트 대상 시스템
    +테스트를 하려는 대상

    참고 자료

    -

    Mocking static methods
    -Mockito mock static methods
    -Enable mocking static methods in Mockito

    ]]>
    - Mockito - static +

    소프트웨어 장인 정신 이야기 - 3장 고급 테스트 주도 개발, 로버트 C. 마틴
    +단위 테스트 - 5장 목과 테스트 취약성, 블라디미르 코리코프
    +테스트 주도 개발 시작하기 - 7장 대역, 최범균
    +테스트 더블, Martin Fowler
    +테스트 관련 용어 정리, Johngrib
    +Test Double, Gerard Meszaros

    ]]>
    + Test + Mock
    - <![CDATA[경로 이미지 생성하기 - 기술 선택]]> - https://greeng00se.github.io/route-image-intro - https://greeng00se.github.io/route-image-intro - Thu, 27 Jul 2023 00:00:00 GMT - - ./route.png

    -

    이미지 생성의 책임

    -

    위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
    -따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

    -

    해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

    -
      -
    • 이미지 생성
    • -
    • 선과 점 표현
    • -
    • 투명한 배경색
    • -
    -

    현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

    -

    고려한 기술

    -

    백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

    -
      -
    • Python의 Matplotlib
    • -
    • AWT(Abstract Window Toolkit) [최종 선택]
    • -
    • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
    • -
    • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)
    • -
    -

    Python & Matplotlib

    -

    데이터 시각화 라이브러리
    -이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

    -
      -
    • 코드가 간단해서 유지 보수성이 좋다.
    • -
    • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
    • -
    • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.
    • -
    -

    Java AWT 이외의 라이브러리

    -

    Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

    -
    라이브러리설명제외 이유
    SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
    JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
    simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
    matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
    -

    Java & AWT(Abstract Window Toolkit)

    -

    그래픽과 이미지를 그리기 위한 도구
    -이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

    + <![CDATA[트랜잭션과 격리수준]]> + https://greeng00se.github.io/transaction-and-isolation + https://greeng00se.github.io/transaction-and-isolation + Wed, 05 Apr 2023 00:00:00 GMT + + 트랜잭션(Transaction) +

    데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
    +트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
    +논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

    +

    트랜잭션의 속성(ACID)

    +

    원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
    +일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
    +격리성(Isolation): 각각의 트랜잭션은 독립적이라 서로에게 영향을 주지 않아야 한다.
    +지속성(Durability): 트랜잭션이 성공적으로 완료된다면 영구적으로 결과에 반영되어야 한다.

    +

    트랜잭션 주의사항

    +

    트랜잭션은 꼭 필요한 최소의 코드에만 적용하는 것이 좋다.(트랜잭션의 범위를 최소화하라)
    +구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

    +

    데이터의 일관성과 안전성을 보장하기 위해 배제해야 한다.
    +네트워크 작업을 트랜잭션 내부에 포함한다면 다음과 같은 문제가 발생할 수 있다.

      +
    • 네트워크 작업이 중간에 실패할 가능성(안전성 X)
    • +
    • 통신으로 인해 데이터가 변경될 수 있는 부분(일관성 X)
    • +
    +

    격리 수준(Isolation level)

    +

    여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 데이터의 조회 및 변경을 허용할지 결정하는 것을 말한다.
    +격리 수준이 높아질 수록 동시 처리 성능이 떨어지는 것이 일반적이지만, SERIALIZABLE이 아니라면 크게 성능의 저하가 발생하지 않는다.

    +

    READ UNCOMMITTED

    +

    각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다.
    +더티 리드 현상이 발생하기 때문에 정합성의 문제가 많은 격리 수준이다.
    +MySQL 사용시 최소 READ COMMITTED 이상의 격리 수준 사용을 권장한다.

    + +

    READ COMMITTED

    +

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    +오라클 DBMS에서 기본으로 사용되는 격리 수준이다.
    +REPEATABLE READ가 보장되지 않기 때문에 NON-REPEATABLE READ 문제가 발생한다.

    + +

    REPEATABLE READ

    +

    트랜잭션이 시작되기 전에 COMMIT이 완료된 내용에 대해서만 조회할 수 있다.
    +MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준이다.
    +MVCC를 이용해 언두(Undo) 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장한다.
    +동일한 결과를 보장하는 방법은 다음과 같다.

      -
    • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
    • -
    • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
    • -
    • 추가적인 api 호출을 하지 않아도 된다.
    • +
    • 모든 InnoDB 트랜잭션은 순차적으로 증가하는 고유한 트랜잭션 번호를 가진다.
    • +
    • Undo 영역에 백업된 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함되어있다.
    • +
    • Undo 영역의 백업된 데이터는 스토리지 엔진이 불필요하다고 판단하는 경우 삭제된다.
    • +
    • REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 가장 오래된 트랜잭션 번호보다 앞선 Undo 영역의 데이터는 삭제하지 않는다.
    -

    기술 선택

    -

    AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
    -하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

    -

    유지 보수

    -

    AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
    -따라서 다음과 같은 방법으로 공유하기로 했다.

    -
      -
    1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
    2. -
    3. AWT를 사용한 부분을 문서화하여 공유한다.
    4. -
    -

    레벨 3를 마무리하며 내용 추가

    -

    기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
    -AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

    ]]>
    - image - awt +

    InnoDB에서는 갭 락과 넥스트 키 락을 이용하여 팬텀 리드 현상을 방지한다.

    + +

    갭 락: 레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    +넥스트 키 락: 레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.

    +

    동시성을 제어하는 방법 중 하나로 하나의 레코드에 대해 여러 개의 버전이 동시에 관리되는 것이다.

      +
    • PostgreSQL은 다중 버전의 데이터를 저장하는 것으로 MVCC를 구현한다.
    • +
    • Oracle, InnoDB는 Undo log를 이용해 이 기능을 구현한다.(최신 버전의 데이터만 DB에 저장)
    • +

    잠금을 사용하지 않는 읽관된 읽기를 제공하는 것이 목적이다.

    +

    SERIALIZABLE

    +

    트랜잭션을 순차적으로 진행시키는 격리 수준이고 따라서 동시 처리 성능도 다른 격리 수준보다 떨어진다.
    +트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 접근할 수 없고 단순한 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야만 한다.
    +InnoDB에서는 팬텀 리드 현상이 REPEATABLE READ 격리 수준에서 발생하지 않기 때문에 굳이 사용할 필요는 없다.

    +

    격리 수준에 따른 부정합 문제

    +

    격리 수준에 따라 더티 리드, 반복 가능하지 않은 조회, 팬텀 리드 문제가 발생한다.

    +
    격리 수준 / 부정합 문제더티 리드반복 가능하지 않은 조회팬텀 리드
    READ UNCOMMITTEDOOO
    READ COMMITTEDXOO
    REPEATABLE READXXO(InnoDB는 X)
    SERIALIZABLEXXX
    +

    더티 리드(Dirty read)

    +

    어떤 트랜잭션에서 처리한 작업이 완료되지 않았어도 다른 트랜잭션에서 볼 수 있는 현상
    +트랜잭션 격리 수준이 READ UNCOMMITTED일 때 발생한다.
    +예) B가 레코드를 추가하고 커밋을 하지 않았지만, A가 해당 레코드를 조회할 수 있는 경우

    +

    반복 가능하지 않은 조회(Non-repeatable read)

    +

    한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 그 값이 다른 현상
    +예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

    + +

    팬텀 리드(Phantom read, Phantom row)

    +

    한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
    +예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

    + +

    참고 자료

    +

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    +Isolation Level, MySQL

    ]]>
    + DataBase + Transaction + Isolation
    - <![CDATA[자바 17, 스프링 6.0, 스프링 부트 3.1]]> - https://greeng00se.github.io/java-spring-springboot - https://greeng00se.github.io/java-spring-springboot - Mon, 24 Jul 2023 00:00:00 GMT - - 자바 17, 스프링 6.0, 스프링 부트 3.1 -

    팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
    -2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

    -

    자바 변경 사항

    -

    우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
    -따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

    -

    Switch Expressions(Java 14)

    -

    Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

    -
    enum RESULT {
    -    WIN, LOSE, DRAW
    -}
    -
    -RESULT result = RESULT.WIN;
    -
    -int prize = switch (result) {
    -    case WIN -> 10_000_000;
    -    case LOSE, DRAW -> 5_000_000;
    -	default -> 0;
    -};
    -
    -

    주요 특징은 다음과 같다.

    + <![CDATA[MySQL 엔진의 잠금]]> + https://greeng00se.github.io/mysql-lock + https://greeng00se.github.io/mysql-lock + Thu, 06 Apr 2023 00:00:00 GMT + + MySQL 엔진의 잠금 +

    MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
    +MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

    +

    글로벌 락(Global lock)

    +

    MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

      -
    • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
    • -
    • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
    • -
    • break 문이 필요 없다.
    • -
    • default 블록을 통해 기본 값을 지정할 수 있다.
    • +
    • 영향을 미치는 범위는 해당 서버 전체이다.
    • +
    • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.
    -

    Text Block(Java 15)

    -

    Java 15에는 새로운 문자열 표현방식이 추가되었다.
    -긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

    -
    @Repository
    -public interface PostRepository extends JpaRepository<Post, Long> {
    -    @Query("""
    -        SELECT p FROM Post p
    -        WHERE p.title LIKE %:keyword%
    -        OR p.content LIKE %:keyword%
    -        """)
    -    List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
    -}
    +

    한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
    +데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
    +InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

    +
    -- GLOBAL LOCK
    +FLUSH TABLES WITH READ LOCK;
    +-- UNLOCK
    +UNLOCK TABLES;
    +
    +-- BACKUP LOCK
    +LOCK INSTANCE FOR BACKUP;
    +-- UNLOCK
    +UNLOCK INSTANCE;
    +
    +

    MySQL 5.5 버전 이전의 기본 스토리지 엔진이다.
    +트랜잭션을 지원하지 않고, SELECT 작업 속도가 빠르다.

    +

    테이블 락(Table lock)

    +

    개별 테이블 단위로 설정되는 잠금이다.
    +명시적 또는 묵시적으로 특정 테이블의 락을 획득할 수 있다.
    +묵시적 락은 MyISAM이나 MEMORY 테이블에 데이터를 변경하는 쿼리를 실행하면 발생한다.
    +InnoDB 테이블에는 DML 쿼리는 무시되고 DDL 일 경우에만 묵시적으로 락을 획득한다.

    +
    -- TABLE LOCK
    +LOCK TABLES table_name [ READ | WRITE ]
    +
    +-- UNLOCK
    +UNLOCK TABLES;
    +
    +

    네임드 락(Named lock)

    +

    임의의 문자열에 대한 잠금을 설정할 수 있는 잠금으로 유저 레벨 락으로도 불린다.
    +여러 스레드나 프로세스가 동일한 데이터를 수정하려는 경우, 동시에 수정하지 못하도록 보호할 수 있다.

    +
    -- aGVyYg== 라는 문자열에 대한 잠금 획득, 이미 잠금을 사용중인 경우 1초 동안만 대기
    +SELECT GET_LOCK('aGVyYg==', 1);
    +
    +-- 문자열에 대한 잠금이 설정되어 있는지 확인한다.
    +SELECT IS_FREE_LOCK('aGVyYg==');
    +
    +-- 문자열에 대한 잠금을 해제한다.
    +SELECT RELEASE_LOCK('aGVyYg==');
    +
    +-- 위 3개 함수 모두 정상적으로 락을 획득하거나 해제한 경우에 1을, 아니면 0을 반환한다.
    +
    +-- 모든 문자열에 대한 잠금을 해제한다. 해제된 잠금의 개수를 반환한다.
    +SELECT RELEASE_ALL_LOCKS();
    +
    +

    메타데이터 락(Metadata lock)

    +

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    +명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    +보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    +
    -- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
    +-- 아래 구문 실행 시 메타데이터 락을 자동으로 획득한다.
    +RENAME TABLE rank TO rank_backup, rank_new TO rank;
     
    -

    NPE 메시지(Java 15)

    -
    String name = null;
    -name.chars();
    -
    -/** 
    -# before
    -java.lang.NullPointerException
    -	at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)
    -
    -# after
    -Cannot invoke "String.chars()" because "name" is null
    -java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
    -*/
    -
    -

    Record(Java 16)

    -

    Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
    -Record를 선언하는 경우 접근자, 생성자, equals & hashcode, toString이 제공된다.
    -데이터 전송 용도로 적합해 보인다.

    -
    public record PostDto(String title, String content) {
    -}
    -
    -

    추가적인 변경사항

    -

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    -

    스프링, 스프링 부트 변경 사항

    -

    스프링과 스프링 부트에도 많은 변경 사항이 있었다.
    -따라서 필요해보이는 몇개 정도만 정리했다.

    -

    스프링 요구사항

    -

    Java 17, Jakarta EE 9 이상이어야 한다.

    -

    네임스페이스 변경

    -

    Jakarta EE 9가 적용되면서 네임스페이스도 전반적으로 javax -> jakarta로 변경되었다.

    -

    PathPatternParser - trailing slash 허용하지 않음

    -

    6.0 이전의 경우 기본 설정 기준으로 @GetMapping("/hello")@GetMapping("/hello/")가 동일했다.
    -6.0 이후의 PathPatternParser가 기본으로 사용되고, /hello/hello/는 서로 다른 URL로 매칭된다.

    -
    -

    PathPatternParser used by default (with the ability to opt into PathMatcher).

    -
    -

    HTTP interface client

    -

    자바 인터페이스와 어노테이션을 이용하여 HTTP 요청을 위한 서비스를 정의할 수 있는 방법이 추가되었다.
    -자세한 내용은 토비님의 강의를 참고하면 좋을 것 같다.

    -

    스프링 부트 최소 요구사항

    -

    Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6
    -이외에도 서드파티들의 최신 릴리즈 버전을 사용함으로, 문제가 발생하는 경우 해당 버전에 맞는 릴리즈 노트를 참고할 수 있을 것 같다.

    참고 자료

    -

    어느 월급쟁이개발자 의 스프링 부트 따라잡기
    -자바 9-16 주요 특징 복습하기
    -Java EE에서 Jakarta EE로의 전환
    -Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩
    -What's New in Spring Framework 6.x
    -Spring Boot 3.0 Release Notes
    -Spring Boot 3.1 Release Notes

    ]]> - Java - Spring Boot - Spring +

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    +MySQL의 User Level Lock를 활용한다면?, gywndi
    +Locking Functions, MySQL 5.7 Reference
    +Locking Functions, MySQL 8.0 Reference

    ]]> + DataBase + Lock + MySQL - <![CDATA[웹소켓]]> - https://greeng00se.github.io/websocket - https://greeng00se.github.io/websocket - Mon, 26 Jun 2023 00:00:00 GMT - - 웹소켓 -

    단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
    -웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

    -

    웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

    -

    웹소켓 등장 배경

    -

    웹소켓이 등장하기 이전, 실시간성을 보장하기 위해 Polling, Long polling, Streaming 같은 기술을 사용했어야 했다.
    -이는 실시간성이나 양방향성을 만족시키지 못했고, HTTP를 이용하기 때문에 과도한 오버헤드가 발생했다.

    -

    Polling: 주기적으로 서버에 요청을 보내 수신할 정보가 있는지 확인하는 방법

      -
    • 서버에서 보낼 내용이 없어도 클라이언트는 알 수 없다.
    • -
    • 계속해서 요청을 보내 확인을 해야하기 때문에 서버에 불필요한 부하를 주어야 한다.
    • -

    Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

      -
    • 폴링 방식보다 서버에 적은 부하를 줄 수 있지만, 요청의 주기가 짧으면 폴링과 차이가 없어진다.
    • -

    Streaming: 클라이언트가 request를 보내면 커넥션을 맺고, 이 커넥션을 유지하면서 서버가 계속 데이터를 보내는 방법

      -
    • 클라이언트가 서버에 요청을 하고 싶다면 새로운 커넥션을 맺어야 한다.
    • -
    -

    웹소켓의 동작

    - -

    1. Upgrade 요청

    -

    WebSocket 프로토콜로 전환하는 HTTP 요청을 보낸다.
    -이는 HTTP와 같이 80, 443 포트를 사용한다.
    -웹소켓으로 전환하기 위해서는 Upgrade: websocket, Connection: Upgrade 헤더가 필요하다.
    -Sec-WebSocket-Key는 서버에서 Sec-WebSocket-Accept를 계산하여 응답하고 이 값이 예상한 값과 다르면 연결이 수립되지 않는다.
    -Sec-WebSocket-Protocol의 경우 서브프로토콜의 목록으로 서버 측에서는 해당 목록 중 하나를 선택하여 반환해야 한다.
    -만약 서버측에서 여러 개 지원이 가능한 경우 지원 가능한 프로토콜 중 첫번째 프로토콜을 클라이언트측으로 보낸다.

    -
    GET /chats HTTP/1.1
    -Host: localhost:8080
    -Upgrade: websocket
    -Connection: Upgrade
    -Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
    -Sec-WebSocket-Protocol: v10.stomp, v11.stomp
    -Sec-WebSocket-Version: 13
    -Origin: http://localhost:8080
    +            <![CDATA[InnoDB 스토리지 엔진의 잠금]]>
    +            https://greeng00se.github.io/innodb-lock
    +            https://greeng00se.github.io/innodb-lock
    +            Fri, 07 Apr 2023 00:00:00 GMT
    +            
    +            InnoDB 스토리지 엔진의 잠금
    +

    MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
    +보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

    +

    동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
    +InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

    +

    트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

    +

    트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
    +일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

    +

    Shared & Exclusive Locks

    +

    InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

    +

    공유 잠금(S, shared lock)

    +

    데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
    +다른 트랜잭션에서 읽기가 가능하지만, 쓰기는 불가능하다.
    +예) SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;

    +

    배타적 잠금(X, exclusive lock)

    +

    데이터 변경을 위한 락, 쓰기 잠금(write lock)으로도 불린다.
    +락을 건 트랜잭션만이 해당 데이터에 접근 가능하다. 다른 트랜잭션의 경우 읽기, 쓰기가 불가능하다.
    +예) SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

    +

    Intention Locks

    +

    InnoDB는 로우 단위 잠금과 테이블 잠금의 공존을 위해 인텍션 잠금을 지원한다.
    +테이블에 있는 로우에 대해서 나중에 요청되는 것이 어떤 형태의 잠금인지 가리키기 위해 사용된다.
    +기본적으로 로우 단위 잠금을 수행하기 전에 인텐션 잠금을 먼저 획득한다.
    +인텐션 락은 기본적으로 충돌을 방지하고 데드락을 방지하는 역할을 한다.

    +

    인텐션 공유 잠금(IS, intention shared lock)

    +

    트랜잭션이 테이블의 개별 로우에 대한 공유 잠금을 수행하는 것을 의미한다.

    +

    인텐션 배타적 잠금(IX, intention exclusive lock)

    +

    트랜잭션이 테이블의 개별 로우에 대한 배타적 잠금을 수행하는 것을 의미한다.

    +

    ** 잠금간의 호환성 **

    +
    XIXSIS
    XConflictConflictConflictConflict
    IXConflictCompatibleConflictCompatible
    SConflictConflictCompatibleCompatible
    ISConflictCompatibleCompatibleCompatible
    +

    Record Locks

    +

    레코드 자체만을 잠그는 락이다.
    +InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다.

    +

    Gap Locks

    +

    레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    +레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하고, 넥스트 키 락의 일부로 사용된다.

    +

    Next-Key Locks

    +

    레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.
    +REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하기 위한 잠금이다.

    +

    AUTO-INC Locks

    +

    AUTO_INCREMENT 칼림이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 한다.
    +InnoDB 는 내부적으로 AUTO-INC 락이라고 하는 테이블 수준의 잠금을 사용한다.
    +트랜잭션과 관계 없이 INSERTREPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 해제된다.

    +

    잠금 예시

    +
    -- 레코드는 id 기준 10, 20, 30, 40, 50이 있다고 가정
    +-- Record Locks: 10에 대해 락이 걸린다.
    +SELECT * FROM table_name where id = 10 for update;
    +
    +-- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다.
    +SELECT * FROM table_name where id > 100 for update;
    +
    +-- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다.
    +SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;
     
    -

    2. Switching Protocols

    -

    서버는 101 Switching Protocols 응답을 반환한다.
    -Sec-WebSocket-Accept은 Sec-WebSocket-Key 뒤에 258EAFA5-E914-47DA-95CA-C5AB0DC85B11를 붙이고 SHA1로 해싱 후 Base64로 인코딩하여 반환한다.
    -이는 서버 웹소켓 프로토콜의 지원 여부를 클라이언트에게 명확히 알리기 위해 존재한다.

    -
    HTTP/1.1 101 Switching Protocols 
    -Upgrade: websocket
    -Connection: Upgrade
    -Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
    -Sec-WebSocket-Protocol: v10.stomp
    -
    -

    3. 통신 후 종료

    -

    연결이 수립되면 웹소켓 프레임 단위로 양방향 통신을 한다.
    -연결 종료를 원하는 경우 클라이언트, 서버 모두 연결 종료를 요청할 수 있다.

    -

    참고 자료

    -

    https://datatracker.ietf.org/doc/html/rfc6455
    -https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
    -https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
    -https://docs.spring.io/spring-framework/reference/web/websocket.html

    ]]>
    - WebSocket +

    참고 자료

    +

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    +Optimistic and Pessimistic record locking, IBM
    +MySQL Innodb Locks, cecil1018
    +MySQL 8.0 InnoDB Locks, MySQL
    +Locks Set by Different SQL Statements in InnoDB, MySQL

    ]]> + DataBase + Lock + InnoDB - <![CDATA[Docusaurus]]> - https://greeng00se.github.io/docusaurus - https://greeng00se.github.io/docusaurus - Sun, 18 Jun 2023 00:00:00 GMT - - 팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

    -

    설치

    -

    공식 홈페이지에 들어가서 최신 버전을 설치한다.

    -
    yarn create docusaurus
    -
    -

    배포

    -

    배포 안내 문서
    -netlify나 vercel 같은 서버리스 플랫폼을 추천하고 있고, 간단하고, 빠른 시간 안에 배포를 할 수 있다.
    -이 글에서는 github pages를 이용해서 배포하는 방법을 설명한다.

    -

    레포지토리 생성

    -

    github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
    -이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

    -

    설정 파일 수정

    -
    module.exports = {
    -  // ...
    -  url: 'https://greeng00se.github.io',
    -  baseUrl: '/',
    -  projectName: 'greeng00se.github.io',
    -  organizationName: 'greeng00se',
    -  trailingSlash: false,
    -  // ...
    -};
    -
    -

    토큰 설정

    -

    github action을 위해 배포용 토큰을 하나 생성하여 생성한 레포지토리에 Repository secrets으로 설정한다.
    -이 글에서는 토큰을 클래식 방식으로 생성했고 스코프는 [repo, user, workflow] 을 설정했다.

    -

    github

    -

    브랜치 생성

    -

    github에서 gh-pages 브랜치를 하나 생성한다.
    -repository -> settings -> pages -> branch에서 생성한 gh-pages로 브랜치를 변경한다.
    -설정한 브랜치가 배포 브랜치가 되며, 해당 브랜치에 있는 파일들을 이용해서 정적 웹사이트를 제공한다.

    -

    워크플로 작성

    -

    Docusaurus 2.0 기준 Node.js 16.14 이상의 버전을 사용해야 합니다.
    -배포시에는 Repository secrets으로 설정한 DEPLOY_TOKEN 을 이용합니다.

    -
    name: blog
    -
    -on:
    -  push:
    -    branches: [main]
    -
    -jobs:
    -  deploy:
    -    name: Deploy to GitHub Pages
    -    runs-on: ubuntu-latest
    -    steps:
    -      - uses: actions/checkout@v2
    -      - uses: actions/setup-node@v3
    -        with:
    -          node-version: 18
    -          cache: yarn
    -
    -      - name: Install dependencies
    -        run: yarn install --frozen-lockfile
    -      - name: Build website
    -        run: yarn build
    -
    -      - name: Deploy to GitHub Pages
    -        uses: peaceiris/actions-gh-pages@v3
    -        with:
    -          github_token: ${{ secrets.DEPLOY_TOKEN }}
    -          publish_dir: ./build
    -          user_name: github-actions[bot]
    -          user_email: 41898282+github-actions[bot]@users.noreply.github.com
    -
    -

    댓글 기능

    -

    giscus를 이용하여 댓글 기능을 추가한다.

    -

    giscus 설정

    -
      -
    1. 공개 저장소여야 한다.
    2. -
    3. giscus 앱이 설치되어 있어야 한다.
    4. -
    5. Discussions 기능이 해당 저장소에서 활성화되어 있어야 한다.
    6. -
    -

    자세한 내용은 giscus를 확인하자.

    -

    docusaurus 설정

    -

    swizzling을 이용하여 컴포넌트를 감싼다.
    -기존에 게시물을 giscus가 포함된 리액트 컴포넌트로 감싸는 형태가 된다.
    -아래 명령어를 이용하여 BlogPostItem을 추출할 수 있다.

    -
    yarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap
    -
    -

    명령어를 입력하면 /src/theme/BlogPostItem/index.js 위치에 파일이 생성된다.
    -파일의 내용을 아래와 같이 수정하고, 이때 setAttribute 부분은 적절하게 자신의 giscus 설정을 이용한다.

    -
    import OriginalBlogPostItem from "@theme-original/BlogPostItem";
    -import React, { useEffect, useRef } from "react";
    -// @ts-expect-error internal code
    -import { useColorMode } from "@docusaurus/theme-common";
    -import { useBlogPost } from "@docusaurus/theme-common/internal";
    -
    -const giscusSelector = "iframe.giscus-frame";
    -
    -function BlogPostItem(props) {
    -  const { colorMode } = useColorMode();
    -  const { isBlogPostPage } = useBlogPost();
    -  const giscusTheme = colorMode === "dark" ? "dark" : "light";
    -  const containerRef = useRef(null);
    -
    -  useEffect(() => {
    -    if (!isBlogPostPage) return;
    -
    -    const giscusEl = containerRef.current.querySelector(giscusSelector);
    -
    -    const createGiscusEl = () => {
    -      const script = document.createElement("script");
    -
    -      script.src = "https://giscus.app/client.js";
    -      script.setAttribute("data-repo", "teco-chat/teco-chat.github.io");
    -      script.setAttribute("data-repo-id", "R_kgDOJZ5j0Q");
    -      script.setAttribute("data-category", "Announcements");
    -      script.setAttribute("data-category-id", "DIC_kwDOJZ5j0c4CXS_Q");
    -      script.setAttribute("data-mapping", "pathname");
    -      script.setAttribute("data-strict", "0");
    -      script.setAttribute("data-reactions-enabled", "1");
    -      script.setAttribute("data-emit-metadata", "0");
    -      script.setAttribute("data-input-position", "bottom");
    -      script.setAttribute("data-theme", giscusTheme);
    -      script.setAttribute("data-lang", "ko");
    -      script.crossOrigin = "anonymous";
    -      script.async = true;
    -      
    -      containerRef.current.appendChild(script);
    -    };
    -
    -    const postThemeMessage = () => {
    -      const message = {
    -        setConfig: {
    -          theme: giscusTheme,
    -        }
    -      };
    -
    -      giscusEl.contentWindow.postMessage({ giscus: message }, "https://giscus.app");
    -    };
    -
    -    giscusEl ? postThemeMessage() : createGiscusEl();
    -  }, [giscusTheme]);
    -
    -  return (
    -    <>
    -      <OriginalBlogPostItem {...props} />
    -      {isBlogPostPage && <div ref={containerRef} />}
    -    </>
    -  );
    -}
    -
    -export default BlogPostItem;
    -
    -

    알고리아 설정 및 직접 관리하기

    -

    알고리아를 사용하면 검색 기능을 추가할 수 있다.
    -유료 플랜이나 netlify를 사용하는 경우 크롤러를 따로 제공해 주는 것 같다.

    -

    무료 플랜은 직접 인덱스를 수집하는 방법과, docsearch를 이용하는 방법이 있다.
    -docsearch에 등록한다면 일주일에 한 번씩 크롤링이 진행된다.
    -이 글에서는 직접 인덱스를 수집하는 방법을 사용한다.

    + <![CDATA[[책] 상자 밖에 있는 사람]]> + https://greeng00se.github.io/book-leadership-and-self-deception + https://greeng00se.github.io/book-leadership-and-self-deception + Sat, 08 Apr 2023 00:00:00 GMT + + 책 정보 +
    +

    상자 밖에 있는 사람
    +아빈저연구소

    +
    +

    자기기만과 자기배반

    +

    책에서는 자기기만과 자기배반에 대한 내용을 다룬다.

      -
    • 직접 인덱스 수집
    • -
    • 설정 파일
    • +
    • 자기기만: 자신의 문제를 인정하지 않는 것
    • +
    • 자기배반: 다른 사람을 위해 무언가 해야만 한다는 생각을 반하는 행위
    -

    알고리아 애플리케이션 생성 및 키 확인

    -

    회원가입을 하고 새로운 애플리케이션 생성을 누른다.
    -생성을 다 마치면 다음과 같이 api 키를 확인할 수 있다.

    -

    algolia

    -

    키 생성

    -

    직접 인덱스를 수집하기 위한 키를 생성한다.
    -addObject, editSettings, deleteIndex acl(접근 제어 목록)이 있으면 된다.

    -

    key

    -

    .env 파일 생성

    -

    프로젝트 폴더 상단에 .env 파일을 생성한다.

    -
    APPLICATION_ID=MVIU5UEMOM
    -API_KEY=인덱스_생성용_키
    -
    -

    config 파일 생성

    -

    마찬가지로 최상단에 config.json 파일을 생성한다. -설정 파일은 해당 링크를 참고한다.
    -또는 Docusaurus의 설정 파일을 참고한다.

    -
    {
    -  "index_name": "teco",
    -  "start_urls": [
    -    "https://teco-chat.github.io/"
    -  ],
    -  "sitemap_urls": [
    -    "https://teco-chat.github.io/sitemap.xml"
    -  ],
    -  "sitemap_alternate_links": true,
    -  "stop_urls": [
    -    "/tests"
    -  ],
    -  "selectors": {
    -    "lvl0": {
    -      "selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",
    -      "type": "xpath",
    -      "global": true,
    -      "default_value": "Documentation"
    -    },
    -    "lvl1": "header h1",
    -    "lvl2": "article h2",
    -    "lvl3": "article h3",
    -    "lvl4": "article h4",
    -    "lvl5": "article h5, article td:first-child",
    -    "lvl6": "article h6",
    -    "text": "article p, article li, article td:last-child"
    -  },
    -  "strip_chars": " .,;:#",
    -  "custom_settings": {
    -    "separatorsToIndex": "_",
    -    "attributesForFaceting": [
    -      "language",
    -      "version",
    -      "type",
    -      "docusaurus_tag"
    -    ],
    -    "attributesToRetrieve": [
    -      "hierarchy",
    -      "content",
    -      "anchor",
    -      "url",
    -      "url_without_anchor",
    -      "type"
    -    ]
    -  },
    -  "conversation_id": [
    -    "833762294"
    -  ],
    -  "nb_hits": 46250
    -}
    -
    -

    docker 이용하여 크롤링

    -

    docker와 jq가 필요하다.
    -jq가 설치되어 있지 않으면 mac 기준 brew를 이용해서 설치할 수 있다.

    -
    brew install jq
    -
    -

    다음 명령어를 이용하여 .env와 config.json을 이용하여 크롤링을 한다.

    -
    docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper
    -
    -

    docusaurus 설정

    -

    전에 확인한 APP ID, Search-Only API KEY, IndexName을 이용하여 docusaurus.config 파일에 설정한다.

    -
    themeConfig:
    -  /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    -  ({
    -    ...
    -    algolia: {
    -      appId: 'MVIU5UEMOM', // Application ID
    -      apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key
    -      indexName: 'teco', // config.json에 설정한 인덱스명
    -      contextualSearch: true,
    -    },
    -  })
    -
    -

    부가 설정

    -

    화면 상단 Github Icon

    -

    파일 최하단에 아래 css 구문을 추가한다.

    -
    .header-github-link:hover {
    -  opacity: 0.6;
    -}
    -
    -.header-github-link:before {
    -  content: '';
    -  width: 24px;
    -  height: 24px;
    -  display: flex;
    -  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
    -    no-repeat;
    -}
    -
    -html[data-theme='dark'] .header-github-link:before {
    -  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
    -    no-repeat;
    -}
    -
    -

    themeconfig -> navbar에 github link를 설정한다.

    -
    navbar: {
    -  title: 'HELLO',
    -  items: [
    -    {
    -        href: 'https://github.com/greeng00se',
    -        position: 'right',
    -        className: 'header-github-link',
    -        'aria-label': 'GitHub repository',
    -    },
    -  ],
    -},
    -
    -

    코드블럭

    -

    java나 kotlin의 경우 기본적으로 하이라이팅을 지원해 주지 않는다.
    -prism 설정을 아래와 같이 변경해 준다.

    -
    prism: {
    -  theme: lightCodeTheme,
    -  darkTheme: darkCodeTheme,
    -  additionalLanguages: ['java', 'kotlin'],
    -}
    -
    -

    mermaid

    -

    mermaid를 사용하려면 @docusaurus/theme-mermaid 를 설치해야 한다.

    -
    yarn add @docusaurus/theme-mermaid
    -
    -

    설치 후 아래와 같이 설정을 추가한다.

    -
    const config = {
    -  ...
    -  markdown: {
    -    mermaid: true,
    -  },
    -  themes: [
    -    '@docusaurus/theme-mermaid'
    -  ],
    -};
    -
    -

    themeConfig에서 mermaid의 테마를 지정할 수 있다.

    -
    themeConfig:
    -    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    -    ({
    -      ...
    -      mermaid: {
    -        theme: {
    -          light: 'neutral', 
    -          dark: 'dark'
    -        },
    -      },
    -    }),
    -
    -

    국제화 설정

    -

    국제화 설정을 한다면 Older Entries 형태의 설명이 다음 페이지 로 변경된다.
    -설정파일에서 i18n에 있는 로케일 설정을 ko로 변경하면 된다.

    -
    i18n: {
    -  defaultLocale: "ko",
    -  locales: ["ko"],
    -},
    -
    -

    블로그 글 author

    -

    팀원 별로 문서를 관리한다면 다음과 같이 어떤 팀원이 글을 작성했는지 설정해야 한다.

    -

    author

    -

    authors.yml 파일을 이용하여 사용자에 대한 기본 설정을 할 수 있다.

    -
    herb:
    -  name: 허브
    -  title: Backend
    -  url: https://github.com/greeng00se
    -  image_url: https://github.com/greeng00se.png
    -
    -mallang:
    -  name: 말랑
    -  title: Backend
    -  url: https://github.com/shin-mallang
    -  image_url: https://github.com/shin-mallang.png
    -
    -

    블로그 글을 작성할 때 다음과 같이 authors에 넣어주기만 하면 된다.

    -
    ---
    -slug: 1
    -title: Hello World
    -authors: [herb, mallang]
    -tags: [hello, docusaurus]
    ----
    -
    -첫 번째 문서 내용
    -
    ]]>
    - Documentation -
    - - <![CDATA[우아한테크코스 레벨 2 회고]]> - https://greeng00se.github.io/woowacourse-level2-retrospective - https://greeng00se.github.io/woowacourse-level2-retrospective - Sun, 11 Jun 2023 00:00:00 GMT - - 23년의 6월이 오고, 레벨 2가 끝났다.
    -빠르게 지나가서 조금 아쉽다.

    -

    학습

    -

    회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
    -항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
    -미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

    -

    고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
    -방학 그리고 레벨 3 때는 조금 더 이론적인 부분을 학습하는데 집중해야겠다.

    -

    점차 학습 범위가 넓어지면서 자연스럽게 모르는 내용이 쌓여간다.
    -필요한 내용은 앞으로 천천히 학습하면 되니까 조급해지지 말아야겠다.

    -

    수면

    -

    레벨 2를 진행하는 동안 수면이 많이 부족했었고, 결과적으로는 그날의 컨디션을 많이 좌우했던 것 같다.
    -앞으로 수면 시간을 늘리고, 좋은 수면 습관을 가지도록 노력해야겠다.

    -

    협업

    -

    레벨 2 마지막에 협업 미션이 있었다.
    -지금까지는 백엔드 크루들과 페어 프로그래밍을 하면서 협업을 경험했다.
    -이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

    -

    레벨 3 때부터 본격적으로 프로젝트가 시작된다.
    -팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

    -

    레벨 2를 마무리하며

    -

    회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. -읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

    ]]>
    - Woowahan Techcourse - Retrospective +

    자기배반을 한다면 자기기만 상태가 된다.
    +자기기만 상태에 빠지는 것을 책에서는 상자 안에 들어간다고 표현한다.

    +

    읽고 나서

    +

    최근에 읽은 책 중 가장 마음이 불편했다.
    +그렇기에 더더욱 나에게 필요한 내용이 담겨있었다.

    +

    살면서 많은 선택의 순간이 존재했고, 그 순간마다 자기배반을 택하는 경우가 많았다.
    +작게는 집안일을 해야 하는데 몸이 조금 힘들다고 하지 않거나
    +크게는 잘못을 인정해야 하는 상황에서 그러지 않은 경우가 있었다.
    +이런 상황이 반복되어 결국 상자 안에 나 자신을 가두는 경우가 많았다.

    +

    더 나은 삶을 위해 내가 상자 안에 있는지 지속적으로 확인하고, 상자 밖으로 나가려는 연습을 해야겠다.
    +넓은 시선을 가지고, 항상 내가 틀릴 수 있다는 것을 생각하고 살아가자.

    +

    밑줄 친 문장들

    +
    +

    우리의 생각은 지식보다 작다.
    +우리의 지식은 사랑보다 작다.
    +우리의 사랑은 존재보다 작다.
    +그리고 우리가 생각하는 나는 실제의 나보다 그만큼 작다.
    +R. D. 랭
    +p.19

    +
    +
    +

    우리가 외적으로 어떤 행동을 하든지 간에, 사람들은 우리 마음에서 그들을 어떻게 대하고 있는지에 따라 주로 반응합니다.
    +우리가 사람들에 대해 어떻게 느끼게 되는지는 우리가 상자 안에 있는지 혹은 상자 밖에 있는지에 따라 달라지게 됩니다.
    +p.66

    +
    +
    +

    비난은 감정에 속하고 낙관은 의지에 속한다.
    +인간은 감정보다 더 큰 존재이다.
    +알랭, 탁닛한
    +p.103

    +
    +
    +

    우리가 자신에게만 집중하고 있는 한, 혼자서 일하는 것 이상의 창조적인 결과나 협력을 이끌어 낸다는 것은 불가능합니다.
    +오늘날 경제 환경에서는 혼자서는 일의 결과를 탁월하게 만들어 내기가 어렵습니다.
    +내가 중심이어야 된다는 폐쇄적인 사고는 함께 일하는 사람들의 열정을 불러오지 못합니다.
    +p.175

    +
    +
    +

    솔직함은 우리의 문제를 해결하는 열쇠입니다.
    +그것은 자신의 행동과 관련된 사람에 대해 기꺼이 사과를 하는 것입니다.
    +그것만이 실타래처럼 엉킨 관계의 문제를 해결할 수 있기 때문이죠.
    +p.188

    +
    +
    +

    누군가를 나와 같이 동일한 가치를 지닌 한 인간으로 생각해서 그 사람을 위해 내가 상자 밖에 계속 머무르고 싶은 열망이 생길 때, 나는 이미 그 사람에 대해 상자 밖에 있다.
    +p.214

    +
    +
    +

    대부분의 사람들이 관계 기술을 가지고 그들이 겪고 있는 문제를 바로잡으려고 하는 노력이 결실을 얻지 못하는 것은 결코 그러한 기술 부족 때문에 생기는 것이 아닙니다.
    +그것들은 자기배반 때문에 생겨납니다.
    +p.224

    +
    +
    +

    우리는 함께 일하고 우리와 함께 살아가는 사람이 진정으로 누구인지 알지 못합니다.
    +우리가 그들과 진정으로 함께 소통하기 전까지는 우리는 그들의 가치를 잘 모릅니다.
    +우리의 위대함이란 다른 사람들의 위대한 점을 발견해 주는 것에 있습니다.
    +p.280

    +
    ]]> + Book
    \ No newline at end of file diff --git a/search.html b/search.html index 830c8b259..bd75ecf57 100644 --- a/search.html +++ b/search.html @@ -13,8 +13,8 @@ - - + + diff --git a/shopping-cart-retrospective.html b/shopping-cart-retrospective.html index 7f433858b..87cc03b08 100644 --- a/shopping-cart-retrospective.html +++ b/shopping-cart-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    웹 장바구니 미션 회고

    · 약 5분

    1단계: https://github.com/woowacourse/jwp-shopping-cart/pull/244
    +

    웹 장바구니 미션 회고

    · 약 5분

    1단계: https://github.com/woowacourse/jwp-shopping-cart/pull/244
    2단계: https://github.com/woowacourse/jwp-shopping-cart/pull/300

    웹 장바구니 미션

    장바구니 미션은 블랙캣이랑 진행했다.
    @@ -27,7 +27,7 @@

    웹 장바구니 미션

    이전에 스프링 사용할 때는 아무 생각 없이 코드를 작성하는 경우가 많았는데, 코드를 작성할 때 근거가 생기고 있는 것 같다.

    새로 학습한 부분

    DTO 우발적 중복

    -

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.

    +

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.

    dto1

    클래스명을 제외하고 필드와 검증 로직 그 외 모든 게 같은 DTO를 보며 중복이라고 생각을 했고, 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
    로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러 가지 종류로 나누어 설명하고 있다.

    @@ -42,7 +42,7 @@

    새로 학습한 부분

    사실 조회를 두 번 하기 싫어서 다양한 방법을 생각했었는데 이번 미션에서는 ThreadLocal을 사용했다.
    일단 Tomcat은 요청마다 다른 스레드를 사용하고, Interceptor에서 조회해서 만든 Credential을 ThreadLocal에 넣어두었다가 ArgumentResolver에서 꺼낸 다음 ThreadLocal을 clear 하면 문제가 없을 거라 판단했다.

    리뷰어인 웨지에게도 어떤 방법을 사용할지 궁금증을 작성했었다.
    -웨지는 email에 index를 걸어두고 dao 재조회를 사용할 것이라고 했다.
    +웨지는 email에 index를 걸어두고 dao 재조회를 사용할 것이라고 했다.
    재사용하지 않고 db에 인덱스를 걸 생각은 하지 못했는데, 제일 직관적이고 좋은 방법이라고 생각했다.

    페어에게 배울 부분

    기록

    @@ -53,6 +53,6 @@

    페어에게 배울 부분

    페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
    따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
    블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

    -

    빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

    +

    빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

    \ No newline at end of file diff --git a/spring-test-isolation.html b/spring-test-isolation.html index 18bd8faa1..42133187e 100644 --- a/spring-test-isolation.html +++ b/spring-test-isolation.html @@ -13,11 +13,11 @@ - - + + -

    스프링 테스트 격리

    · 약 5분

    테스트 격리

    +

    스프링 테스트 격리

    · 약 5분

    테스트 격리

    테스트의 순서에 따라 성공 실패 여부가 결정되는 비결정적인(non-determinism) 테스트가 되어서는 안되고, 테스트는 항상 순서에 상관없이 독립적으로 수행되도록 보장되어야 한다. 일반적으로 자원의 공유, 외부 API, 시간 등으로 비결정적인 테스트가 된다. 이를 해결하기 위해 테스트 대역을 사용하거나, 컨텍스트를 재실행하는 @DirtiesContext, 자원을 초기화하기 위해 테스트 이후에 테이블을 롤백 하는 @Transactional등 다양한 방법이 있다.
    해당 글에서는 스프링에서 데이터베이스 자원의 공유를 방지하기 위해 테스트 격리를 수행하는 부분에 대해 설명한다.

    테스트끼리 서로 의존하면 안 된다.
    @@ -98,6 +98,6 @@

    참고 자료

    The Spring TestExecutionListener, Baeldung
    인수테스트에서 테스트 격리하기, 테코블
    Eradicating Non-Determinism in Tests, martin fowler
    -@SpringBootTest의 테스트 격리시키기, MangKyu

    +@SpringBootTest의 테스트 격리시키기, MangKyu

    \ No newline at end of file diff --git a/subway-retrospective.html b/subway-retrospective.html index 9626657f2..88f8c166e 100644 --- a/subway-retrospective.html +++ b/subway-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    지하철 미션 회고

    · 약 8분

    1단계: https://github.com/woowacourse/jwp-subway-path/pull/16
    +

    지하철 미션 회고

    · 약 8분

    1단계: https://github.com/woowacourse/jwp-subway-path/pull/16
    2, 3단계: https://github.com/woowacourse/jwp-subway-path/pull/126

    지하철 미션

    점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
    @@ -29,7 +29,7 @@

    지하철 미션

    노선을 저장하는 방법에 대해서 밀리와 이야기를 나눴다.

    1. 구간을 데이터베이스에서 전부 제거하고 전부 추가하는 방법
    2. -
    3. 변경된 요소만 데이터베이스에 반영하는 방법
    4. +
    5. 변경된 요소만 데이터베이스에 반영하는 방법

    페어 시간이 짧아서 더욱 간단한 1번을 선택했고, 시간 내 요구사항을 만족시키기 위해 더 간단하게 구현하는 방법을 선택하는 것도 좋은 트레이드오프였던 것 같다.
    추후 페어가 끝나고 리뷰어인 서브웨이가 일부분만 반영하는 것으로 개선해 보는 것도 좋을 것 같다고 코멘트를 남겨주셔서 추가 및 제거된 요소만 반영하도록 변경했다.

    @@ -44,7 +44,7 @@

    새로 학습한 부분

    또한 분리하지 않는다면 정책의 순서가 중요한데, 연령별 할인 정책을 마지막에 두어야 했기 때문에 책임 연쇄 패턴도 고려를 했지만 조금 더 간결해 보이는 컴포지트 패턴을 선택했다.

    도메인에 특정 기술의 의존성을 분리

    처음에 도메인 패키지에 jgrapht 라이브러리를 의존하고 있는 클래스를 두어서 도메인 패키지가 jgrapht와 강결합이 되어버렸다.
    -따라서 도메인 패키지 내에는 경로 검색에 대한 인터페이스를 두고, 세부 구현은 도메인 패키지 외부로 분리했다.
    +따라서 도메인 패키지 내에는 경로 검색에 대한 인터페이스를 두고, 세부 구현은 도메인 패키지 외부로 분리했다.
    최대한 간결하게 구현한다고 생각을 해도, 이런 부분은 인터페이스를 두어 결합을 피하는 것이 좋을 것 같다.

    컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
    이때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

    @@ -92,6 +92,6 @@

    페어에게 배울 부분

    편한 분위기

    전체적으로 페어 할 때 편하게 진행했던 것 같다.
    일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
    -나는 과연 다른 사람들에게 편한 사람일까?

    +나는 과연 다른 사람들에게 편한 사람일까?

    \ No newline at end of file diff --git a/tags.html b/tags.html index bd4ec0932..eed308db6 100644 --- a/tags.html +++ b/tags.html @@ -13,10 +13,10 @@ - - + + - + \ No newline at end of file diff --git a/tags/async.html b/tags/async.html index 337934873..3353feed1 100644 --- a/tags/async.html +++ b/tags/async.html @@ -13,93 +13,216 @@ - - + + -

    "async" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    문제 상황

    -

    현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
    -확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

    -

    비동기 예외 발생시 로깅 설정

    -

    스프링 4.1 부터 제공되는 AsyncUncaughtExceptionHandler의 경우 반환 타입이 void인 비동기 메서드를 예외 처리하기 쉽도록 도와준다.

    -

    따라서 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 핸들링하는 클래스를 생성했다.
    -기존의 동기 예외 처리의 경우 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다.
    -비동기 예외 처리도 마찬가지로 MDC의 정보를 가져와서 로그를 출력하도록 설정했다.

    -
    @Slf4j
    -public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    -
    -    private static final String LOG_FORMAT = "[%s] %s";
    -
    -    @Override
    -    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
    -        log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
    -    }
    +

    "async" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 12분

    이전 글

    +

    경로 이미지 생성하기 - 기술 선택
    +경로 이미지 생성하기 - 구현

    +

    개요

    +

    현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
    +경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
    +따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.

    +

    주기능의 응답속도 개선

    +

    여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
    +하지만 현재 여행 종료와 감상 생성의 응답 속도가 경로 이미지 생성 시간에 영향을 받고 있다.
    +경로 이미지 생성은 비동기 처리하여도 애플리케이션 사용에 문제가 되지 않는다.
    +소요 시간이 1초 이상 걸리는 경우가 존재하기에 이미지 생성을 비동기 처리하고 여행 종료와 감상 생성 기능의 응답 시간을 개선하는 것이 더 중요하다.

    +

    확장성 대비

    +

    현재 10분 간격으로 위치 정보를 서버에 저장하고 있다.
    +조금 더 짧은 간격으로 위치 정보를 그리는 경우 하나의 여행에 많은 위치 정보가 저장될 수밖에 없고 따라서 경로 이미지 생성에 걸리는 시간이 더 길어질 수 있다.
    +따라서 추후에 더 짧은 간격으로 위치 정보를 저장하는 경우를 대비하여 이미지 생성은 비동기로 처리하는 것이 합당하다.

    +

    비동기 처리

    +

    @Async를 사용하면 간단하게 메서드를 비동기로 동작하도록 만들 수 있다.

    +

    비동기 설정

    +

    사용하기 전에 설정 파일을 하나 만들어서 EnableAsync 설정을 해야한다.
    +해당 설정을 적용하면 비동기적으로 실행하려는 메서드에 @Async 애너테이션을 붙여주기만 하면 비동기로 동작한다.

    +
    @EnableAsync
    +@Configuration
    +public class AsyncConfig {
     }
     
    -

    AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
    -getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

    -
    @EnableAsync
    -@Configuration
    -public class AsyncConfig implements AsyncConfigurer {
    +

    스프링 부트를 사용하지 않는 경우 기본적으로 비동기 처리를 할 때 매번 새로운 스레드를 생성하기 때문에 스레드 풀 설정을 따로 해줘야 한다. 하지만 스프링 부트를 사용하는 경우 ThreadPoolTaskExecutor를 따로 설정하지 않아도 기본적으로 스프링 부트가 생성을 도와준다.

    +
    +

    In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing. +7.7. Task Execution and Scheduling, Spring Boot Docs

    +
    +

    @Async 적용

    +

    이미지 생성기에 Async 애너테이션을 붙여 비동기로 동작하도록 한다.

    +
    @Async
    +public void generate(
    +        List<Double> latitudes,
    +        List<Double> longitudes,
    +        List<Double> pointedLatitudes,
    +        List<Double> pointedLongitudes,
    +        Long tripId
    +) {
    +    // 이미지 생성
    +    RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);
    +    Coordinates coordinates = Coordinates.of(latitudes, longitudes);
    +    Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);
    +    drawImage(coordinates, routeImageDrawer, pointedCoordinates);
     
    -    @Override
    -    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    -        return new AsyncExceptionHandler();
    -    }
    +    // 이미지 저장
    +    String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());
    +
    +    // 자원 할당 해제
    +    routeImageDrawer.dispose();
    +
    +    // 데이터베이스 값 변경
    +    Trip trip = tripRepository.findById(tripId)
    +        .orElseThrow();
    +    trip.changeRouteImageUrl(imageUrl);
    +    tripRepository.save(trip);
     }
     
    -

    이제 비동기 상황에서 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아 처리한다.

    -

    MDC 정보 연동 문제

    -

    비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없는 문제가 발생했다.

    -

    ./mdc-null.png

    -

    스프링 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

    -
    public class MdcTaskDecorator implements TaskDecorator {
    -
    -    @Override
    -    public Runnable decorate(final Runnable runnable) {
    -        Map<String, String> threadContext = MDC.getCopyOfContextMap();
    -        return () -> {
    -            MDC.setContextMap(threadContext);
    -            runnable.run();
    -        };
    -    }
    +

    비동기 처리시 문제점

    +

    현재 이미지 생성을 하고 저장 후, 저장 경로를 DB에 반영해야 한다.
    +따라서 패키지 간 순환 참조 형태가 되며 의존성 방향이 문제가 생긴다.

    + +

    이를 해결하기 위해서는 인터페이스를 사용하는 방법과 이벤트를 사용하는 방법이 있다.
    +인터페이스를 사용한다면 다음과 같은 구조가 된다.

    + +

    패키지 간 의존성은 해결되었지만, 이미지 경로 저장을 위해 tripId를 받아야하는 등의 논리적인 의존성은 아직 해결되지 않았다.
    +따라서 이벤트를 사용하기로 했다.

    +

    이벤트 사용

    +

    스프링의 애플리케이션 이벤트를 사용하면 비즈니스 로직의 비관심사(ex. 경로 이미지 생성)을 효율적인 방법으로 처리할 수 있다.

    +

    이벤트 발행

    +

    이벤트를 사용하려면 먼저 이벤트를 발행해야 한다.
    +스프링에서는 ApplicationEventPublisher 인터페이스를 사용하여 이벤트를 발행할 수 있다.
    +해당 인터페이스는 내부적으로 ApplicationContext가 구현하여 이벤트를 발행한다.

    +
    public void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {
    +    ...
    +
    +    // 이벤트 발행
    +    applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));
    +}
    +
    +public record TripUpdateEvent(Long tripId) {
     }
     
    -

    생성한 Decorator 클래스를 설정 파일에 등록해 준다.

    -
    @RequiredArgsConstructor
    -@EnableAsync
    -@Configuration
    -public class AsyncConfig implements AsyncConfigurer {
    -
    -    private final AsyncConfigurationProperties properties;
    -
    -    @Bean
    -    public ThreadPoolTaskExecutor taskExecutor() {
    -        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    -        executor.setCorePoolSize(properties.coreSize());
    -        executor.setMaxPoolSize(properties.maxSize());
    -        executor.setQueueCapacity(properties.queueCapacity());
    -        
    -        // highlight-next-line
    -        executor.setTaskDecorator(new MdcTaskDecorator());
    -        executor.setWaitForTasksToCompleteOnShutdown(true);
    -        executor.initialize();
    -        return executor;
    +

    이벤트를 발행할 때 발행하는 이벤트명이 중요하다.
    +이벤트를 구독하는 도메인의 행위를 담고 있는 이벤트를 발행(ex. RouteImageGenerateEvent)한다면 논리적인 의존 관계가 남아있기에 이벤트를 적절히 사용했다고 보기 어렵다.
    +발행하는 이벤트명은 주기능이 어떤 행위(ex. TripUpdateEvent)를 했는지에 대한 정보가 담겨있는 이벤트명으로 발행하는 것이 중요하다.

    +

    이벤트 구독

    +

    이벤트를 구독하여 실행하는 메서드는 비동기로 처리하기 위하여 @Async 애너테이션을 적용했다.
    +이벤트의 구독은 여행이 정상적으로 종료될 때 여행에 대한 정보를 가지고 경로 이미지를 생성하기 위해 @TransactionalEventListener를 사용했다.

    +

    TransactionPhase을 사용하여 트랜잭션 이벤트를 어떤 단계에서 수신하고 처리할지를 지정할 수 있다.

    AFTER_COMMIT(기본값): 트랜잭션이 정상적으로 커밋 되는 경우 이벤트 실행
    +AFTER_ROLLBACK: 트랜잭션이 롤백되는 경우 이벤트 실행
    +AFTER_COMPLETION: 트랜잭션이 커밋 또는 롤백 되었을 경우 이벤트 실행
    +BEFORE_COMMIT: 트랜잭션이 커밋 되기 전 이벤트 실행

    +

    이미지 생성의 경우 트랜잭션에서 제외하기 위해 @Transactional 애너테이션을 사용하지 않았다.

    +
    @Component
    +public class TripUpdateEventHandler {
    +
    +    private final RouteImageGenerator routeImageGenerator;
    +    private final TripRepository tripRepository;
    +
    +    public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {
    +        this.routeImageGenerator = routeImageGenerator;
    +        this.tripRepository = tripRepository;
         }
     
    -    @Override
    -    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    -        return new AsyncExceptionHandler();
    +    @Async
    +    @TransactionalEventListener(phase = AFTER_COMMIT)
    +    public void handle(TripUpdateEvent tripUpdateEvent) {
    +        Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());
    +
    +        String imageUrl = routeImageGenerator.generate(
    +                trip.getLatitudes(),
    +                trip.getLongitudes(),
    +                trip.getPointedLatitudes(),
    +                trip.getPointedLongitudes()
    +        );
    +
    +        trip.changeRouteImageUrl(imageUrl);
    +        tripRepository.save(trip);
         }
     }
     
    -

    설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

    -

    ./mdc-not-null.png

    -

    참고 자료

    -

    spring async, baeldung
    -@Async will not call by @ControllerAdvice for global exception
    -Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
    -TaskDecorator, Spring docs
    -AsyncUncaughtExceptionHandler

    +

    이벤트를 사용함으로써 패키지 간 순환 참조 문제가 다음과 같이 해결되었다.
    +또한 주기능과 부기능을 분리함으로써 경로 이미지 생성 기능에 대한 전체적인 결합도를 낮추었다.

    + +

    테스트

    +

    비동기로 동작하는 메서드를 테스트하기 위해서는 아래와 같은 방법이 있다.

    + + +
    @ContextConfiguration(classes = TestSyncConfig.class)
    +@SpringBootTest
    +public class TripUpdateEventHandlerIntegrationTest {
    +
    +    ...
    +
    +    @Test
    +    void 여행수정_이벤트를_발생시키면_이미지를_생성_요청을_한다() {
    +        // given
    +        TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);
    +        given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))
    +                .willReturn(여행());
    +
    +        // when
    +        transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));
    +
    +        // then
    +        then(routeImageGenerator)
    +                .should(times(1))
    +                .generate(any(), any(), any(), any());
    +    }
    +}
    +
    +

    처음에는 테스트에서만 동기로 설정 후 검증하려고 했다.
    +통합 테스트에선 트랜잭션이 정상 종료되었을 때 비동기로 이벤트를 구독하여 이미지 생성 메서드를 호출하는지 검증이 필요했기 때문에 최종적으로 Mockito.timeout 메서드를 사용하여 비동기 메서드가 통과될 때까지 대기하는 방향으로 변경했다.

    +

    결과

    +

    ./time.png

    +

    위 응답 시간은 위치 정보 1000개를 기준으로 테스트한 값이다.
    +응답 시간에 이미지 생성 시간이 포함되지 않아서 성능이 개선된 것을 볼 수 있다.

    +

    참고 자료

    +

    7.7. Task Execution and Scheduling, Spring Boot Docs
    +Spring Events, Baeldung
    +회원시스템 이벤트기반 아키텍처 구축하기

    \ No newline at end of file diff --git a/tags/async/page/2.html b/tags/async/page/2.html index d4f505235..2d7ee0280 100644 --- a/tags/async/page/2.html +++ b/tags/async/page/2.html @@ -13,216 +13,93 @@ - - + + -

    "async" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 12분

    이전 글

    -

    경로 이미지 생성하기 - 기술 선택
    -경로 이미지 생성하기 - 구현

    -

    개요

    -

    현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
    -경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
    -따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.

    -

    주기능의 응답속도 개선

    -

    여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
    -하지만 현재 여행 종료와 감상 생성의 응답 속도가 경로 이미지 생성 시간에 영향을 받고 있다.
    -경로 이미지 생성은 비동기 처리하여도 애플리케이션 사용에 문제가 되지 않는다.
    -소요 시간이 1초 이상 걸리는 경우가 존재하기에 이미지 생성을 비동기 처리하고 여행 종료와 감상 생성 기능의 응답 시간을 개선하는 것이 더 중요하다.

    -

    확장성 대비

    -

    현재 10분 간격으로 위치 정보를 서버에 저장하고 있다.
    -조금 더 짧은 간격으로 위치 정보를 그리는 경우 하나의 여행에 많은 위치 정보가 저장될 수밖에 없고 따라서 경로 이미지 생성에 걸리는 시간이 더 길어질 수 있다.
    -따라서 추후에 더 짧은 간격으로 위치 정보를 저장하는 경우를 대비하여 이미지 생성은 비동기로 처리하는 것이 합당하다.

    -

    비동기 처리

    -

    @Async를 사용하면 간단하게 메서드를 비동기로 동작하도록 만들 수 있다.

    -

    비동기 설정

    -

    사용하기 전에 설정 파일을 하나 만들어서 EnableAsync 설정을 해야한다.
    -해당 설정을 적용하면 비동기적으로 실행하려는 메서드에 @Async 애너테이션을 붙여주기만 하면 비동기로 동작한다.

    -
    @EnableAsync
    -@Configuration
    -public class AsyncConfig {
    -}
    -
    -

    스프링 부트를 사용하지 않는 경우 기본적으로 비동기 처리를 할 때 매번 새로운 스레드를 생성하기 때문에 스레드 풀 설정을 따로 해줘야 한다. 하지만 스프링 부트를 사용하는 경우 ThreadPoolTaskExecutor를 따로 설정하지 않아도 기본적으로 스프링 부트가 생성을 도와준다.

    -
    -

    In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing. -7.7. Task Execution and Scheduling, Spring Boot Docs

    -
    -

    @Async 적용

    -

    이미지 생성기에 Async 애너테이션을 붙여 비동기로 동작하도록 한다.

    -
    @Async
    -public void generate(
    -        List<Double> latitudes,
    -        List<Double> longitudes,
    -        List<Double> pointedLatitudes,
    -        List<Double> pointedLongitudes,
    -        Long tripId
    -) {
    -    // 이미지 생성
    -    RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);
    -    Coordinates coordinates = Coordinates.of(latitudes, longitudes);
    -    Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);
    -    drawImage(coordinates, routeImageDrawer, pointedCoordinates);
    -
    -    // 이미지 저장
    -    String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());
    -
    -    // 자원 할당 해제
    -    routeImageDrawer.dispose();
    -
    -    // 데이터베이스 값 변경
    -    Trip trip = tripRepository.findById(tripId)
    -        .orElseThrow();
    -    trip.changeRouteImageUrl(imageUrl);
    -    tripRepository.save(trip);
    +

    "async" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    문제 상황

    +

    현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
    +확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

    +

    비동기 예외 발생시 로깅 설정

    +

    스프링 4.1 부터 제공되는 AsyncUncaughtExceptionHandler의 경우 반환 타입이 void인 비동기 메서드를 예외 처리하기 쉽도록 도와준다.

    +

    따라서 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 핸들링하는 클래스를 생성했다.
    +기존의 동기 예외 처리의 경우 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다.
    +비동기 예외 처리도 마찬가지로 MDC의 정보를 가져와서 로그를 출력하도록 설정했다.

    +
    @Slf4j
    +public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    +
    +    private static final String LOG_FORMAT = "[%s] %s";
    +
    +    @Override
    +    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
    +        log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
    +    }
     }
     
    -

    비동기 처리시 문제점

    -

    현재 이미지 생성을 하고 저장 후, 저장 경로를 DB에 반영해야 한다.
    -따라서 패키지 간 순환 참조 형태가 되며 의존성 방향이 문제가 생긴다.

    - -

    이를 해결하기 위해서는 인터페이스를 사용하는 방법과 이벤트를 사용하는 방법이 있다.
    -인터페이스를 사용한다면 다음과 같은 구조가 된다.

    - -

    패키지 간 의존성은 해결되었지만, 이미지 경로 저장을 위해 tripId를 받아야하는 등의 논리적인 의존성은 아직 해결되지 않았다.
    -따라서 이벤트를 사용하기로 했다.

    -

    이벤트 사용

    -

    스프링의 애플리케이션 이벤트를 사용하면 비즈니스 로직의 비관심사(ex. 경로 이미지 생성)을 효율적인 방법으로 처리할 수 있다.

    -

    이벤트 발행

    -

    이벤트를 사용하려면 먼저 이벤트를 발행해야 한다.
    -스프링에서는 ApplicationEventPublisher 인터페이스를 사용하여 이벤트를 발행할 수 있다.
    -해당 인터페이스는 내부적으로 ApplicationContext가 구현하여 이벤트를 발행한다.

    -
    public void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {
    -    ...
    -
    -    // 이벤트 발행
    -    applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));
    -}
    +

    AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
    +getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

    +
    @EnableAsync
    +@Configuration
    +public class AsyncConfig implements AsyncConfigurer {
     
    -public record TripUpdateEvent(Long tripId) {
    +    @Override
    +    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    +        return new AsyncExceptionHandler();
    +    }
     }
     
    -

    이벤트를 발행할 때 발행하는 이벤트명이 중요하다.
    -이벤트를 구독하는 도메인의 행위를 담고 있는 이벤트를 발행(ex. RouteImageGenerateEvent)한다면 논리적인 의존 관계가 남아있기에 이벤트를 적절히 사용했다고 보기 어렵다.
    -발행하는 이벤트명은 주기능이 어떤 행위(ex. TripUpdateEvent)를 했는지에 대한 정보가 담겨있는 이벤트명으로 발행하는 것이 중요하다.

    -

    이벤트 구독

    -

    이벤트를 구독하여 실행하는 메서드는 비동기로 처리하기 위하여 @Async 애너테이션을 적용했다.
    -이벤트의 구독은 여행이 정상적으로 종료될 때 여행에 대한 정보를 가지고 경로 이미지를 생성하기 위해 @TransactionalEventListener를 사용했다.

    -

    TransactionPhase을 사용하여 트랜잭션 이벤트를 어떤 단계에서 수신하고 처리할지를 지정할 수 있다.

    AFTER_COMMIT(기본값): 트랜잭션이 정상적으로 커밋 되는 경우 이벤트 실행
    -AFTER_ROLLBACK: 트랜잭션이 롤백되는 경우 이벤트 실행
    -AFTER_COMPLETION: 트랜잭션이 커밋 또는 롤백 되었을 경우 이벤트 실행
    -BEFORE_COMMIT: 트랜잭션이 커밋 되기 전 이벤트 실행

    -

    이미지 생성의 경우 트랜잭션에서 제외하기 위해 @Transactional 애너테이션을 사용하지 않았다.

    -
    @Component
    -public class TripUpdateEventHandler {
    -
    -    private final RouteImageGenerator routeImageGenerator;
    -    private final TripRepository tripRepository;
    -
    -    public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {
    -        this.routeImageGenerator = routeImageGenerator;
    -        this.tripRepository = tripRepository;
    -    }
    -
    -    @Async
    -    @TransactionalEventListener(phase = AFTER_COMMIT)
    -    public void handle(TripUpdateEvent tripUpdateEvent) {
    -        Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());
    -
    -        String imageUrl = routeImageGenerator.generate(
    -                trip.getLatitudes(),
    -                trip.getLongitudes(),
    -                trip.getPointedLatitudes(),
    -                trip.getPointedLongitudes()
    -        );
    -
    -        trip.changeRouteImageUrl(imageUrl);
    -        tripRepository.save(trip);
    +

    이제 비동기 상황에서 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아 처리한다.

    +

    MDC 정보 연동 문제

    +

    비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없는 문제가 발생했다.

    +

    ./mdc-null.png

    +

    스프링 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

    +
    public class MdcTaskDecorator implements TaskDecorator {
    +
    +    @Override
    +    public Runnable decorate(final Runnable runnable) {
    +        Map<String, String> threadContext = MDC.getCopyOfContextMap();
    +        return () -> {
    +            MDC.setContextMap(threadContext);
    +            runnable.run();
    +        };
         }
     }
     
    -

    이벤트를 사용함으로써 패키지 간 순환 참조 문제가 다음과 같이 해결되었다.
    -또한 주기능과 부기능을 분리함으로써 경로 이미지 생성 기능에 대한 전체적인 결합도를 낮추었다.

    - -

    테스트

    -

    비동기로 동작하는 메서드를 테스트하기 위해서는 아래와 같은 방법이 있다.

    - - -
    @ContextConfiguration(classes = TestSyncConfig.class)
    -@SpringBootTest
    -public class TripUpdateEventHandlerIntegrationTest {
    -
    -    ...
     
    -    @Test
    -    void 여행수정_이벤트를_발생시키면_이미지를_생성_요청을_한다() {
    -        // given
    -        TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);
    -        given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))
    -                .willReturn(여행());
    -
    -        // when
    -        transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));
    -
    -        // then
    -        then(routeImageGenerator)
    -                .should(times(1))
    -                .generate(any(), any(), any(), any());
    +    @Override
    +    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    +        return new AsyncExceptionHandler();
         }
     }
    -
    -

    처음에는 테스트에서만 동기로 설정 후 검증하려고 했다.
    -통합 테스트에선 트랜잭션이 정상 종료되었을 때 비동기로 이벤트를 구독하여 이미지 생성 메서드를 호출하는지 검증이 필요했기 때문에 최종적으로 Mockito.timeout 메서드를 사용하여 비동기 메서드가 통과될 때까지 대기하는 방향으로 변경했다.

    -

    결과

    -

    ./time.png

    -

    위 응답 시간은 위치 정보 1000개를 기준으로 테스트한 값이다.
    -응답 시간에 이미지 생성 시간이 포함되지 않아서 성능이 개선된 것을 볼 수 있다.

    -

    참고 자료

    -

    7.7. Task Execution and Scheduling, Spring Boot Docs
    -Spring Events, Baeldung
    -회원시스템 이벤트기반 아키텍처 구축하기

    +
    +

    설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

    +

    ./mdc-not-null.png

    +

    참고 자료

    +

    spring async, baeldung
    +@Async will not call by @ControllerAdvice for global exception
    +Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
    +TaskDecorator, Spring docs
    +AsyncUncaughtExceptionHandler

    \ No newline at end of file diff --git a/tags/awt.html b/tags/awt.html index c60af67a9..937d6e5cb 100644 --- a/tags/awt.html +++ b/tags/awt.html @@ -13,201 +13,60 @@ - - + + -

    "awt" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 12분

    개요

    -

    여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
    -경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

    -

    구현 결과

    -

    ./result.png

    -

    예시 데이터는 다음과 같다.
    -서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

    -
    List<Double> x = List.of(
    -        126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
    -        126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
    -);
    -List<Double> y = List.of(
    -        37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
    -        37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
    -);
    -List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
    -List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);
    -
    -

    IMAGE_SIZE & ROUTE_SIZE

    -
    private static final int IMAGE_SIZE = 800;
    -private static final int ROUTE_SIZE = 600;
    -
    -

    코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
    -IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
    -ROUTE_SIZE의 경우 상하좌우 100px 만큼의 간격을 위해 존재한다.
    -따라서 실제 경로 이미지의 크기는 600 * 600 사이즈로 생성된다.

    -

    ./600.png

    -

    사이즈 변경의 이유

    -

    255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

    -

    주요 클래스

    -

    요약

    -
    클래스명설명특이사항
    Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
    CoordinatesCoordinate의 일급 컬렉션-
    Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
    PositionsPositions의 일급 컬렉션-
    RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
    RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
    RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
    BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
    Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
    -

    의존관계

    - -

    Coordinates(위도, 경도의 일급 컬렉션)

    -

    List<Double> 2개(위도, 경도)인 형태로 관리하는 방법이 있었지만, 위치 점을 여러개 찍는 부분에서 로직이 복잡해 질 것 같아서 Coordinate(x, y)와 일급 컬렉션인 Coordinates로 관리하기로 했다.
    -Coordinates 클래스에는 다음 두 개의 인터페이스가 존재한다.

    +

    "awt" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    ./route.png

    +

    이미지 생성의 책임

    +

    위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
    +따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

    +

    해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

      -
    • calculatePositions: 경로 이미지의 크기를 받아 실제 이미지 생성시 사용될 Positions를 반환
    • -
    • indexOf: 다른 Coordinates를 받아 동일한 위치점에 해당하는 인덱스를 반환하는
    • +
    • 이미지 생성
    • +
    • 선과 점 표현
    • +
    • 투명한 배경색
    -

    Positions 계산 로직은 다음과 같다.
    -위도, 경도 각각에 대한 부분을 이미지 생성시 필요한 값으로 변환한다.

    -
    // 호출
    -// List<Integer> xPositions = toPositions(xValues, maxDifference, routeImageSize);
    -// List<Integer> yPositions = toPositions(yValues, maxDifference, routeImageSize);
    -
    -private List<Integer> toPositions(List<Double> values, Double maxDifference, Integer routeImageSize) {
    -    Double minValue = Collections.min(values);
    -    return values.stream()
    -            .map(value -> normalizeCoordinate(value, maxDifference, minValue))
    -            .map(value -> mapToPosition(value, routeImageSize))
    -            .toList();
    -}
    -
    -private double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {
    -    return (coordinate - minValue) / maxDifference;
    -}
    -
    -private int mapToPosition(Double coordinate, Integer routeImageSize) {
    -    return (int) (coordinate * routeImageSize);
    -}
    -
    -

    위도로 예시든 내용이다.

    -
      -
    1. Collections.min(values) → 위도 리스트의 최소값을 구한다.
    2. -
    3. normalizeCoordinate → 각각의 위도 값에서 최소값을 빼고 0 ~ 1 사이 값으로 변환 후 위경도의 최대 차이로 나눈다.
    4. -
    5. mapToPosition → 그래프 크기를 받아 0 ~ 1 사이 값을 실제 이미지를 위한 위치값으로 변환한다.
    6. -
    -

    Positions(실제 이미지 생성에 사용할 위치)

    -

    Positions 클래스에는 다음 다섯 개의 인터페이스가 존재한다.

    +

    현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

    +

    고려한 기술

    +

    백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

      -
    • align: 이미지 사이즈와 경로 이미지 사이즈를 받아 Position 값들을 중앙 정렬한다.
    • -
    • getPositionsByIndexes: 인덱스 리스트를 받아 입력받은 인덱스에 해당하는 값들을 반환한다.
    • -
    • size: 크기를 반환한다.
    • -
    • xPositions: x 값들을 반환한다.
    • -
    • yPositions: y 값들을 반환한다.
    • +
    • Python의 Matplotlib
    • +
    • AWT(Abstract Window Toolkit) [최종 선택]
    • +
    • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
    • +
    • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)
    -

    중앙 정렬 로직은 다음과 같다.

    -
    public Positions align(int imageSize, int routeSize) {
    -    int xOffset = calculateOffset(Position::x, imageSize);
    -    int yOffset = calculateOffset(Position::y, imageSize);
    -
    -    return items.stream()
    -            .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))
    -            .collect(collectingAndThen(toList(), Positions::new));
    -}
    -
    -private int calculateOffset(ToIntFunction<Position> positionToInteger, int imageSize) {
    -    List<Integer> positions = items.stream()
    -            .mapToInt(positionToInteger)
    -            .boxed()
    -            .toList();
    -
    -    int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;
    -    return imageSize / 2 - midValue;
    -}
    -
    -

    상하좌우 여백을 동일하게 주기 위해서 offset 값을 구해서 x, y 값에 각각 더하는 형태로 중앙 정렬을 수행했다.
    -BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

    -

    ./800.png

    -

    따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

    -

    x 값 → 계산한 offset 그대로 더한다.
    -y 값 → imageSize(800)에서 y + offset 값을 뺀다.

    -

    RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

    -

    BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
    -그림을 그리기 위해 설정한 상수들이 존재한다.

    -
    // RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
    -// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
    -// 이를 RGBA라고 부른다.
    -private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
    -// 배경 투명색
    -private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
    -// 경로를 위한 STROKE
    -private static final int LINE_STROKE_WIDTH = 7;
    -private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    -// 위치 점을 위한 STROKE
    -private static final int POINT_STROKE_WIDTH = 20;
    -private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    -// 안티앨리어싱 등 화질 개선을 위한 설정
    -private static final Map<Object, Object> renderingHints = Map.of(
    -        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
    -        RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
    -        RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
    -);
    -
    -

    RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

    +

    Python & Matplotlib

    +

    데이터 시각화 라이브러리
    +이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

      -
    • drawLine: 선을 그린다.
    • -
    • drawPoint: 점을 찍는다.
    • -
    • dispose: 자원 할당을 해제한다.
    • +
    • 코드가 간단해서 유지 보수성이 좋다.
    • +
    • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
    • +
    • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.
    -

    dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

    -

    이미지 생성 Flow

    -

    1. 이미지 생성 준비

    - -

    2. 선 그리기 요청

    - -

    3. 위치 점 그리기 요청

    - -

    4. 업로드 요청

    - -

    전체 Flow

    -
    +

    Java AWT 이외의 라이브러리

    +

    Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

    +
    라이브러리설명제외 이유
    SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
    JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
    simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
    matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
    +

    Java & AWT(Abstract Window Toolkit)

    +

    그래픽과 이미지를 그리기 위한 도구
    +이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

    +
      +
    • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
    • +
    • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
    • +
    • 추가적인 api 호출을 하지 않아도 된다.
    • +
    +

    기술 선택

    +

    AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
    +하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

    +

    유지 보수

    +

    AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
    +따라서 다음과 같은 방법으로 공유하기로 했다.

    +
      +
    1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
    2. +
    3. AWT를 사용한 부분을 문서화하여 공유한다.
    4. +
    +

    레벨 3를 마무리하며 내용 추가

    +

    기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
    +AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

    \ No newline at end of file diff --git a/tags/awt/page/2.html b/tags/awt/page/2.html index da63520e4..600616f9a 100644 --- a/tags/awt/page/2.html +++ b/tags/awt/page/2.html @@ -13,60 +13,201 @@ - - + + -

    "awt" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    ./route.png

    -

    이미지 생성의 책임

    -

    위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
    -따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

    -

    해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

    -
      -
    • 이미지 생성
    • -
    • 선과 점 표현
    • -
    • 투명한 배경색
    • -
    -

    현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

    -

    고려한 기술

    -

    백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

    +

    "awt" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 12분

    개요

    +

    여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
    +경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

    +

    구현 결과

    +

    ./result.png

    +

    예시 데이터는 다음과 같다.
    +서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

    +
    List<Double> x = List.of(
    +        126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
    +        126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
    +);
    +List<Double> y = List.of(
    +        37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
    +        37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
    +);
    +List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
    +List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);
    +
    +

    IMAGE_SIZE & ROUTE_SIZE

    +
    private static final int IMAGE_SIZE = 800;
    +private static final int ROUTE_SIZE = 600;
    +
    +

    코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
    +IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
    +ROUTE_SIZE의 경우 상하좌우 100px 만큼의 간격을 위해 존재한다.
    +따라서 실제 경로 이미지의 크기는 600 * 600 사이즈로 생성된다.

    +

    ./600.png

    +

    사이즈 변경의 이유

    +

    255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

    +

    주요 클래스

    +

    요약

    +
    클래스명설명특이사항
    Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
    CoordinatesCoordinate의 일급 컬렉션-
    Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
    PositionsPositions의 일급 컬렉션-
    RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
    RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
    RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
    BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
    Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
    +

    의존관계

    + +

    Coordinates(위도, 경도의 일급 컬렉션)

    +

    List<Double> 2개(위도, 경도)인 형태로 관리하는 방법이 있었지만, 위치 점을 여러개 찍는 부분에서 로직이 복잡해 질 것 같아서 Coordinate(x, y)와 일급 컬렉션인 Coordinates로 관리하기로 했다.
    +Coordinates 클래스에는 다음 두 개의 인터페이스가 존재한다.

      -
    • Python의 Matplotlib
    • -
    • AWT(Abstract Window Toolkit) [최종 선택]
    • -
    • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
    • -
    • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)
    • +
    • calculatePositions: 경로 이미지의 크기를 받아 실제 이미지 생성시 사용될 Positions를 반환
    • +
    • indexOf: 다른 Coordinates를 받아 동일한 위치점에 해당하는 인덱스를 반환하는
    -

    Python & Matplotlib

    -

    데이터 시각화 라이브러리
    -이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

    +

    Positions 계산 로직은 다음과 같다.
    +위도, 경도 각각에 대한 부분을 이미지 생성시 필요한 값으로 변환한다.

    +
    // 호출
    +// List<Integer> xPositions = toPositions(xValues, maxDifference, routeImageSize);
    +// List<Integer> yPositions = toPositions(yValues, maxDifference, routeImageSize);
    +
    +private List<Integer> toPositions(List<Double> values, Double maxDifference, Integer routeImageSize) {
    +    Double minValue = Collections.min(values);
    +    return values.stream()
    +            .map(value -> normalizeCoordinate(value, maxDifference, minValue))
    +            .map(value -> mapToPosition(value, routeImageSize))
    +            .toList();
    +}
    +
    +private double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {
    +    return (coordinate - minValue) / maxDifference;
    +}
    +
    +private int mapToPosition(Double coordinate, Integer routeImageSize) {
    +    return (int) (coordinate * routeImageSize);
    +}
    +
    +

    위도로 예시든 내용이다.

    +
      +
    1. Collections.min(values) → 위도 리스트의 최소값을 구한다.
    2. +
    3. normalizeCoordinate → 각각의 위도 값에서 최소값을 빼고 0 ~ 1 사이 값으로 변환 후 위경도의 최대 차이로 나눈다.
    4. +
    5. mapToPosition → 그래프 크기를 받아 0 ~ 1 사이 값을 실제 이미지를 위한 위치값으로 변환한다.
    6. +
    +

    Positions(실제 이미지 생성에 사용할 위치)

    +

    Positions 클래스에는 다음 다섯 개의 인터페이스가 존재한다.

      -
    • 코드가 간단해서 유지 보수성이 좋다.
    • -
    • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
    • -
    • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.
    • +
    • align: 이미지 사이즈와 경로 이미지 사이즈를 받아 Position 값들을 중앙 정렬한다.
    • +
    • getPositionsByIndexes: 인덱스 리스트를 받아 입력받은 인덱스에 해당하는 값들을 반환한다.
    • +
    • size: 크기를 반환한다.
    • +
    • xPositions: x 값들을 반환한다.
    • +
    • yPositions: y 값들을 반환한다.
    -

    Java AWT 이외의 라이브러리

    -

    Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

    -
    라이브러리설명제외 이유
    SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
    JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
    simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
    matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
    -

    Java & AWT(Abstract Window Toolkit)

    -

    그래픽과 이미지를 그리기 위한 도구
    -이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

    +

    중앙 정렬 로직은 다음과 같다.

    +
    public Positions align(int imageSize, int routeSize) {
    +    int xOffset = calculateOffset(Position::x, imageSize);
    +    int yOffset = calculateOffset(Position::y, imageSize);
    +
    +    return items.stream()
    +            .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))
    +            .collect(collectingAndThen(toList(), Positions::new));
    +}
    +
    +private int calculateOffset(ToIntFunction<Position> positionToInteger, int imageSize) {
    +    List<Integer> positions = items.stream()
    +            .mapToInt(positionToInteger)
    +            .boxed()
    +            .toList();
    +
    +    int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;
    +    return imageSize / 2 - midValue;
    +}
    +
    +

    상하좌우 여백을 동일하게 주기 위해서 offset 값을 구해서 x, y 값에 각각 더하는 형태로 중앙 정렬을 수행했다.
    +BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

    +

    ./800.png

    +

    따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

    +

    x 값 → 계산한 offset 그대로 더한다.
    +y 값 → imageSize(800)에서 y + offset 값을 뺀다.

    +

    RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

    +

    BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
    +그림을 그리기 위해 설정한 상수들이 존재한다.

    +
    // RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
    +// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
    +// 이를 RGBA라고 부른다.
    +private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
    +// 배경 투명색
    +private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
    +// 경로를 위한 STROKE
    +private static final int LINE_STROKE_WIDTH = 7;
    +private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    +// 위치 점을 위한 STROKE
    +private static final int POINT_STROKE_WIDTH = 20;
    +private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
    +// 안티앨리어싱 등 화질 개선을 위한 설정
    +private static final Map<Object, Object> renderingHints = Map.of(
    +        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
    +        RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
    +        RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
    +);
    +
    +

    RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

      -
    • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
    • -
    • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
    • -
    • 추가적인 api 호출을 하지 않아도 된다.
    • +
    • drawLine: 선을 그린다.
    • +
    • drawPoint: 점을 찍는다.
    • +
    • dispose: 자원 할당을 해제한다.
    -

    기술 선택

    -

    AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
    -하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

    -

    유지 보수

    -

    AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
    -따라서 다음과 같은 방법으로 공유하기로 했다.

    -
      -
    1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
    2. -
    3. AWT를 사용한 부분을 문서화하여 공유한다.
    4. -
    -

    레벨 3를 마무리하며 내용 추가

    -

    기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
    -AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

    +

    dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

    +

    이미지 생성 Flow

    +

    1. 이미지 생성 준비

    + +

    2. 선 그리기 요청

    + +

    3. 위치 점 그리기 요청

    + +

    4. 업로드 요청

    + +

    전체 Flow

    +
    \ No newline at end of file diff --git a/tags/book.html b/tags/book.html index ff2cbb49a..de69db302 100644 --- a/tags/book.html +++ b/tags/book.html @@ -13,78 +13,49 @@ - - + + -

    "Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    책 정보

    +

    "Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    책 정보

    -

    상자 밖에 있는 사람
    -아빈저연구소

    +

    글, 우리도 잘 쓸 수 있습니다.
    +박솔미

    -

    자기기만과 자기배반

    -

    책에서는 자기기만과 자기배반에 대한 내용을 다룬다.

    -
      -
    • 자기기만: 자신의 문제를 인정하지 않는 것
    • -
    • 자기배반: 다른 사람을 위해 무언가 해야만 한다는 생각을 반하는 행위
    • -
    -

    자기배반을 한다면 자기기만 상태가 된다.
    -자기기만 상태에 빠지는 것을 책에서는 상자 안에 들어간다고 표현한다.

    읽고 나서

    -

    최근에 읽은 책 중 가장 마음이 불편했다.
    -그렇기에 더더욱 나에게 필요한 내용이 담겨있었다.

    -

    살면서 많은 선택의 순간이 존재했고, 그 순간마다 자기배반을 택하는 경우가 많았다.
    -작게는 집안일을 해야 하는데 몸이 조금 힘들다고 하지 않거나
    -크게는 잘못을 인정해야 하는 상황에서 그러지 않은 경우가 있었다.
    -이런 상황이 반복되어 결국 상자 안에 나 자신을 가두는 경우가 많았다.

    -

    더 나은 삶을 위해 내가 상자 안에 있는지 지속적으로 확인하고, 상자 밖으로 나가려는 연습을 해야겠다.
    -넓은 시선을 가지고, 항상 내가 틀릴 수 있다는 것을 생각하고 살아가자.

    +

    저자의 경험과 함께 글쓰기에 대한 가벼운 조언이 담겨있어 가볍게 읽기 좋았다.
    +글을 잘 작성해 보고 싶을 때 적용해 볼 수 있는 정보가 많아서 도움이 되었다.

    +

    우아한 테크코스의 프리코스를 진행할 때 후기를 작성하고 나면 항상 글이 딱딱하다는 느낌을 받았다.
    +다른 지원자들의 읽기 편하고, 밝은 느낌을 주는 글을 보면 부러운 마음을 가지기도 했다.
    +이 책을 읽었으니 2023년에는 조금 더 글을 잘 적어보려고 한다.

    밑줄 친 문장들

    -

    우리의 생각은 지식보다 작다.
    -우리의 지식은 사랑보다 작다.
    -우리의 사랑은 존재보다 작다.
    -그리고 우리가 생각하는 나는 실제의 나보다 그만큼 작다.
    -R. D. 랭
    -p.19

    +

    문장이 심심하고 지루하다면 +내용을 일목요연하게 정리했고, 글의 의도도 삐뚤지 않고, 단어도 적절한 것으로 골랐는데… 그런데도 어딘가가 심심하고 지루하다면? 축축 처지고 따분하다면? 말꼬리를 모조리 ‘~다’로 통일한 건 아닌지 점검해 보세요.

    -

    우리가 외적으로 어떤 행동을 하든지 간에, 사람들은 우리 마음에서 그들을 어떻게 대하고 있는지에 따라 주로 반응합니다.
    -우리가 사람들에 대해 어떻게 느끼게 되는지는 우리가 상자 안에 있는지 혹은 상자 밖에 있는지에 따라 달라지게 됩니다.
    -p.66

    +

    말꼬리를 잘 갖고 놀아야 합니다. 문장의 마지막 글자를 매번 다르게 고쳐쓰는 것만으로도 글에 활기를 더할 수 있죠. 때론 문장을 다 마치지 않고, 단어로만 끝맺는 것도 방법. 문장과 문장 사이에 쉼표가 들어서며 글 전체에 활기가 돌게 돼요. 문장의 길이도 다채로워지는 덕분에 덤으로 얻게 되는 것도 있습니다. 바로, 글의 리듬.

    -

    비난은 감정에 속하고 낙관은 의지에 속한다.
    -인간은 감정보다 더 큰 존재이다.
    -알랭, 탁닛한
    -p.103

    +

    이전 문장에서 끝난 글자로, 다음 문장을 끝맺지 않기. 한두 문단마다 단어 수준의 아주 짧은 문장 배치하기.

    -

    우리가 자신에게만 집중하고 있는 한, 혼자서 일하는 것 이상의 창조적인 결과나 협력을 이끌어 낸다는 것은 불가능합니다.
    -오늘날 경제 환경에서는 혼자서는 일의 결과를 탁월하게 만들어 내기가 어렵습니다.
    -내가 중심이어야 된다는 폐쇄적인 사고는 함께 일하는 사람들의 열정을 불러오지 못합니다.
    -p.175

    +

    글의 진짜 이유, 글의 진짜 목적, 글의 진짜 대상을 찾으려고 애썼습니다. 지금처럼 틀을 떠올린다거나, 눈치를 본다거나, 정치적인 셈도 하지 않았어요.

    -

    솔직함은 우리의 문제를 해결하는 열쇠입니다.
    -그것은 자신의 행동과 관련된 사람에 대해 기꺼이 사과를 하는 것입니다.
    -그것만이 실타래처럼 엉킨 관계의 문제를 해결할 수 있기 때문이죠.
    -p.188

    +

    제목은 짧게, 보기 쉽게, 읽기 쉽게, 발음이 비슷하게, 순서를 바꿔서

    -

    누군가를 나와 같이 동일한 가치를 지닌 한 인간으로 생각해서 그 사람을 위해 내가 상자 밖에 계속 머무르고 싶은 열망이 생길 때, 나는 이미 그 사람에 대해 상자 밖에 있다.
    -p.214

    +

    글을 마지막으로 다듬을 때, 노래에 가까워질 방법은 없을지 고민해봅니다. 감히 가 닿을 수 없는 목표이겠지만, 할 수 있는 최소한의 리듬이라도 붙여주고 싶어요.

    -

    대부분의 사람들이 관계 기술을 가지고 그들이 겪고 있는 문제를 바로잡으려고 하는 노력이 결실을 얻지 못하는 것은 결코 그러한 기술 부족 때문에 생기는 것이 아닙니다.
    -그것들은 자기배반 때문에 생겨납니다.
    -p.224

    +

    여는 말과 마지막 말에 작정하고 마음을 담는 연습을 해봅시다. 글의 어느 구석이라도 뻔한 글자는 남기지 않겠노라 다짐하며 써보는 겁니다. 나만이 가진 유일한 메시지에 집중하면서요. 그럼 생각이 달라지고, 고르는 단어도 달라지고, 남긴 문장도 달라져요. 결국에는 글을 쓴 사람인 나 자신도 남달라질 겁니다.

    -

    우리는 함께 일하고 우리와 함께 살아가는 사람이 진정으로 누구인지 알지 못합니다.
    -우리가 그들과 진정으로 함께 소통하기 전까지는 우리는 그들의 가치를 잘 모릅니다.
    -우리의 위대함이란 다른 사람들의 위대한 점을 발견해 주는 것에 있습니다.
    -p.280

    +

    맞춤법은 중요합니다. 하지만 맞춤법보다 더 중요한 건 거기에 담긴 마음입니다. 내 마음을 글에 담아 실어 보내기 전, 맞춤법을 점검하는 이유 역시 그겁니다. 오직 내 마음이 남에게 읽히는 동안 방해가 되지 않기를 바라기 때문이죠. 내가 쓴 글도, 남이 쓴 글도. 언제나 그 안에 담긴 마음이 먼저입니다.

    +
    +
    +

    글을 쓴다고 글이 완성되는 게 아니에요. 글과 닮은 모습으로 살 때, 글은 비로소 완성됩니다.

    \ No newline at end of file diff --git a/tags/book/page/2.html b/tags/book/page/2.html index 1a4b47295..1ffb296c5 100644 --- a/tags/book/page/2.html +++ b/tags/book/page/2.html @@ -13,11 +13,11 @@ - - + + -

    "Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    책 정보

    +

    "Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    책 정보

    객체지향의 사실과 오해
    조영호

    @@ -68,7 +68,7 @@

    밑줄 친 문장들

    시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법

    자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.

    객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.

    -

    객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다. +

    객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다. p.35

    diff --git a/tags/book/page/3.html b/tags/book/page/3.html index 4caa34776..c5b2cf50b 100644 --- a/tags/book/page/3.html +++ b/tags/book/page/3.html @@ -13,49 +13,78 @@ - - + + -

    "Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    책 정보

    +

    "Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    책 정보

    -

    글, 우리도 잘 쓸 수 있습니다.
    -박솔미

    +

    상자 밖에 있는 사람
    +아빈저연구소

    +

    자기기만과 자기배반

    +

    책에서는 자기기만과 자기배반에 대한 내용을 다룬다.

    +
      +
    • 자기기만: 자신의 문제를 인정하지 않는 것
    • +
    • 자기배반: 다른 사람을 위해 무언가 해야만 한다는 생각을 반하는 행위
    • +
    +

    자기배반을 한다면 자기기만 상태가 된다.
    +자기기만 상태에 빠지는 것을 책에서는 상자 안에 들어간다고 표현한다.

    읽고 나서

    -

    저자의 경험과 함께 글쓰기에 대한 가벼운 조언이 담겨있어 가볍게 읽기 좋았다.
    -글을 잘 작성해 보고 싶을 때 적용해 볼 수 있는 정보가 많아서 도움이 되었다.

    -

    우아한 테크코스의 프리코스를 진행할 때 후기를 작성하고 나면 항상 글이 딱딱하다는 느낌을 받았다.
    -다른 지원자들의 읽기 편하고, 밝은 느낌을 주는 글을 보면 부러운 마음을 가지기도 했다.
    -이 책을 읽었으니 2023년에는 조금 더 글을 잘 적어보려고 한다.

    +

    최근에 읽은 책 중 가장 마음이 불편했다.
    +그렇기에 더더욱 나에게 필요한 내용이 담겨있었다.

    +

    살면서 많은 선택의 순간이 존재했고, 그 순간마다 자기배반을 택하는 경우가 많았다.
    +작게는 집안일을 해야 하는데 몸이 조금 힘들다고 하지 않거나
    +크게는 잘못을 인정해야 하는 상황에서 그러지 않은 경우가 있었다.
    +이런 상황이 반복되어 결국 상자 안에 나 자신을 가두는 경우가 많았다.

    +

    더 나은 삶을 위해 내가 상자 안에 있는지 지속적으로 확인하고, 상자 밖으로 나가려는 연습을 해야겠다.
    +넓은 시선을 가지고, 항상 내가 틀릴 수 있다는 것을 생각하고 살아가자.

    밑줄 친 문장들

    -

    문장이 심심하고 지루하다면 -내용을 일목요연하게 정리했고, 글의 의도도 삐뚤지 않고, 단어도 적절한 것으로 골랐는데… 그런데도 어딘가가 심심하고 지루하다면? 축축 처지고 따분하다면? 말꼬리를 모조리 ‘~다’로 통일한 건 아닌지 점검해 보세요.

    +

    우리의 생각은 지식보다 작다.
    +우리의 지식은 사랑보다 작다.
    +우리의 사랑은 존재보다 작다.
    +그리고 우리가 생각하는 나는 실제의 나보다 그만큼 작다.
    +R. D. 랭
    +p.19

    -

    말꼬리를 잘 갖고 놀아야 합니다. 문장의 마지막 글자를 매번 다르게 고쳐쓰는 것만으로도 글에 활기를 더할 수 있죠. 때론 문장을 다 마치지 않고, 단어로만 끝맺는 것도 방법. 문장과 문장 사이에 쉼표가 들어서며 글 전체에 활기가 돌게 돼요. 문장의 길이도 다채로워지는 덕분에 덤으로 얻게 되는 것도 있습니다. 바로, 글의 리듬.

    +

    우리가 외적으로 어떤 행동을 하든지 간에, 사람들은 우리 마음에서 그들을 어떻게 대하고 있는지에 따라 주로 반응합니다.
    +우리가 사람들에 대해 어떻게 느끼게 되는지는 우리가 상자 안에 있는지 혹은 상자 밖에 있는지에 따라 달라지게 됩니다.
    +p.66

    -

    이전 문장에서 끝난 글자로, 다음 문장을 끝맺지 않기. 한두 문단마다 단어 수준의 아주 짧은 문장 배치하기.

    +

    비난은 감정에 속하고 낙관은 의지에 속한다.
    +인간은 감정보다 더 큰 존재이다.
    +알랭, 탁닛한
    +p.103

    -

    글의 진짜 이유, 글의 진짜 목적, 글의 진짜 대상을 찾으려고 애썼습니다. 지금처럼 틀을 떠올린다거나, 눈치를 본다거나, 정치적인 셈도 하지 않았어요.

    +

    우리가 자신에게만 집중하고 있는 한, 혼자서 일하는 것 이상의 창조적인 결과나 협력을 이끌어 낸다는 것은 불가능합니다.
    +오늘날 경제 환경에서는 혼자서는 일의 결과를 탁월하게 만들어 내기가 어렵습니다.
    +내가 중심이어야 된다는 폐쇄적인 사고는 함께 일하는 사람들의 열정을 불러오지 못합니다.
    +p.175

    -

    제목은 짧게, 보기 쉽게, 읽기 쉽게, 발음이 비슷하게, 순서를 바꿔서

    +

    솔직함은 우리의 문제를 해결하는 열쇠입니다.
    +그것은 자신의 행동과 관련된 사람에 대해 기꺼이 사과를 하는 것입니다.
    +그것만이 실타래처럼 엉킨 관계의 문제를 해결할 수 있기 때문이죠.
    +p.188

    -

    글을 마지막으로 다듬을 때, 노래에 가까워질 방법은 없을지 고민해봅니다. 감히 가 닿을 수 없는 목표이겠지만, 할 수 있는 최소한의 리듬이라도 붙여주고 싶어요.

    +

    누군가를 나와 같이 동일한 가치를 지닌 한 인간으로 생각해서 그 사람을 위해 내가 상자 밖에 계속 머무르고 싶은 열망이 생길 때, 나는 이미 그 사람에 대해 상자 밖에 있다.
    +p.214

    -

    여는 말과 마지막 말에 작정하고 마음을 담는 연습을 해봅시다. 글의 어느 구석이라도 뻔한 글자는 남기지 않겠노라 다짐하며 써보는 겁니다. 나만이 가진 유일한 메시지에 집중하면서요. 그럼 생각이 달라지고, 고르는 단어도 달라지고, 남긴 문장도 달라져요. 결국에는 글을 쓴 사람인 나 자신도 남달라질 겁니다.

    +

    대부분의 사람들이 관계 기술을 가지고 그들이 겪고 있는 문제를 바로잡으려고 하는 노력이 결실을 얻지 못하는 것은 결코 그러한 기술 부족 때문에 생기는 것이 아닙니다.
    +그것들은 자기배반 때문에 생겨납니다.
    +p.224

    -

    맞춤법은 중요합니다. 하지만 맞춤법보다 더 중요한 건 거기에 담긴 마음입니다. 내 마음을 글에 담아 실어 보내기 전, 맞춤법을 점검하는 이유 역시 그겁니다. 오직 내 마음이 남에게 읽히는 동안 방해가 되지 않기를 바라기 때문이죠. 내가 쓴 글도, 남이 쓴 글도. 언제나 그 안에 담긴 마음이 먼저입니다.

    -
    -
    -

    글을 쓴다고 글이 완성되는 게 아니에요. 글과 닮은 모습으로 살 때, 글은 비로소 완성됩니다.

    +

    우리는 함께 일하고 우리와 함께 살아가는 사람이 진정으로 누구인지 알지 못합니다.
    +우리가 그들과 진정으로 함께 소통하기 전까지는 우리는 그들의 가치를 잘 모릅니다.
    +우리의 위대함이란 다른 사람들의 위대한 점을 발견해 주는 것에 있습니다.
    +p.280

    \ No newline at end of file diff --git a/tags/class.html b/tags/class.html index e043889cb..d1664c68b 100644 --- a/tags/class.html +++ b/tags/class.html @@ -13,11 +13,11 @@ - - + + -

    "Class" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    클래스 파일

    +

    "Class" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    클래스 파일

    자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
    컴파일된 클래스파일은 어떤 구조로 되어있을까?

    클래스 파일의 데이터 형식

    @@ -59,8 +59,8 @@

    클래스 파일 포맷 버전

    class file format major versions

    Java SEReleasedMajorSupported majors
    8March 20145245 .. 52
    9September 20175345 .. 53
    10March 20185445 .. 54
    11September 20185545 .. 55
    12March 20195645 .. 56
    13September 20195745 .. 57
    14March 20205845 .. 58
    15September 20205945 .. 59
    16March 20216045 .. 60
    17September 20216145 .. 61

    상수 풀

    -

    2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
    -클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
    +

    2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
    +클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
    JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

    액세스 플래그

    클래스, 인터페이스와 같은 파일의 속성을 표시한다.
    diff --git a/tags/cloudwatch.html b/tags/cloudwatch.html index 648e9c8c6..5f3a63291 100644 --- a/tags/cloudwatch.html +++ b/tags/cloudwatch.html @@ -13,11 +13,11 @@ - - + + -

    "cloudwatch" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    CloudWatch

    +

    "cloudwatch" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    CloudWatch

    AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
    지표를 감시하여 알림을 보내는 기능도 제공한다.
    프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
    @@ -49,7 +49,7 @@

    설치

    사용 설명서에 각 인스턴스 유형마다 다운로드 링크가 자세하게 안내되어 있다.

    Wizard

    -

    CloudWatch Wizard를 사용하면 간단하게 설정 파일 생성할 수 있다.
    +

    CloudWatch Wizard를 사용하면 간단하게 설정 파일 생성할 수 있다.
    로그를 수집하도록 설정하는 경우 Wizard 실행 명령어 입력 전 log 파일의 절대 경로를 복사해두는 것이 좋다.
    아래의 명령어를 입력하여 Wizard를 실행할 수 있다.

    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
    diff --git a/tags/composite.html b/tags/composite.html
    index 6d52081ed..2121b3a87 100644
    --- a/tags/composite.html
    +++ b/tags/composite.html
    @@ -13,11 +13,11 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "Composite" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    요구사항

    +

    "Composite" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    요구사항

    지하철 미션에는 다음과 같은 요구사항이 있었다.

    • 거리별 추가 요금 정책
    • @@ -36,7 +36,7 @@

      인터페이스 사용

      public class AgeDiscountFarePolicy implements FarePolicy { ... }

    composite1

    -

    모든 요금 정책을 포함하는 새로운 요금 정책 만들기

    +

    모든 요금 정책을 포함하는 새로운 요금 정책 만들기

    나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
    이 또한 FarePolicy를 구현한 형태가 되고, 필드로는 나머지 구현체들을 가지고 있다.

    public class SubwayFarePolicy implements FarePolicy {
    @@ -112,7 +112,7 @@ 

    컴포지트 패턴의

    패턴 사용시 주의해야할 부분

    패턴은 공통으로 사용 가능한 역할, 책임, 협력의 템플릿이다.
    반복되는 문제를 효율적으로 해결할 수 있지만 패턴에 매몰되서는 안된다.
    -패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
    +패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
    항상 트레이드오프를 생각하자!

    참고 자료

    컴포지트 패턴, GoF의 디자인 패턴
    diff --git a/tags/data-base.html b/tags/data-base.html index c015ba31f..b2a3064f4 100644 --- a/tags/data-base.html +++ b/tags/data-base.html @@ -13,68 +13,138 @@ - - + + -

    "DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    InnoDB 스토리지 엔진의 잠금

    -

    MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
    -보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

    -

    동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
    -InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

    -

    트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

    -

    트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
    -일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

    -

    Shared & Exclusive Locks

    -

    InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

    -

    공유 잠금(S, shared lock)

    -

    데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
    -다른 트랜잭션에서 읽기가 가능하지만, 쓰기는 불가능하다.
    -예) SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;

    -

    배타적 잠금(X, exclusive lock)

    -

    데이터 변경을 위한 락, 쓰기 잠금(write lock)으로도 불린다.
    -락을 건 트랜잭션만이 해당 데이터에 접근 가능하다. 다른 트랜잭션의 경우 읽기, 쓰기가 불가능하다.
    -예) SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

    -

    Intention Locks

    -

    InnoDB는 로우 단위 잠금과 테이블 잠금의 공존을 위해 인텍션 잠금을 지원한다.
    -테이블에 있는 로우에 대해서 나중에 요청되는 것이 어떤 형태의 잠금인지 가리키기 위해 사용된다.
    -기본적으로 로우 단위 잠금을 수행하기 전에 인텐션 잠금을 먼저 획득한다.
    -인텐션 락은 기본적으로 충돌을 방지하고 데드락을 방지하는 역할을 한다.

    -

    인텐션 공유 잠금(IS, intention shared lock)

    -

    트랜잭션이 테이블의 개별 로우에 대한 공유 잠금을 수행하는 것을 의미한다.

    -

    인텐션 배타적 잠금(IX, intention exclusive lock)

    -

    트랜잭션이 테이블의 개별 로우에 대한 배타적 잠금을 수행하는 것을 의미한다.

    -

    ** 잠금간의 호환성 **

    -
    XIXSIS
    XConflictConflictConflictConflict
    IXConflictCompatibleConflictCompatible
    SConflictConflictCompatibleCompatible
    ISConflictCompatibleCompatibleCompatible
    -

    Record Locks

    -

    레코드 자체만을 잠그는 락이다.
    -InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다.

    -

    Gap Locks

    -

    레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    -레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하고, 넥스트 키 락의 일부로 사용된다.

    -

    Next-Key Locks

    -

    레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.
    -REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하기 위한 잠금이다.

    -

    AUTO-INC Locks

    -

    AUTO_INCREMENT 칼림이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 한다.
    -InnoDB 는 내부적으로 AUTO-INC 락이라고 하는 테이블 수준의 잠금을 사용한다.
    -트랜잭션과 관계 없이 INSERTREPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 해제된다.

    -

    잠금 예시

    -
    -- 레코드는 id 기준 10, 20, 30, 40, 50이 있다고 가정
    --- Record Locks: 10에 대해 락이 걸린다.
    -SELECT * FROM table_name where id = 10 for update;
    -
    --- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다.
    -SELECT * FROM table_name where id > 100 for update;
    -
    --- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다.
    -SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;
    -
    +

    "DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    트랜잭션(Transaction)

    +

    데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
    +트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
    +논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

    +

    트랜잭션의 속성(ACID)

    +

    원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
    +일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
    +격리성(Isolation): 각각의 트랜잭션은 독립적이라 서로에게 영향을 주지 않아야 한다.
    +지속성(Durability): 트랜잭션이 성공적으로 완료된다면 영구적으로 결과에 반영되어야 한다.

    +

    트랜잭션 주의사항

    +

    트랜잭션은 꼭 필요한 최소의 코드에만 적용하는 것이 좋다.(트랜잭션의 범위를 최소화하라)
    +구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

    +

    데이터의 일관성과 안전성을 보장하기 위해 배제해야 한다.
    +네트워크 작업을 트랜잭션 내부에 포함한다면 다음과 같은 문제가 발생할 수 있다.

      +
    • 네트워크 작업이 중간에 실패할 가능성(안전성 X)
    • +
    • 통신으로 인해 데이터가 변경될 수 있는 부분(일관성 X)
    • +
    +

    격리 수준(Isolation level)

    +

    여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 데이터의 조회 및 변경을 허용할지 결정하는 것을 말한다.
    +격리 수준이 높아질 수록 동시 처리 성능이 떨어지는 것이 일반적이지만, SERIALIZABLE이 아니라면 크게 성능의 저하가 발생하지 않는다.

    +

    READ UNCOMMITTED

    +

    각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다.
    +더티 리드 현상이 발생하기 때문에 정합성의 문제가 많은 격리 수준이다.
    +MySQL 사용시 최소 READ COMMITTED 이상의 격리 수준 사용을 권장한다.

    + +

    READ COMMITTED

    +

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    +오라클 DBMS에서 기본으로 사용되는 격리 수준이다.
    +REPEATABLE READ가 보장되지 않기 때문에 NON-REPEATABLE READ 문제가 발생한다.

    + +

    REPEATABLE READ

    +

    트랜잭션이 시작되기 전에 COMMIT이 완료된 내용에 대해서만 조회할 수 있다.
    +MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준이다.
    +MVCC를 이용해 언두(Undo) 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장한다.
    +동일한 결과를 보장하는 방법은 다음과 같다.

    +
      +
    • 모든 InnoDB 트랜잭션은 순차적으로 증가하는 고유한 트랜잭션 번호를 가진다.
    • +
    • Undo 영역에 백업된 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함되어있다.
    • +
    • Undo 영역의 백업된 데이터는 스토리지 엔진이 불필요하다고 판단하는 경우 삭제된다.
    • +
    • REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 가장 오래된 트랜잭션 번호보다 앞선 Undo 영역의 데이터는 삭제하지 않는다.
    • +
    +

    InnoDB에서는 갭 락과 넥스트 키 락을 이용하여 팬텀 리드 현상을 방지한다.

    + +

    갭 락: 레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    +넥스트 키 락: 레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.

    +

    동시성을 제어하는 방법 중 하나로 하나의 레코드에 대해 여러 개의 버전이 동시에 관리되는 것이다.

      +
    • PostgreSQL은 다중 버전의 데이터를 저장하는 것으로 MVCC를 구현한다.
    • +
    • Oracle, InnoDB는 Undo log를 이용해 이 기능을 구현한다.(최신 버전의 데이터만 DB에 저장)
    • +

    잠금을 사용하지 않는 읽관된 읽기를 제공하는 것이 목적이다.

    +

    SERIALIZABLE

    +

    트랜잭션을 순차적으로 진행시키는 격리 수준이고 따라서 동시 처리 성능도 다른 격리 수준보다 떨어진다.
    +트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 접근할 수 없고 단순한 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야만 한다.
    +InnoDB에서는 팬텀 리드 현상이 REPEATABLE READ 격리 수준에서 발생하지 않기 때문에 굳이 사용할 필요는 없다.

    +

    격리 수준에 따른 부정합 문제

    +

    격리 수준에 따라 더티 리드, 반복 가능하지 않은 조회, 팬텀 리드 문제가 발생한다.

    +
    격리 수준 / 부정합 문제더티 리드반복 가능하지 않은 조회팬텀 리드
    READ UNCOMMITTEDOOO
    READ COMMITTEDXOO
    REPEATABLE READXXO(InnoDB는 X)
    SERIALIZABLEXXX
    +

    더티 리드(Dirty read)

    +

    어떤 트랜잭션에서 처리한 작업이 완료되지 않았어도 다른 트랜잭션에서 볼 수 있는 현상
    +트랜잭션 격리 수준이 READ UNCOMMITTED일 때 발생한다.
    +예) B가 레코드를 추가하고 커밋을 하지 않았지만, A가 해당 레코드를 조회할 수 있는 경우

    +

    반복 가능하지 않은 조회(Non-repeatable read)

    +

    한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 그 값이 다른 현상
    +예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

    + +

    팬텀 리드(Phantom read, Phantom row)

    +

    한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
    +예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

    +

    참고 자료

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    -Optimistic and Pessimistic record locking, IBM
    -MySQL Innodb Locks, cecil1018
    -MySQL 8.0 InnoDB Locks, MySQL
    -Locks Set by Different SQL Statements in InnoDB, MySQL

    +Isolation Level, MySQL

    \ No newline at end of file diff --git a/tags/data-base/page/2.html b/tags/data-base/page/2.html index 59328ea64..469933ca2 100644 --- a/tags/data-base/page/2.html +++ b/tags/data-base/page/2.html @@ -13,11 +13,11 @@ - - + + -

    "DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    MySQL 엔진의 잠금

    +

    "DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    MySQL 엔진의 잠금

    MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
    MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

    글로벌 락(Global lock)

    @@ -70,7 +70,7 @@

    네임드 락(Named lock)

    SELECT RELEASE_ALL_LOCKS();

    메타데이터 락(Metadata lock)

    -

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    +

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    -- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
    diff --git a/tags/data-base/page/3.html b/tags/data-base/page/3.html
    index 82b01cbfa..7a0aaabe6 100644
    --- a/tags/data-base/page/3.html
    +++ b/tags/data-base/page/3.html
    @@ -13,138 +13,68 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    트랜잭션(Transaction)

    -

    데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
    -트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
    -논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

    -

    트랜잭션의 속성(ACID)

    -

    원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
    -일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
    -격리성(Isolation): 각각의 트랜잭션은 독립적이라 서로에게 영향을 주지 않아야 한다.
    -지속성(Durability): 트랜잭션이 성공적으로 완료된다면 영구적으로 결과에 반영되어야 한다.

    -

    트랜잭션 주의사항

    -

    트랜잭션은 꼭 필요한 최소의 코드에만 적용하는 것이 좋다.(트랜잭션의 범위를 최소화하라)
    -구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

    -

    데이터의 일관성과 안전성을 보장하기 위해 배제해야 한다.
    -네트워크 작업을 트랜잭션 내부에 포함한다면 다음과 같은 문제가 발생할 수 있다.

      -
    • 네트워크 작업이 중간에 실패할 가능성(안전성 X)
    • -
    • 통신으로 인해 데이터가 변경될 수 있는 부분(일관성 X)
    • -
    -

    격리 수준(Isolation level)

    -

    여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 데이터의 조회 및 변경을 허용할지 결정하는 것을 말한다.
    -격리 수준이 높아질 수록 동시 처리 성능이 떨어지는 것이 일반적이지만, SERIALIZABLE이 아니라면 크게 성능의 저하가 발생하지 않는다.

    -

    READ UNCOMMITTED

    -

    각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다.
    -더티 리드 현상이 발생하기 때문에 정합성의 문제가 많은 격리 수준이다.
    -MySQL 사용시 최소 READ COMMITTED 이상의 격리 수준 사용을 권장한다.

    - -

    READ COMMITTED

    -

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    -오라클 DBMS에서 기본으로 사용되는 격리 수준이다.
    -REPEATABLE READ가 보장되지 않기 때문에 NON-REPEATABLE READ 문제가 발생한다.

    - -

    REPEATABLE READ

    -

    트랜잭션이 시작되기 전에 COMMIT이 완료된 내용에 대해서만 조회할 수 있다.
    -MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준이다.
    -MVCC를 이용해 언두(Undo) 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장한다.
    -동일한 결과를 보장하는 방법은 다음과 같다.

    -
      -
    • 모든 InnoDB 트랜잭션은 순차적으로 증가하는 고유한 트랜잭션 번호를 가진다.
    • -
    • Undo 영역에 백업된 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함되어있다.
    • -
    • Undo 영역의 백업된 데이터는 스토리지 엔진이 불필요하다고 판단하는 경우 삭제된다.
    • -
    • REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 가장 오래된 트랜잭션 번호보다 앞선 Undo 영역의 데이터는 삭제하지 않는다.
    • -
    -

    InnoDB에서는 갭 락과 넥스트 키 락을 이용하여 팬텀 리드 현상을 방지한다.

    - -

    갭 락: 레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    -넥스트 키 락: 레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.

    -

    동시성을 제어하는 방법 중 하나로 하나의 레코드에 대해 여러 개의 버전이 동시에 관리되는 것이다.

      -
    • PostgreSQL은 다중 버전의 데이터를 저장하는 것으로 MVCC를 구현한다.
    • -
    • Oracle, InnoDB는 Undo log를 이용해 이 기능을 구현한다.(최신 버전의 데이터만 DB에 저장)
    • -

    잠금을 사용하지 않는 읽관된 읽기를 제공하는 것이 목적이다.

    -

    SERIALIZABLE

    -

    트랜잭션을 순차적으로 진행시키는 격리 수준이고 따라서 동시 처리 성능도 다른 격리 수준보다 떨어진다.
    -트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 접근할 수 없고 단순한 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야만 한다.
    -InnoDB에서는 팬텀 리드 현상이 REPEATABLE READ 격리 수준에서 발생하지 않기 때문에 굳이 사용할 필요는 없다.

    -

    격리 수준에 따른 부정합 문제

    -

    격리 수준에 따라 더티 리드, 반복 가능하지 않은 조회, 팬텀 리드 문제가 발생한다.

    -
    격리 수준 / 부정합 문제더티 리드반복 가능하지 않은 조회팬텀 리드
    READ UNCOMMITTEDOOO
    READ COMMITTEDXOO
    REPEATABLE READXXO(InnoDB는 X)
    SERIALIZABLEXXX
    -

    더티 리드(Dirty read)

    -

    어떤 트랜잭션에서 처리한 작업이 완료되지 않았어도 다른 트랜잭션에서 볼 수 있는 현상
    -트랜잭션 격리 수준이 READ UNCOMMITTED일 때 발생한다.
    -예) B가 레코드를 추가하고 커밋을 하지 않았지만, A가 해당 레코드를 조회할 수 있는 경우

    -

    반복 가능하지 않은 조회(Non-repeatable read)

    -

    한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 그 값이 다른 현상
    -예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

    - -

    팬텀 리드(Phantom read, Phantom row)

    -

    한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
    -예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

    - +

    "DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    InnoDB 스토리지 엔진의 잠금

    +

    MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
    +보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

    +

    동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
    +InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

    +

    트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

    +

    트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
    +일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

    +

    Shared & Exclusive Locks

    +

    InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

    +

    공유 잠금(S, shared lock)

    +

    데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
    +다른 트랜잭션에서 읽기가 가능하지만, 쓰기는 불가능하다.
    +예) SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;

    +

    배타적 잠금(X, exclusive lock)

    +

    데이터 변경을 위한 락, 쓰기 잠금(write lock)으로도 불린다.
    +락을 건 트랜잭션만이 해당 데이터에 접근 가능하다. 다른 트랜잭션의 경우 읽기, 쓰기가 불가능하다.
    +예) SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

    +

    Intention Locks

    +

    InnoDB는 로우 단위 잠금과 테이블 잠금의 공존을 위해 인텍션 잠금을 지원한다.
    +테이블에 있는 로우에 대해서 나중에 요청되는 것이 어떤 형태의 잠금인지 가리키기 위해 사용된다.
    +기본적으로 로우 단위 잠금을 수행하기 전에 인텐션 잠금을 먼저 획득한다.
    +인텐션 락은 기본적으로 충돌을 방지하고 데드락을 방지하는 역할을 한다.

    +

    인텐션 공유 잠금(IS, intention shared lock)

    +

    트랜잭션이 테이블의 개별 로우에 대한 공유 잠금을 수행하는 것을 의미한다.

    +

    인텐션 배타적 잠금(IX, intention exclusive lock)

    +

    트랜잭션이 테이블의 개별 로우에 대한 배타적 잠금을 수행하는 것을 의미한다.

    +

    ** 잠금간의 호환성 **

    +
    XIXSIS
    XConflictConflictConflictConflict
    IXConflictCompatibleConflictCompatible
    SConflictConflictCompatibleCompatible
    ISConflictCompatibleCompatibleCompatible
    +

    Record Locks

    +

    레코드 자체만을 잠그는 락이다.
    +InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다.

    +

    Gap Locks

    +

    레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    +레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하고, 넥스트 키 락의 일부로 사용된다.

    +

    Next-Key Locks

    +

    레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.
    +REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하기 위한 잠금이다.

    +

    AUTO-INC Locks

    +

    AUTO_INCREMENT 칼림이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 한다.
    +InnoDB 는 내부적으로 AUTO-INC 락이라고 하는 테이블 수준의 잠금을 사용한다.
    +트랜잭션과 관계 없이 INSERTREPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 해제된다.

    +

    잠금 예시

    +
    -- 레코드는 id 기준 10, 20, 30, 40, 50이 있다고 가정
    +-- Record Locks: 10에 대해 락이 걸린다.
    +SELECT * FROM table_name where id = 10 for update;
    +
    +-- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다.
    +SELECT * FROM table_name where id > 100 for update;
    +
    +-- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다.
    +SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;
    +

    참고 자료

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    -Isolation Level, MySQL

    +Optimistic and Pessimistic record locking, IBM
    +MySQL Innodb Locks, cecil1018
    +MySQL 8.0 InnoDB Locks, MySQL
    +Locks Set by Different SQL Statements in InnoDB, MySQL

    \ No newline at end of file diff --git a/tags/documentation.html b/tags/documentation.html index c56299be5..3312b2107 100644 --- a/tags/documentation.html +++ b/tags/documentation.html @@ -13,11 +13,11 @@ - - + + -

    "Documentation" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 11분

    팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

    +

    "Documentation" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 11분

    팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

    설치

    공식 홈페이지에 들어가서 최신 버전을 설치한다.

    yarn create docusaurus
    @@ -27,7 +27,7 @@ 

    배포

    netlify나 vercel 같은 서버리스 플랫폼을 추천하고 있고, 간단하고, 빠른 시간 안에 배포를 할 수 있다.
    이 글에서는 github pages를 이용해서 배포하는 방법을 설명한다.

    레포지토리 생성

    -

    github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
    +

    github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
    이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

    설정 파일 수정

    module.exports = {
    diff --git a/tags/dto.html b/tags/dto.html
    index e589593e6..787948517 100644
    --- a/tags/dto.html
    +++ b/tags/dto.html
    @@ -13,11 +13,11 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "DTO" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
    +

    "DTO" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
    요청에 담긴 Body를 통해 전달받은 값을 DTO로 매핑하여 추가와 수정을 했다.

    장바구니 미션에서의 상품 추가 및 수정

    중복1

    @@ -26,7 +26,7 @@

    장바구니 미 위 경우는 중복일까? 중복이 아닐까?

    이 부분에 대해서 다음과 같은 리뷰를 받았다.

    -

    ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

    +

    ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

    질문에 대해 아래와 같이 답변을 했다.

    @@ -42,7 +42,7 @@

    중복과 우발적 중복

    그렇기 때문에 위 상황은 우발적 중복으로 보인다. 그래도 중복을 제거해볼 수 있지 않을까?

    하나로 사용하는 건 안좋아보이고, 중복은 제거하고 싶은 마음

    지금은 추가, 수정 2가지 경우 밖에 없지만 조금 더 복잡한 요구사항이 주어져서 10가지 경우로 입력을 받으면 어떻게 해야할까?
    -서비스 계층에서도 계층의 분리를 위해서 다른 DTO를 사용하고 있다면 20개의 DTO를 만들어야 할까?
    +서비스 계층에서도 계층의 분리를 위해서 다른 DTO를 사용하고 있다면 20개의 DTO를 만들어야 할까?
    리뷰어가 알려준 의존 역전을 이용한 방법을 통해 이를 해결해보자!

    중복 제거 전 코드

    현재 코드에서는 아래와 같은 구조로 되어있다.
    @@ -84,7 +84,7 @@

    인터페이스 작성하기

    }

    구현체 작성하기

    -

    중��복4

    +

    중복4

    위에서 작성한 인터페이스를 구현하는 클래스를 작성한다.
    요청은 ProductRequest 클래스로 받고, 서비스에 전달할 땐 해당 인터페이스의 명세만 맞추면 문제없이 사용할 수 있다.

    ├── controller
    diff --git a/tags/elastic-beanstalk.html b/tags/elastic-beanstalk.html
    index 1edcb7aab..cbdd2aeda 100644
    --- a/tags/elastic-beanstalk.html
    +++ b/tags/elastic-beanstalk.html
    @@ -13,11 +13,11 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "Elastic Beanstalk" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    설정 환경

    +

    "Elastic Beanstalk" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    설정 환경

    소프트웨어 이미지: Amazon Linux 2023 AMI
    아키텍쳐: ARM
    인스턴스 유형: t4g.small
    diff --git a/tags/event.html b/tags/event.html index de33ae880..d0db25c4a 100644 --- a/tags/event.html +++ b/tags/event.html @@ -13,11 +13,11 @@ - - + + -

    "event" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 12분

    이전 글

    +

    "event" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 12분

    이전 글

    경로 이미지 생성하기 - 기술 선택
    경로 이미지 생성하기 - 구현

    개요

    @@ -27,7 +27,7 @@

    개요

    주기능의 응답속도 개선

    여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
    하지만 현재 여행 종료와 감상 생성의 응답 속도가 경로 이미지 생성 시간에 영향을 받고 있다.
    -경로 이미지 생성은 비동기 처리하여도 애플리케이션 사용에 문제가 되지 않는다.
    +경로 이미지 생성은 비동기 처리하여도 애플리케이션 사용에 문제가 되지 않는다.
    소요 시간이 1초 이상 걸리는 경우가 존재하기에 이미지 생성을 비동기 처리하고 여행 종료와 감상 생성 기능의 응답 시간을 개선하는 것이 더 중요하다.

    확장성 대비

    현재 10분 간격으로 위치 정보를 서버에 저장하고 있다.
    diff --git a/tags/exception.html b/tags/exception.html index 8e97acab6..cc9ccd80d 100644 --- a/tags/exception.html +++ b/tags/exception.html @@ -13,16 +13,16 @@ - - + + -

    "exception" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    문제 상황

    +

    "exception" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    문제 상황

    현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
    확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

    비동기 예외 발생시 로깅 설정

    스프링 4.1 부터 제공되는 AsyncUncaughtExceptionHandler의 경우 반환 타입이 void인 비동기 메서드를 예외 처리하기 쉽도록 도와준다.

    -

    따라서 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 핸들링하는 클래스를 생성했다.
    +

    따라서 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 핸들링하는 클래스를 생성했다.
    기존의 동기 예외 처리의 경우 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다.
    비동기 예외 처리도 마찬가지로 MDC의 정보를 가져와서 로그를 출력하도록 설정했다.

    @Slf4j
    diff --git a/tags/grasp.html b/tags/grasp.html
    index f5c796db0..aee3e7d96 100644
    --- a/tags/grasp.html
    +++ b/tags/grasp.html
    @@ -13,11 +13,11 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "GRASP" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 9분

    GRASP(General Responsibility Assignment Software Pattern)

    +

    "GRASP" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 9분

    GRASP(General Responsibility Assignment Software Pattern)

    크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

    각 패턴마다 Solution과 Problem로 구성되어 있다.

    정보 전문가 패턴(Information Expert)

    @@ -29,7 +29,7 @@

    창조자 패턴(Creator)

    Q: 누가 객체 A를 생성하는가?

    A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

      -
    • B가 A 객체를 포함 또는 참조한다.
    • +
    • B가 A 객체를 포함 또는 참조한다.
    • B가 A 객체를 기록한다.
    • B가 A 객체를 긴밀하게 사용한다.
    • B가 A 객체의 초기값을 가지고 있다.
    • @@ -67,7 +67,7 @@

      높은 응집도 패턴(High Cohes

      변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

        -
      • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
      • +
      • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
      • 유지보수가 쉬워진다.
      • 낮은 결합도 또한 지원한다.
      • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.
      • @@ -90,8 +90,8 @@

        변경 보호 패턴(Protected

        Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

        A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

        간접 참조 패턴(Indirection)

        -

        Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

        -

        A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

        +

        Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

        +

        A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

        중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

        중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

        순수한 가공물 패턴(Pure Fabrication)

        diff --git a/tags/image.html b/tags/image.html index 3cc08313b..56fc39d64 100644 --- a/tags/image.html +++ b/tags/image.html @@ -13,201 +13,60 @@ - - + + -

        "image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

        모든 태그 보기

        · 약 12분

        개요

        -

        여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
        -경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

        -

        구현 결과

        -

        ./result.png

        -

        예시 데이터는 다음과 같다.
        -서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

        -
        List<Double> x = List.of(
        -        126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
        -        126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
        -);
        -List<Double> y = List.of(
        -        37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
        -        37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
        -);
        -List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
        -List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);
        -
        -

        IMAGE_SIZE & ROUTE_SIZE

        -
        private static final int IMAGE_SIZE = 800;
        -private static final int ROUTE_SIZE = 600;
        -
        -

        코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
        -IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
        -ROUTE_SIZE의 경우 상하좌우 100px 만큼의 간격을 위해 존재한다.
        -따라서 실제 경로 이미지의 크기는 600 * 600 사이즈로 생성된다.

        -

        ./600.png

        -

        사이즈 변경의 이유

        -

        255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

        -

        주요 클래스

        -

        요약

        -
        클래스명설명특이사항
        Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
        CoordinatesCoordinate의 일급 컬렉션-
        Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
        PositionsPositions의 일급 컬렉션-
        RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
        RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
        RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
        BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
        Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
        -

        의존관계

        - -

        Coordinates(위도, 경도의 일급 컬렉션)

        -

        List<Double> 2개(위도, 경도)인 형태로 관리하는 방법이 있었지만, 위치 점을 여러개 찍는 부분에서 로직이 복잡해 질 것 같아서 Coordinate(x, y)와 일급 컬렉션인 Coordinates로 관리하기로 했다.
        -Coordinates 클래스에는 다음 두 개의 인터페이스가 존재한다.

        +

        "image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

        모든 태그 보기

        · 약 6분

        ./route.png

        +

        이미지 생성의 책임

        +

        위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
        +따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

        +

        해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

          -
        • calculatePositions: 경로 이미지의 크기를 받아 실제 이미지 생성시 사용될 Positions를 반환
        • -
        • indexOf: 다른 Coordinates를 받아 동일한 위치점에 해당하는 인덱스를 반환하는
        • +
        • 이미지 생성
        • +
        • 선과 점 표현
        • +
        • 투명한 배경색
        -

        Positions 계산 로직은 다음과 같다.
        -위도, 경도 각각에 대한 부분을 이미지 생성시 필요한 값으로 변환한다.

        -
        // 호출
        -// List<Integer> xPositions = toPositions(xValues, maxDifference, routeImageSize);
        -// List<Integer> yPositions = toPositions(yValues, maxDifference, routeImageSize);
        -
        -private List<Integer> toPositions(List<Double> values, Double maxDifference, Integer routeImageSize) {
        -    Double minValue = Collections.min(values);
        -    return values.stream()
        -            .map(value -> normalizeCoordinate(value, maxDifference, minValue))
        -            .map(value -> mapToPosition(value, routeImageSize))
        -            .toList();
        -}
        -
        -private double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {
        -    return (coordinate - minValue) / maxDifference;
        -}
        -
        -private int mapToPosition(Double coordinate, Integer routeImageSize) {
        -    return (int) (coordinate * routeImageSize);
        -}
        -
        -

        위도로 예시든 내용이다.

        -
          -
        1. Collections.min(values) → 위도 리스트의 최소값을 구한다.
        2. -
        3. normalizeCoordinate → 각각의 위도 값에서 최소값을 빼고 0 ~ 1 사이 값으로 변환 후 위경도의 최대 차이로 나눈다.
        4. -
        5. mapToPosition → 그래프 크기를 받아 0 ~ 1 사이 값을 실제 이미지를 위한 위치값으로 변환한다.
        6. -
        -

        Positions(실제 이미지 생성에 사용할 위치)

        -

        Positions 클래스에는 다음 다섯 개의 인터페이스가 존재한다.

        +

        현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

        +

        고려한 기술

        +

        백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

          -
        • align: 이미지 사이즈와 경로 이미지 사이즈를 받아 Position 값들을 중앙 정렬한다.
        • -
        • getPositionsByIndexes: 인덱스 리스트를 받아 입력받은 인덱스에 해당하는 값들을 반환한다.
        • -
        • size: 크기를 반환한다.
        • -
        • xPositions: x 값들을 반환한다.
        • -
        • yPositions: y 값들을 반환한다.
        • +
        • Python의 Matplotlib
        • +
        • AWT(Abstract Window Toolkit) [최종 선택]
        • +
        • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
        • +
        • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)
        -

        중앙 정렬 로직은 다음과 같다.

        -
        public Positions align(int imageSize, int routeSize) {
        -    int xOffset = calculateOffset(Position::x, imageSize);
        -    int yOffset = calculateOffset(Position::y, imageSize);
        -
        -    return items.stream()
        -            .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))
        -            .collect(collectingAndThen(toList(), Positions::new));
        -}
        -
        -private int calculateOffset(ToIntFunction<Position> positionToInteger, int imageSize) {
        -    List<Integer> positions = items.stream()
        -            .mapToInt(positionToInteger)
        -            .boxed()
        -            .toList();
        -
        -    int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;
        -    return imageSize / 2 - midValue;
        -}
        -
        -

        상하좌우 여백을 동일하게 주기 위해서 offset 값을 구해서 x, y 값에 각각 더하는 형태로 중앙 정렬을 수행했다.
        -BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

        -

        ./800.png

        -

        따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

        -

        x 값 → 계산한 offset 그대로 더한다.
        -y 값 → imageSize(800)에서 y + offset 값을 뺀다.

        -

        RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

        -

        BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
        -그림을 그리기 위해 설정한 상수들이 존재한다.

        -
        // RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
        -// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
        -// 이를 RGBA라고 부른다.
        -private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
        -// 배경 투명색
        -private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
        -// 경로를 위한 STROKE
        -private static final int LINE_STROKE_WIDTH = 7;
        -private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
        -// 위치 점을 위한 STROKE
        -private static final int POINT_STROKE_WIDTH = 20;
        -private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
        -// 안티앨리어싱 등 화질 개선을 위한 설정
        -private static final Map<Object, Object> renderingHints = Map.of(
        -        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
        -        RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
        -        RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
        -);
        -
        -

        RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

        +

        Python & Matplotlib

        +

        데이터 시각화 라이브러리
        +이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

          -
        • drawLine: 선을 그린다.
        • -
        • drawPoint: 점을 찍는다.
        • -
        • dispose: 자원 할당을 해제한다.
        • +
        • 코드가 간단해서 유지 보수성이 좋다.
        • +
        • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
        • +
        • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.
        -

        dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

        -

        이미지 생성 Flow

        -

        1. 이미지 생성 준비

        - -

        2. 선 그리기 요청

        - -

        3. 위치 점 그리기 요청

        - -

        4. 업로드 요청

        - -

        전체 Flow

        -
        +

        Java AWT 이외의 라이브러리

        +

        Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

        +
        라이브러리설명제외 이유
        SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
        JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
        simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
        matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
        +

        Java & AWT(Abstract Window Toolkit)

        +

        그래픽과 이미지를 그리기 위한 도구
        +이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

        +
          +
        • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
        • +
        • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
        • +
        • 추가적인 api 호출을 하지 않아도 된다.
        • +
        +

        기술 선택

        +

        AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
        +하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

        +

        유지 보수

        +

        AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
        +따라서 다음과 같은 방법으로 공유하기로 했다.

        +
          +
        1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
        2. +
        3. AWT를 사용한 부분을 문서화하여 공유한다.
        4. +
        +

        레벨 3를 마무리하며 내용 추가

        +

        기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
        +AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

        \ No newline at end of file diff --git a/tags/image/page/2.html b/tags/image/page/2.html index 02990529e..ff2aacb26 100644 --- a/tags/image/page/2.html +++ b/tags/image/page/2.html @@ -13,11 +13,11 @@ - - + + -

        "image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

        모든 태그 보기

        · 약 7분

        개요

        +

        "image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

        모든 태그 보기

        · 약 7분

        개요

        이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

        사용 기술

        언어: Python 3.10
        @@ -36,7 +36,7 @@

        요구사항

      • 위도, 경도로 이루어진 배열을 입력받는다.
      • 이미지 생성
      • 선과 점 표현
      • -
      • 투명한 배경색
      • +
      • 투명한 배경색
      • 위경도 차이가 크든 작든 제공하는 이미지 내에 경로가 다 포함되어 있어야 한다.

      이미지 출력 방식

      diff --git a/tags/image/page/3.html b/tags/image/page/3.html index f497f48fb..c517cc384 100644 --- a/tags/image/page/3.html +++ b/tags/image/page/3.html @@ -13,60 +13,201 @@ - - + + -

      "image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      ./route.png

      -

      이미지 생성의 책임

      -

      위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
      -따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

      -

      해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

      -
        -
      • 이미지 생성
      • -
      • 선과 점 표현
      • -
      • 투명한 배경색
      • -
      -

      현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

      -

      고려한 기술

      -

      백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

      +

      "image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 12분

      개요

      +

      여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
      +경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

      +

      구현 결과

      +

      ./result.png

      +

      예시 데이터는 다음과 같다.
      +서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

      +
      List<Double> x = List.of(
      +        126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
      +        126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
      +);
      +List<Double> y = List.of(
      +        37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
      +        37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
      +);
      +List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
      +List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);
      +
      +

      IMAGE_SIZE & ROUTE_SIZE

      +
      private static final int IMAGE_SIZE = 800;
      +private static final int ROUTE_SIZE = 600;
      +
      +

      코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
      +IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
      +ROUTE_SIZE의 경우 상하좌우 100px 만큼의 간격을 위해 존재한다.
      +따라서 실제 경로 이미지의 크기는 600 * 600 사이즈로 생성된다.

      +

      ./600.png

      +

      사이즈 변경의 이유

      +

      255 * 255 정도의 작은 사이즈로 이미지를 생성해보려고 했는데, 이미지의 선명도가 좋지 않아 800 * 800 사이즈로 변경했다.

      +

      주요 클래스

      +

      요약

      +
      클래스명설명특이사항
      Coordinate위도, 경도로 이루어진 위치 값좌표를 뜻하지만 여행 도메인에 포함된 Point 클래스와 구분하기 위해 longitude, latitude를 사용하지 않고 x, y 사용
      CoordinatesCoordinate의 일급 컬렉션-
      Position실제 이미지 생성에 사용할 위치 값Integer 타입의 x, y 사용
      PositionsPositions의 일급 컬렉션-
      RouteImageDrawer실제 이미지에 경로를 그려주는 클래스 BufferedImage, Graphics2D를 가지고 있음이미지 생성에 필요한 상수가 정의되어 있음
      RouteImageUploaderBufferedImage를 받아 서버에 업로드 하는 클래스현재 업로드 위치가 정해지지 않아 일단 기본(프로젝트 루트) 위치에 생성
      RouteImageGenerator이미지를 생성하고 업로드하는 서비스여행 종료, 감상 저장시 해당 클래스를 통해 이미지 생성 요청
      BufferedImage(AWT)이미지 데이터를 처리하고 조작하는 데 사용왼쪽 상단의 좌표가 (0, 0)
      Graphics2D(AWT)선 그리기, 색상 관리 등을 지원하는 클래스 실제 해당 클래스의 draw 메서드를 경로를 그림JDK 1.2 이후에 추가됨, 2D(평면) 그래픽 환경을 지원, bufferedImage.createGraphics 메서드를 통해 생성
      +

      의존관계

      + +

      Coordinates(위도, 경도의 일급 컬렉션)

      +

      List<Double> 2개(위도, 경도)인 형태로 관리하는 방법이 있었지만, 위치 점을 여러개 찍는 부분에서 로직이 복잡해 질 것 같아서 Coordinate(x, y)와 일급 컬렉션인 Coordinates로 관리하기로 했다.
      +Coordinates 클래스에는 다음 두 개의 인터페이스가 존재한다.

        -
      • Python의 Matplotlib
      • -
      • AWT(Abstract Window Toolkit) [최종 선택]
      • -
      • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
      • -
      • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)
      • +
      • calculatePositions: 경로 이미지의 크기를 받아 실제 이미지 생성시 사용될 Positions를 반환
      • +
      • indexOf: 다른 Coordinates를 받아 동일한 위치점에 해당하는 인덱스를 반환하는
      -

      Python & Matplotlib

      -

      데이터 시각화 라이브러리
      -이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

      +

      Positions 계산 로직은 다음과 같다.
      +위도, 경도 각각에 대한 부분을 이미지 생성시 필요한 값으로 변환한다.

      +
      // 호출
      +// List<Integer> xPositions = toPositions(xValues, maxDifference, routeImageSize);
      +// List<Integer> yPositions = toPositions(yValues, maxDifference, routeImageSize);
      +
      +private List<Integer> toPositions(List<Double> values, Double maxDifference, Integer routeImageSize) {
      +    Double minValue = Collections.min(values);
      +    return values.stream()
      +            .map(value -> normalizeCoordinate(value, maxDifference, minValue))
      +            .map(value -> mapToPosition(value, routeImageSize))
      +            .toList();
      +}
      +
      +private double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {
      +    return (coordinate - minValue) / maxDifference;
      +}
      +
      +private int mapToPosition(Double coordinate, Integer routeImageSize) {
      +    return (int) (coordinate * routeImageSize);
      +}
      +
      +

      위도로 예시든 내용이다.

      +
        +
      1. Collections.min(values) → 위도 리스트의 최소값을 구한다.
      2. +
      3. normalizeCoordinate → 각각의 위도 값에서 최소값을 빼고 0 ~ 1 사이 값으로 변환 후 위경도의 최대 차이로 나눈다.
      4. +
      5. mapToPosition → 그래프 크기를 받아 0 ~ 1 사이 값을 실제 이미지를 위한 위치값으로 변환한다.
      6. +
      +

      Positions(실제 이미지 생성에 사용할 위치)

      +

      Positions 클래스에는 다음 다섯 개의 인터페이스가 존재한다.

        -
      • 코드가 간단해서 유지 보수성이 좋다.
      • -
      • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
      • -
      • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.
      • +
      • align: 이미지 사이즈와 경로 이미지 사이즈를 받아 Position 값들을 중앙 정렬한다.
      • +
      • getPositionsByIndexes: 인덱스 리스트를 받아 입력받은 인덱스에 해당하는 값들을 반환한다.
      • +
      • size: 크기를 반환한다.
      • +
      • xPositions: x 값들을 반환한다.
      • +
      • yPositions: y 값들을 반환한다.
      -

      Java AWT 이외의 라이브러리

      -

      Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

      -
      라이브러리설명제외 이유
      SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
      JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
      simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
      matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음
      -

      Java & AWT(Abstract Window Toolkit)

      -

      그래픽과 이미지를 그리기 위한 도구
      -이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

      +

      중앙 정렬 로직은 다음과 같다.

      +
      public Positions align(int imageSize, int routeSize) {
      +    int xOffset = calculateOffset(Position::x, imageSize);
      +    int yOffset = calculateOffset(Position::y, imageSize);
      +
      +    return items.stream()
      +            .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))
      +            .collect(collectingAndThen(toList(), Positions::new));
      +}
      +
      +private int calculateOffset(ToIntFunction<Position> positionToInteger, int imageSize) {
      +    List<Integer> positions = items.stream()
      +            .mapToInt(positionToInteger)
      +            .boxed()
      +            .toList();
      +
      +    int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;
      +    return imageSize / 2 - midValue;
      +}
      +
      +

      상하좌우 여백을 동일하게 주기 위해서 offset 값을 구해서 x, y 값에 각각 더하는 형태로 중앙 정렬을 수행했다.
      +BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

      +

      ./800.png

      +

      따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

      +

      x 값 → 계산한 offset 그대로 더한다.
      +y 값 → imageSize(800)에서 y + offset 값을 뺀다.

      +

      RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

      +

      BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
      +그림을 그리기 위해 설정한 상수들이 존재한다.

      +
      // RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
      +// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
      +// 이를 RGBA라고 부른다.
      +private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
      +// 배경 투명색
      +private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
      +// 경로를 위한 STROKE
      +private static final int LINE_STROKE_WIDTH = 7;
      +private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
      +// 위치 점을 위한 STROKE
      +private static final int POINT_STROKE_WIDTH = 20;
      +private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
      +// 안티앨리어싱 등 화질 개선을 위한 설정
      +private static final Map<Object, Object> renderingHints = Map.of(
      +        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
      +        RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
      +        RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
      +);
      +
      +

      RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

        -
      • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
      • -
      • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
      • -
      • 추가적인 api 호출을 하지 않아도 된다.
      • +
      • drawLine: 선을 그린다.
      • +
      • drawPoint: 점을 찍는다.
      • +
      • dispose: 자원 할당을 해제한다.
      -

      기술 선택

      -

      AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
      -하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

      -

      유지 보수

      -

      AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
      -따라서 다음과 같은 방법으로 공유하기로 했다.

      -
        -
      1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
      2. -
      3. AWT를 사용한 부분을 문서화하여 공유한다.
      4. -
      -

      레벨 3를 마무리하며 내용 추가

      -

      기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
      -AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

      +

      dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

      +

      이미지 생성 Flow

      +

      1. 이미지 생성 준비

      + +

      2. 선 그리기 요청

      + +

      3. 위치 점 그리기 요청

      + +

      4. 업로드 요청

      + +

      전체 Flow

      +
      \ No newline at end of file diff --git a/tags/inno-db.html b/tags/inno-db.html index e395ce24d..e3935ece1 100644 --- a/tags/inno-db.html +++ b/tags/inno-db.html @@ -13,11 +13,11 @@ - - + + -

      "InnoDB" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      InnoDB 스토리지 엔진의 잠금

      +

      "InnoDB" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      InnoDB 스토리지 엔진의 잠금

      MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
      보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

      동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
      @@ -67,7 +67,7 @@

      잠금 예시

      -- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다. SELECT * FROM table_name where id > 100 for update; --- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다. +-- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다. SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;

    참고 자료

    diff --git a/tags/intelli-j.html b/tags/intelli-j.html index 2bd00fe14..51601ac03 100644 --- a/tags/intelli-j.html +++ b/tags/intelli-j.html @@ -13,11 +13,11 @@ - - + + -

    "IntelliJ" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 1분

    Import 자동 적용

    +

    "IntelliJ" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 1분

    Import 자동 적용

    Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

    auto-import

    저장시 동작

    diff --git a/tags/isolation.html b/tags/isolation.html index c51400020..b1c86f915 100644 --- a/tags/isolation.html +++ b/tags/isolation.html @@ -13,11 +13,11 @@ - - + + -

    "Isolation" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    트랜잭션(Transaction)

    +

    "Isolation" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    트랜잭션(Transaction)

    데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
    트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
    논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

    @@ -51,7 +51,7 @@

    READ UNCOMMITTED

    Database->>+Bob: Alice Alice->>Database: COMMIT(Alice)">

    READ COMMITTED

    -

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    +

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    오라클 DBMS에서 기본으로 사용되는 격리 수준이다.
    REPEATABLE READ가 보장되지 않기 때문에 NON-REPEATABLE READ 문제가 발생한다.

    - - + + -

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    자바 17, 스프링 6.0, 스프링 부트 3.1

    -

    팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
    -2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

    -

    자바 변경 사항

    -

    우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
    -따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

    -

    Switch Expressions(Java 14)

    -

    Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

    -
    enum RESULT {
    -    WIN, LOSE, DRAW
    -}
    -
    -RESULT result = RESULT.WIN;
    -
    -int prize = switch (result) {
    -    case WIN -> 10_000_000;
    -    case LOSE, DRAW -> 5_000_000;
    -	default -> 0;
    -};
    -
    -

    주요 특징은 다음과 같다.

    -
      -
    • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
    • -
    • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
    • -
    • break 문이 필요 없다.
    • -
    • default 블록을 통해 기본 값을 지정할 수 있다.
    • -
    -

    Text Block(Java 15)

    -

    Java 15에는 새로운 문자열 표현방식이 추가되었다.
    -긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

    -
    @Repository
    -public interface PostRepository extends JpaRepository<Post, Long> {
    -    @Query("""
    -        SELECT p FROM Post p
    -        WHERE p.title LIKE %:keyword%
    -        OR p.content LIKE %:keyword%
    -        """)
    -    List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
    +

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 2분

    이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    +ISO-8601을 기반으로 작성
    +설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

    +

    날짜와 시간에 관련된 데이터를 다루는 국제 표준

    +

    LocalDate, LocalTime, LocalDateTime

    +

    날짜와 시간을 표현하는 클래스

    +

    Instant

    +

    유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
    +기계의 관점에서 시간 표현

    +

    Duration, Period

    +

    간격을 표현하는 클래스

    +

    TemporalAdjusters

    +

    복잡한 날짜 조정이 필요할 때 사용
    +필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

    +
    @FunctionalInterface
    +public interface TemporalAdjuster {
    +    Temporal adjustInto(Temporal temporal);
     }
     
    -

    NPE 메시지(Java 15)

    -
    String name = null;
    -name.chars();
    -
    -/** 
    -# before
    -java.lang.NullPointerException
    -	at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)
    -
    -# after
    -Cannot invoke "String.chars()" because "name" is null
    -java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
    -*/
    +

    DateTimeFormatter

    +

    날짜와 시간 포맷 클래스
    +특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

    +

    ZoneId, ZoneOffset

    +

    ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
    +ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

    +
    Instant instant = Instant.now();
    +LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
     
    -

    Record(Java 16)

    -

    Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
    -Record를 선언하는 경우 접근자, 생성자, equals & hashcode, toString이 제공된다.
    -데이터 전송 용도로 적합해 보인다.

    -
    public record PostDto(String title, String content) {
    -}
    -
    -

    추가적인 변경사항

    -

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    -

    스프링, 스프링 부트 변경 사항

    -

    스프링과 스프링 부트에도 많은 변경 사항이 있었다.
    -따라서 필요해보이는 몇개 정도만 정리했다.

    -

    스프링 요구사항

    -

    Java 17, Jakarta EE 9 이상이어야 한다.

    -

    네임스페이스 변경

    -

    Jakarta EE 9가 적용되면서 네임스페이스도 전반적으로 javax -> jakarta로 변경되었다.

    -

    PathPatternParser - trailing slash 허용하지 않음

    -

    6.0 이전의 경우 기본 설정 기준으로 @GetMapping("/hello")@GetMapping("/hello/")가 동일했다.
    -6.0 이후의 PathPatternParser가 기본으로 사용되고, /hello/hello/는 서로 다른 URL로 매칭된다.

    -
    -

    PathPatternParser used by default (with the ability to opt into PathMatcher).

    -
    -

    HTTP interface client

    -

    자바 인터페이스와 어노테이션을 이용하여 HTTP 요청을 위한 서비스를 정의할 수 있는 방법이 추가되었다.
    -자세한 내용은 토비님의 강의를 참고하면 좋을 것 같다.

    -

    스프링 부트 최소 요구사항

    -

    Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6
    -이외에도 서드파티들의 최신 릴리즈 버전을 사용함으로, 문제가 발생하는 경우 해당 버전에 맞는 릴리즈 노트를 참고할 수 있을 것 같다.

    -

    참고 자료

    -

    어느 월급쟁이개발자 의 스프링 부트 따라잡기
    -자바 9-16 주요 특징 복습하기
    -Java EE에서 Jakarta EE로의 전환
    -Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩
    -What's New in Spring Framework 6.x
    -Spring Boot 3.0 Release Notes
    -Spring Boot 3.1 Release Notes

    +

    참고 자료

    +
    \ No newline at end of file diff --git a/tags/java/page/2.html b/tags/java/page/2.html index 8e608a727..d0165e5bb 100644 --- a/tags/java/page/2.html +++ b/tags/java/page/2.html @@ -13,83 +13,99 @@ - - + + -

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    클래스 파일

    -

    자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
    -컴파일된 클래스파일은 어떤 구조로 되어있을까?

    -

    클래스 파일의 데이터 형식

    -

    8비트 바이트의 스트림으로 구성된다.
    -16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
    -멀티바이트의 경우 항상 big endian 순서로 저장된다.

    -

    u1 → unsigned 1byte
    -u2 → unsigned 2byte
    -u4 → unsigned 4byte

    -

    클래스 파일 구조

    -
    ClassFile {
    -    u4             magic;
    -    u2             minor_version;
    -    u2             major_version;
    -    u2             constant_pool_count;
    -    cp_info        constant_pool[constant_pool_count-1];
    -    u2             access_flags;
    -    u2             this_class;
    -    u2             super_class;
    -    u2             interfaces_count;
    -    u2             interfaces[interfaces_count];
    -    u2             fields_count;
    -    field_info     fields[fields_count];
    -    u2             methods_count;
    -    method_info    methods[methods_count];
    -    u2             attributes_count;
    -    attribute_info attributes[attributes_count];
    +

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
    +이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

    +

    Argument Sources

    +

    @ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
    +JUnit이 제공하는 다양한 Source가 있기 때문에, 테스트에 맞춰 다양하게 사용할 수 있다.

    +

    Value Source

    +

    값을 이용하여 제공하는 형태로, 다음과 같은 타입의 값을 매개변수로 제공할 수 있다.

    +
      +
    • short, int, long, float, double
    • +
    • byte, char, boolean, String, Class
    • +
    +
    @ParameterizedTest
    +@ValueSource(ints = {1, 100, Integer.MAX_VALUE})
    +void valueTest(final int value) {
    +    Assertions.assertThat(value).isPositive();
     }
     
    -

    매직넘버

    -

    모든 클래스 파일은 0xCAFEBABE라는 매직넘버로 시작한다.
    -보통 매직넘버는 파일 종류를 식별하는 용도로 사용된다.

    -

    클래스 파일 포맷 버전

    -

    클래스 파일 버전 값은 클래스로더의 호환성 보장을 위해 꼭 필요한 값이다.

    +

    Null & Empty Source

    +

    null 값, 빈 값을 제공한다.
    +Empty Source의 경우 다음과 같은 타입에 한해 매개변수로 제공할 수 있다.

      -
    • Java 17 버전으로 빌드한다면 class version 61 ex) 00 00 00 3D
    • +
    • String
    • +
    • java.util.List, java.util.Set, java.util.Map
    • +
    • primitive arrays — ex) int[]
    • +
    • object arrays — ex) String[]
    -

    호환되지 않는 버전의 클래스 파일을 로딩하려고 하는 경우 런타임에 UnsupportedClassVersionError 예외가 발생한다.

    -

    class file format major versions

    -
    Java SEReleasedMajorSupported majors
    8March 20145245 .. 52
    9September 20175345 .. 53
    10March 20185445 .. 54
    11September 20185545 .. 55
    12March 20195645 .. 56
    13September 20195745 .. 57
    14March 20205845 .. 58
    15September 20205945 .. 59
    16March 20216045 .. 60
    17September 20216145 .. 61
    -

    상수 풀

    -

    2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
    -클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
    -JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

    -

    액세스 플래그

    -

    클래스, 인터페이스와 같은 파일의 속성을 표시한다.
    -예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.

    +
    @ParameterizedTest
    +@NullAndEmptySource
    +void nullAndEmptyTest(final String value) {
    +    Assertions.assertThat(value).isNullOrEmpty();
    +}
    +
    +

    Enum Source

    +

    EnumSource를 이용하여 Enum 또한 매개변수로 제공할 수 있다.

    +
    enum Day {
    +    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
    +}
    +
    +@ParameterizedTest
    +@EnumSource(Day.class)
    +void enumTest(final Day day) {
    +    assertThat(day).isInstanceOf(Day.class);
    +}
    +
    +

    다음과 같이 mode 값을 이용하여 특징 Enum을 제외하거나, 포함시킬 수 있다. (default: Mode.Include)

    +
    @ParameterizedTest
    +@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)
    +void enumTest(final Day day) {
    +    // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
    +    assertThat(day).isInstanceOf(Day.class);
    +}
    +
    +

    CSV Source

    +

    csv 형식의 값을 이용하여 매개변수를 제공한다.
    +구분자의 기본값은 쉼표(,)로 구분자를 변경하고 싶을 땐 delimeter 값을 따로 전달하여 사용할 수 있다. +개인적으로 2개 정도의 값을 매개변수로 전달하는 경우 CsvSource를 사용한다.

    +
    @ParameterizedTest
    +@CsvSource({"1,1", "2,4", "3,9", "4,16"})
    +void csvTest(final int number, final int result) {
    +    assertThat(number * number).isEqualTo(result);
    +}
    +
    +

    Method Source

    +

    복잡한 타입의 값을 전달할 때 사용한다.
    +메서드명을 입력하여 매개변수를 제공하는 메서드를 지정할 수 있다.
    +메서드명을 따로 입력하지 않으면 테스트명과 동일한 static 메서드가 지정된다.

    +
    @ParameterizedTest
    +@MethodSource
    +void methodTest(final List<Integer> numbers, final int count) {
    +    assertThat(numbers).hasSize(count);
    +}
    +
    +private static Stream<Arguments> methodTest() {
    +    return Stream.of(
    +            Arguments.of(List.of(1), 1),
    +            Arguments.of(List.of(1, 2), 2),
    +            Arguments.of(List.of(1, 2, 3), 3)
    +    );
    +}
    +
    +

    ETC.

    +

    위에서 언급한 방법 이외에도 다양한 방법으로 매개변수를 제공할 수 있다.

      -
    • 계산은 다음과 같이 이루어진다. ACC_PUBLIC xor ACC_INTERFACE xor ACC_ABSTRACT
    • +
    • CSV 파일을 이용한 CsvFileSource
    • +
    • ArgumentsProvider 구현한 클래스를 이용하는 ArgumentsSource
    -

    공식문서에 들어가면 각 플래그에 대한 설명 + 플래그 설정시 동시에 설정되면 안되는 플래그와 같은 설명이 자세하게 나와있다.

    -

    Class access and property modifiers

    -
    Flag NameValueInterpretation
    ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
    ACC_FINAL0x0010Declared final; no subclasses allowed.
    ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
    ACC_INTERFACE0x0200Is an interface, not a class.
    ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
    ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
    ACC_ANNOTATION0x2000Declared as an annotation type.
    ACC_ENUM0x4000Declared as an enum type.
    ACC_MODULE0x8000Is a module, not a class or interface.
    -

    this_class

    -

    클래스명과 같은 이름을 표현하는 값으로, 상수 풀에서 클래스명과 일치하는 항목의 인덱스를 참조한다.
    -해당 인덱스의 항목은 CONSTANT_Class_infoclass 형식의 값이어야 한다.

    -

    super_class

    -

    상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
    -아무것도 상속하지 않는 클래스의 경우 java.lang.Object의 인덱스 값이 들어있다.

    -

    interface, field, method

    -

    각각의 개수와, 정보에 대한 값이 들어있다.
    -interface, field, method를 표시하는 방법이 각각 다르고, 접근자에 대한 플래그도 각각 다르다.

    -

    attributes

    -

    해당 클래스 파일에서 사용하는 추가 정보의 모음이다. 예) 소스파일명
    -정해진 클래스 파일의 구조를 확장하는 역할을 한다.

    -

    클래스 파일 확인하면서 사용한 툴

    -

    IntelliJ plugin - BinEd
    -IntelliJ plugin - jclasslib Bytecode Viewer

    -

    참고 자료

    -

    2장 JVM 이야기, 자바 최적화
    -Class file in Java, File Format
    -java se11 Class 파일 형식, Oracle
    -java se17 Class 파일 형식, Oracle

    +

    참고 자료

    +
    \ No newline at end of file diff --git a/tags/java/page/3.html b/tags/java/page/3.html index 64321df41..6e7c6546e 100644 --- a/tags/java/page/3.html +++ b/tags/java/page/3.html @@ -13,11 +13,11 @@ - - + + -

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
    +

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
    이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
    템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

    기존 코드

    diff --git a/tags/java/page/4.html b/tags/java/page/4.html index 7efe699ef..3be205346 100644 --- a/tags/java/page/4.html +++ b/tags/java/page/4.html @@ -13,99 +13,83 @@ - - + + -

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
    -이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

    -

    Argument Sources

    -

    @ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
    -JUnit이 제공하는 다양한 Source가 있기 때문에, 테스트에 맞춰 다양하게 사용할 수 있다.

    -

    Value Source

    -

    값을 이용하여 제공하는 형태로, 다음과 같은 타입의 값을 매개변수로 제공할 수 있다.

    -
      -
    • short, int, long, float, double
    • -
    • byte, char, boolean, String, Class
    • -
    -
    @ParameterizedTest
    -@ValueSource(ints = {1, 100, Integer.MAX_VALUE})
    -void valueTest(final int value) {
    -    Assertions.assertThat(value).isPositive();
    +

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    클래스 파일

    +

    자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
    +컴파일된 클래스파일은 어떤 구조로 되어있을까?

    +

    클래스 파일의 데이터 형식

    +

    8비트 바이트의 스트림으로 구성된다.
    +16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
    +멀티바이트의 경우 항상 big endian 순서로 저장된다.

    +

    u1 → unsigned 1byte
    +u2 → unsigned 2byte
    +u4 → unsigned 4byte

    +

    클래스 파일 구조

    +
    ClassFile {
    +    u4             magic;
    +    u2             minor_version;
    +    u2             major_version;
    +    u2             constant_pool_count;
    +    cp_info        constant_pool[constant_pool_count-1];
    +    u2             access_flags;
    +    u2             this_class;
    +    u2             super_class;
    +    u2             interfaces_count;
    +    u2             interfaces[interfaces_count];
    +    u2             fields_count;
    +    field_info     fields[fields_count];
    +    u2             methods_count;
    +    method_info    methods[methods_count];
    +    u2             attributes_count;
    +    attribute_info attributes[attributes_count];
     }
     
    -

    Null & Empty Source

    -

    null 값, 빈 값을 제공한다.
    -Empty Source의 경우 다음과 같은 타입에 한해 매개변수로 제공할 수 있다.

    +

    매직넘버

    +

    모든 클래스 파일은 0xCAFEBABE라는 매직넘버로 시작한다.
    +보통 매직넘버는 파일 종류를 식별하는 용도로 사용된다.

    +

    클래스 파일 포맷 버전

    +

    클래스 파일 버전 값은 클래스로더의 호환성 보장을 위해 꼭 필요한 값이다.

      -
    • String
    • -
    • java.util.List, java.util.Set, java.util.Map
    • -
    • primitive arrays — ex) int[]
    • -
    • object arrays — ex) String[]
    • +
    • Java 17 버전으로 빌드한다면 class version 61 ex) 00 00 00 3D
    -
    @ParameterizedTest
    -@NullAndEmptySource
    -void nullAndEmptyTest(final String value) {
    -    Assertions.assertThat(value).isNullOrEmpty();
    -}
    -
    -

    Enum Source

    -

    EnumSource를 이용하여 Enum 또한 매개변수로 제공할 수 있다.

    -
    enum Day {
    -    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
    -}
    -
    -@ParameterizedTest
    -@EnumSource(Day.class)
    -void enumTest(final Day day) {
    -    assertThat(day).isInstanceOf(Day.class);
    -}
    -
    -

    다음과 같이 mode 값을 이용하여 특징 Enum을 제외하거나, 포함시킬 수 있다. (default: Mode.Include)

    -
    @ParameterizedTest
    -@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)
    -void enumTest(final Day day) {
    -    // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
    -    assertThat(day).isInstanceOf(Day.class);
    -}
    -
    -

    CSV Source

    -

    csv 형식의 값을 이용하여 매개변수를 제공한다.
    -구분자의 기본값은 쉼표(,)로 구분자를 변경하고 싶을 땐 delimeter 값을 따로 전달하여 사용할 수 있다. -개인적으로 2개 정도의 값을 매개변수로 전달하는 경우 CsvSource를 사용한다.

    -
    @ParameterizedTest
    -@CsvSource({"1,1", "2,4", "3,9", "4,16"})
    -void csvTest(final int number, final int result) {
    -    assertThat(number * number).isEqualTo(result);
    -}
    -
    -

    Method Source

    -

    복잡한 타입의 값을 전달할 때 사용한다.
    -메서드명을 입력하여 매개변수를 제공하는 메서드를 지정할 수 있다.
    -메서드명을 따로 입력하지 않으면 테스트명과 동일한 static 메서드가 지정된다.

    -
    @ParameterizedTest
    -@MethodSource
    -void methodTest(final List<Integer> numbers, final int count) {
    -    assertThat(numbers).hasSize(count);
    -}
    -
    -private static Stream<Arguments> methodTest() {
    -    return Stream.of(
    -            Arguments.of(List.of(1), 1),
    -            Arguments.of(List.of(1, 2), 2),
    -            Arguments.of(List.of(1, 2, 3), 3)
    -    );
    -}
    -
    -

    ETC.

    -

    위에서 언급한 방법 이외에도 다양한 방법으로 매개변수를 제공할 수 있다.

    +

    호환되지 않는 버전의 클래스 파일을 로딩하려고 하는 경우 런타임에 UnsupportedClassVersionError 예외가 발생한다.

    +

    class file format major versions

    +
    Java SEReleasedMajorSupported majors
    8March 20145245 .. 52
    9September 20175345 .. 53
    10March 20185445 .. 54
    11September 20185545 .. 55
    12March 20195645 .. 56
    13September 20195745 .. 57
    14March 20205845 .. 58
    15September 20205945 .. 59
    16March 20216045 .. 60
    17September 20216145 .. 61
    +

    상수 풀

    +

    2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
    +클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
    +JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

    +

    액세스 플래그

    +

    클래스, 인터페이스와 같은 파일의 속성을 표시한다.
    +예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.

      -
    • CSV 파일을 이용한 CsvFileSource
    • -
    • ArgumentsProvider 구현한 클래스를 이용하는 ArgumentsSource
    • +
    • 계산은 다음과 같이 이루어진다. ACC_PUBLIC xor ACC_INTERFACE xor ACC_ABSTRACT
    -

    참고 자료

    -
    +

    공식문서에 들어가면 각 플래그에 대한 설명 + 플래그 설정시 동시에 설정되면 안되는 플래그와 같은 설명이 자세하게 나와있다.

    +

    Class access and property modifiers

    +
    Flag NameValueInterpretation
    ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
    ACC_FINAL0x0010Declared final; no subclasses allowed.
    ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
    ACC_INTERFACE0x0200Is an interface, not a class.
    ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
    ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
    ACC_ANNOTATION0x2000Declared as an annotation type.
    ACC_ENUM0x4000Declared as an enum type.
    ACC_MODULE0x8000Is a module, not a class or interface.
    +

    this_class

    +

    클래스명과 같은 이름을 표현하는 값으로, 상수 풀에서 클래스명과 일치하는 항목의 인덱스를 참조한다.
    +해당 인덱스의 항목은 CONSTANT_Class_infoclass 형식의 값이어야 한다.

    +

    super_class

    +

    상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
    +아무것도 상속하지 않는 클래스의 경우 java.lang.Object의 인덱스 값이 들어있다.

    +

    interface, field, method

    +

    각각의 개수와, 정보에 대한 값이 들어있다.
    +interface, field, method를 표시하는 방법이 각각 다르고, 접근자에 대한 플래그도 각각 다르다.

    +

    attributes

    +

    해당 클래스 파일에서 사용하는 추가 정보의 모음이다. 예) 소스파일명
    +정해진 클래스 파일의 구조를 확장하는 역할을 한다.

    +

    클래스 파일 확인하면서 사용한 툴

    +

    IntelliJ plugin - BinEd
    +IntelliJ plugin - jclasslib Bytecode Viewer

    +

    참고 자료

    +

    2장 JVM 이야기, 자바 최적화
    +Class file in Java, File Format
    +java se11 Class 파일 형식, Oracle
    +java se17 Class 파일 형식, Oracle

    \ No newline at end of file diff --git a/tags/java/page/5.html b/tags/java/page/5.html index 0e23085a1..c081951b5 100644 --- a/tags/java/page/5.html +++ b/tags/java/page/5.html @@ -13,46 +13,99 @@ - - + + -

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 2분

    이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    -ISO-8601을 기반으로 작성
    -설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

    -

    날짜와 시간에 관련된 데이터를 다루는 국제 표준

    -

    LocalDate, LocalTime, LocalDateTime

    -

    날짜와 시간을 표현하는 클래스

    -

    Instant

    -

    유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
    -기계의 관점에서 시간 표현

    -

    Duration, Period

    -

    간격을 표현하는 클래스

    -

    TemporalAdjusters

    -

    복잡한 날짜 조정이 필요할 때 사용
    -필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

    -
    @FunctionalInterface
    -public interface TemporalAdjuster {
    -    Temporal adjustInto(Temporal temporal);
    +

    "Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    자바 17, 스프링 6.0, 스프링 부트 3.1

    +

    팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
    +2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

    +

    자바 변경 사항

    +

    우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
    +따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

    +

    Switch Expressions(Java 14)

    +

    Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

    +
    enum RESULT {
    +    WIN, LOSE, DRAW
     }
    +
    +RESULT result = RESULT.WIN;
    +
    +int prize = switch (result) {
    +    case WIN -> 10_000_000;
    +    case LOSE, DRAW -> 5_000_000;
    +	default -> 0;
    +};
     
    -

    DateTimeFormatter

    -

    날짜와 시간 포맷 클래스
    -특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

    -

    ZoneId, ZoneOffset

    -

    ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
    -ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

    -
    Instant instant = Instant.now();
    -LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
    -
    -

    참고 자료

    +

    주요 특징은 다음과 같다.

    +
  • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
  • +
  • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
  • +
  • break 문이 필요 없다.
  • +
  • default 블록을 통해 기본 값을 지정할 수 있다.
  • + +

    Text Block(Java 15)

    +

    Java 15에는 새로운 문자열 표현방식이 추가되었다.
    +긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

    +
    @Repository
    +public interface PostRepository extends JpaRepository<Post, Long> {
    +    @Query("""
    +        SELECT p FROM Post p
    +        WHERE p.title LIKE %:keyword%
    +        OR p.content LIKE %:keyword%
    +        """)
    +    List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
    +}
    +
    +

    NPE 메시지(Java 15)

    +
    String name = null;
    +name.chars();
    +
    +/** 
    +# before
    +java.lang.NullPointerException
    +	at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)
    +
    +# after
    +Cannot invoke "String.chars()" because "name" is null
    +java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
    +*/
    +
    +

    Record(Java 16)

    +

    Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
    +Record를 선언하는 경우 접근자, 생성자, equals & hashcode, toString이 제공된다.
    +데이터 전송 용도로 적합해 보인다.

    +
    public record PostDto(String title, String content) {
    +}
    +
    +

    추가적인 변경사항

    +

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    +

    스프링, 스프링 부트 변경 사항

    +

    스프링과 스프링 부트에도 많은 변경 사항이 있었다.
    +따라서 필요해보이는 몇개 정도만 정리했다.

    +

    스프링 요구사항

    +

    Java 17, Jakarta EE 9 이상이어야 한다.

    +

    네임스페이스 변경

    +

    Jakarta EE 9가 적용되면서 네임스페이스도 전반적으로 javax -> jakarta로 변경되었다.

    +

    PathPatternParser - trailing slash 허용하지 않음

    +

    6.0 이전의 경우 기본 설정 기준으로 @GetMapping("/hello")@GetMapping("/hello/")가 동일했다.
    +6.0 이후의 PathPatternParser가 기본으로 사용되고, /hello/hello/는 서로 다른 URL로 매칭된다.

    +
    +

    PathPatternParser used by default (with the ability to opt into PathMatcher).

    +
    +

    HTTP interface client

    +

    자바 인터페이스와 어노테이션을 이용하여 HTTP 요청을 위한 서비스를 정의할 수 있는 방법이 추가되었다.
    +자세한 내용은 토비님의 강의를 참고하면 좋을 것 같다.

    +

    스프링 부트 최소 요구사항

    +

    Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6
    +이외에도 서드파티들의 최신 릴리즈 버전을 사용함으로, 문제가 발생하는 경우 해당 버전에 맞는 릴리즈 노트를 참고할 수 있을 것 같다.

    +

    참고 자료

    +

    어느 월급쟁이개발자 의 스프링 부트 따라잡기
    +자바 9-16 주요 특징 복습하기
    +Java EE에서 Jakarta EE로의 전환
    +Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩
    +What's New in Spring Framework 6.x
    +Spring Boot 3.0 Release Notes
    +Spring Boot 3.1 Release Notes

    \ No newline at end of file diff --git a/tags/jdbc.html b/tags/jdbc.html index a4afdd120..8f7c8dd67 100644 --- a/tags/jdbc.html +++ b/tags/jdbc.html @@ -13,11 +13,11 @@ - - + + -

    "JDBC" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
    +

    "JDBC" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
    이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
    템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

    기존 코드

    diff --git a/tags/jenkins.html b/tags/jenkins.html index 1c8ba244a..1d3426fc6 100644 --- a/tags/jenkins.html +++ b/tags/jenkins.html @@ -13,11 +13,11 @@ - - + + -

    "Jenkins" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    설정 환경

    +

    "Jenkins" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    설정 환경

    소프트웨어 이미지: Amazon Linux 2023 AMI
    아키텍쳐: ARM
    인스턴스 유형: t4g.small
    diff --git a/tags/kotlin.html b/tags/kotlin.html index 70aed4114..fbbf70622 100644 --- a/tags/kotlin.html +++ b/tags/kotlin.html @@ -13,11 +13,11 @@ - - + + -

    "Kotlin" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    nullable 타입

    +

    "Kotlin" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    nullable 타입

    코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
    이는 실행 시점이 아닌 컴파일 시 미리 오류가 발생할 가능성이 있는 부분을 미리 감지하여 NPE 발생의 가능성을 줄여준다.

    코틀린의 경우 nullable 타입을 다음과 같이 표현한다.

    @@ -53,7 +53,7 @@

    ?: 엘비스 연산자

    return word ?: "" }
    -

    코틀린에서는 throw도 식이기 때문에 엘비스 연산자를 이용하여 예외를 던질 수 있다.
    +

    코틀린에서는 throw도 식이기 때문에 엘비스 연산자를 이용하여 예외를 던질 수 있다.
    예를 들어 사용자 정보가 있는 저장소에 찾는 사용자가 없는 경우 아래와 같이 사용할 수 있다.

    userRepository.findByName(name) ?: throw IllegalArgumentException()
     
    diff --git a/tags/lock.html b/tags/lock.html index f894b20ea..52151e10e 100644 --- a/tags/lock.html +++ b/tags/lock.html @@ -13,68 +13,74 @@ - - + + -

    "Lock" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    InnoDB 스토리지 엔진의 잠금

    -

    MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
    -보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

    -

    동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
    -InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

    -

    트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

    -

    트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
    -일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

    -

    Shared & Exclusive Locks

    -

    InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

    -

    공유 잠금(S, shared lock)

    -

    데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
    -다른 트랜잭션에서 읽기가 가능하지만, 쓰기는 불가능하다.
    -예) SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;

    -

    배타적 잠금(X, exclusive lock)

    -

    데이터 변경을 위한 락, 쓰기 잠금(write lock)으로도 불린다.
    -락을 건 트랜잭션만이 해당 데이터에 접근 가능하다. 다른 트랜잭션의 경우 읽기, 쓰기가 불가능하다.
    -예) SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

    -

    Intention Locks

    -

    InnoDB는 로우 단위 잠금과 테이블 잠금의 공존을 위해 인텍션 잠금을 지원한다.
    -테이블에 있는 로우에 대해서 나중에 요청되는 것이 어떤 형태의 잠금인지 가리키기 위해 사용된다.
    -기본적으로 로우 단위 잠금을 수행하기 전에 인텐션 잠금을 먼저 획득한다.
    -인텐션 락은 기본적으로 충돌을 방지하고 데드락을 방지하는 역할을 한다.

    -

    인텐션 공유 잠금(IS, intention shared lock)

    -

    트랜잭션이 테이블의 개별 로우에 대한 공유 잠금을 수행하는 것을 의미한다.

    -

    인텐션 배타적 잠금(IX, intention exclusive lock)

    -

    트랜잭션이 테이블의 개별 로우에 대한 배타적 잠금을 수행하는 것을 의미한다.

    -

    ** 잠금간의 호환성 **

    -
    XIXSIS
    XConflictConflictConflictConflict
    IXConflictCompatibleConflictCompatible
    SConflictConflictCompatibleCompatible
    ISConflictCompatibleCompatibleCompatible
    -

    Record Locks

    -

    레코드 자체만을 잠그는 락이다.
    -InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다.

    -

    Gap Locks

    -

    레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    -레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하고, 넥스트 키 락의 일부로 사용된다.

    -

    Next-Key Locks

    -

    레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.
    -REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하기 위한 잠금이다.

    -

    AUTO-INC Locks

    -

    AUTO_INCREMENT 칼림이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 한다.
    -InnoDB 는 내부적으로 AUTO-INC 락이라고 하는 테이블 수준의 잠금을 사용한다.
    -트랜잭션과 관계 없이 INSERTREPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 해제된다.

    -

    잠금 예시

    -
    -- 레코드는 id 기준 10, 20, 30, 40, 50이 있다고 가정
    --- Record Locks: 10에 대해 락이 걸린다.
    -SELECT * FROM table_name where id = 10 for update;
    +

    "Lock" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    MySQL 엔진의 잠금

    +

    MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
    +MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

    +

    글로벌 락(Global lock)

    +

    MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

    +
      +
    • 영향을 미치는 범위는 해당 서버 전체이다.
    • +
    • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.
    • +
    +

    한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
    +데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
    +InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

    +
    -- GLOBAL LOCK
    +FLUSH TABLES WITH READ LOCK;
    +-- UNLOCK
    +UNLOCK TABLES;
     
    --- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다.
    -SELECT * FROM table_name where id > 100 for update;
    +-- BACKUP LOCK
    +LOCK INSTANCE FOR BACKUP;
    +-- UNLOCK
    +UNLOCK INSTANCE;
    +
    +

    MySQL 5.5 버전 이전의 기본 스토리지 엔진이다.
    +트랜잭션을 지원하지 않고, SELECT 작업 속도가 빠르다.

    +

    테이블 락(Table lock)

    +

    개별 테이블 단위로 설정되는 잠금이다.
    +명시적 또는 묵시적으로 특정 테이블의 락을 획득할 수 있다.
    +묵시적 락은 MyISAM이나 MEMORY 테이블에 데이터를 변경하는 쿼리를 실행하면 발생한다.
    +InnoDB 테이블에는 DML 쿼리는 무시되고 DDL 일 경우에만 묵시적으로 락을 획득한다.

    +
    -- TABLE LOCK
    +LOCK TABLES table_name [ READ | WRITE ]
    +
    +-- UNLOCK
    +UNLOCK TABLES;
    +
    +

    네임드 락(Named lock)

    +

    임의의 문자열에 대한 잠금을 설정할 수 있는 잠금으로 유저 레벨 락으로도 불린다.
    +여러 스레드나 프로세스가 동일한 데이터를 수정하려는 경우, 동시에 수정하지 못하도록 보호할 수 있다.

    +
    -- aGVyYg== 라는 문자열에 대한 잠금 획득, 이미 잠금을 사용중인 경우 1초 동안만 대기
    +SELECT GET_LOCK('aGVyYg==', 1);
    +
    +-- 문자열에 대한 잠금이 설정되어 있는지 확인한다.
    +SELECT IS_FREE_LOCK('aGVyYg==');
     
    --- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다.
    -SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;
    +-- 문자열에 대한 잠금을 해제한다.
    +SELECT RELEASE_LOCK('aGVyYg==');
    +
    +-- 위 3개 함수 모두 정상적으로 락을 획득하거나 해제한 경우에 1을, 아니면 0을 반환한다.
    +
    +-- 모든 문자열에 대한 잠금을 해제한다. 해제된 잠금의 개수를 반환한다.
    +SELECT RELEASE_ALL_LOCKS();
    +
    +

    메타데이터 락(Metadata lock)

    +

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    +명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    +보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    +
    -- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
    +-- 아래 구문 실행 시 메타데이터 락을 자동으로 획득한다.
    +RENAME TABLE rank TO rank_backup, rank_new TO rank;
     

    참고 자료

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    -Optimistic and Pessimistic record locking, IBM
    -MySQL Innodb Locks, cecil1018
    -MySQL 8.0 InnoDB Locks, MySQL
    -Locks Set by Different SQL Statements in InnoDB, MySQL

    +MySQL의 User Level Lock를 활용한다면?, gywndi
    +Locking Functions, MySQL 5.7 Reference
    +Locking Functions, MySQL 8.0 Reference

    \ No newline at end of file diff --git a/tags/lock/page/2.html b/tags/lock/page/2.html index aed131f01..760274bd4 100644 --- a/tags/lock/page/2.html +++ b/tags/lock/page/2.html @@ -13,74 +13,68 @@ - - + + -

    "Lock" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    MySQL 엔진의 잠금

    -

    MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
    -MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

    -

    글로벌 락(Global lock)

    -

    MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

    -
      -
    • 영향을 미치는 범위는 해당 서버 전체이다.
    • -
    • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.
    • -
    -

    한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
    -데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
    -InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

    -
    -- GLOBAL LOCK
    -FLUSH TABLES WITH READ LOCK;
    --- UNLOCK
    -UNLOCK TABLES;
    +

    "Lock" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    InnoDB 스토리지 엔진의 잠금

    +

    MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
    +보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

    +

    동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
    +InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

    +

    트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

    +

    트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
    +일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

    +

    Shared & Exclusive Locks

    +

    InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

    +

    공유 잠금(S, shared lock)

    +

    데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
    +다른 트랜잭션에서 읽기가 가능하지만, 쓰기는 불가능하다.
    +예) SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;

    +

    배타적 잠금(X, exclusive lock)

    +

    데이터 변경을 위한 락, 쓰기 잠금(write lock)으로도 불린다.
    +락을 건 트랜잭션만이 해당 데이터에 접근 가능하다. 다른 트랜잭션의 경우 읽기, 쓰기가 불가능하다.
    +예) SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

    +

    Intention Locks

    +

    InnoDB는 로우 단위 잠금과 테이블 잠금의 공존을 위해 인텍션 잠금을 지원한다.
    +테이블에 있는 로우에 대해서 나중에 요청되는 것이 어떤 형태의 잠금인지 가리키기 위해 사용된다.
    +기본적으로 로우 단위 잠금을 수행하기 전에 인텐션 잠금을 먼저 획득한다.
    +인텐션 락은 기본적으로 충돌을 방지하고 데드락을 방지하는 역할을 한다.

    +

    인텐션 공유 잠금(IS, intention shared lock)

    +

    트랜잭션이 테이블의 개별 로우에 대한 공유 잠금을 수행하는 것을 의미한다.

    +

    인텐션 배타적 잠금(IX, intention exclusive lock)

    +

    트랜잭션이 테이블의 개별 로우에 대한 배타적 잠금을 수행하는 것을 의미한다.

    +

    ** 잠금간의 호환성 **

    +
    XIXSIS
    XConflictConflictConflictConflict
    IXConflictCompatibleConflictCompatible
    SConflictConflictCompatibleCompatible
    ISConflictCompatibleCompatibleCompatible
    +

    Record Locks

    +

    레코드 자체만을 잠그는 락이다.
    +InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다.

    +

    Gap Locks

    +

    레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 락이다.
    +레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하고, 넥스트 키 락의 일부로 사용된다.

    +

    Next-Key Locks

    +

    레코드 락과 갭 락을 합쳐놓은 형태의 잠금으로 레코드와 그 레코드 앞의 갭 락을 포함한다.
    +REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하기 위한 잠금이다.

    +

    AUTO-INC Locks

    +

    AUTO_INCREMENT 칼림이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 한다.
    +InnoDB 는 내부적으로 AUTO-INC 락이라고 하는 테이블 수준의 잠금을 사용한다.
    +트랜잭션과 관계 없이 INSERTREPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 해제된다.

    +

    잠금 예시

    +
    -- 레코드는 id 기준 10, 20, 30, 40, 50이 있다고 가정
    +-- Record Locks: 10에 대해 락이 걸린다.
    +SELECT * FROM table_name where id = 10 for update;
     
    --- BACKUP LOCK
    -LOCK INSTANCE FOR BACKUP;
    --- UNLOCK
    -UNLOCK INSTANCE;
    -
    -

    MySQL 5.5 버전 이전의 기본 스토리지 엔진이다.
    -트랜잭션을 지원하지 않고, SELECT 작업 속도가 빠르다.

    -

    테이블 락(Table lock)

    -

    개별 테이블 단위로 설정되는 잠금이다.
    -명시적 또는 묵시적으로 특정 테이블의 락을 획득할 수 있다.
    -묵시적 락은 MyISAM이나 MEMORY 테이블에 데이터를 변경하는 쿼리를 실행하면 발생한다.
    -InnoDB 테이블에는 DML 쿼리는 무시되고 DDL 일 경우에만 묵시적으로 락을 획득한다.

    -
    -- TABLE LOCK
    -LOCK TABLES table_name [ READ | WRITE ]
    -
    --- UNLOCK
    -UNLOCK TABLES;
    -
    -

    네임드 락(Named lock)

    -

    임의의 문자열에 대한 잠금을 설정할 수 있는 잠금으로 유저 레벨 락으로도 불린다.
    -여러 스레드나 프로세스가 동일한 데이터를 수정하려는 경우, 동시에 수정하지 못하도록 보호할 수 있다.

    -
    -- aGVyYg== 라는 문자열에 대한 잠금 획득, 이미 잠금을 사용중인 경우 1초 동안만 대기
    -SELECT GET_LOCK('aGVyYg==', 1);
    -
    --- 문자열에 대한 잠금이 설정되어 있는지 확인한다.
    -SELECT IS_FREE_LOCK('aGVyYg==');
    +-- Gap Locks: 51부터 PositiveInfinity까지 락이 걸린다.
    +SELECT * FROM table_name where id > 100 for update;
     
    --- 문자열에 대한 잠금을 해제한다.
    -SELECT RELEASE_LOCK('aGVyYg==');
    -
    --- 위 3개 함수 모두 정상적으로 락을 획득하거나 해제한 경우에 1을, 아니면 0을 반환한다.
    -
    --- 모든 문자열에 대한 잠금을 해제한다. 해제된 잠금의 개수를 반환한다.
    -SELECT RELEASE_ALL_LOCKS();
    -
    -

    메타데이터 락(Metadata lock)

    -

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    -명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    -보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    -
    -- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
    --- 아래 구문 실행 시 메타데이터 락을 자동으로 획득한다.
    -RENAME TABLE rank TO rank_backup, rank_new TO rank;
    +-- Next-Key Locks: 21부터 30, 31부터 40에 락이 걸린다.
    +SELECT * FROM table_name where id BETWEEN 25 AND 35 for update;
     

    참고 자료

    Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
    -MySQL의 User Level Lock를 활용한다면?, gywndi
    -Locking Functions, MySQL 5.7 Reference
    -Locking Functions, MySQL 8.0 Reference

    +Optimistic and Pessimistic record locking, IBM
    +MySQL Innodb Locks, cecil1018
    +MySQL 8.0 InnoDB Locks, MySQL
    +Locks Set by Different SQL Statements in InnoDB, MySQL

    \ No newline at end of file diff --git a/tags/log.html b/tags/log.html index 1e9b4b768..93f1b46b7 100644 --- a/tags/log.html +++ b/tags/log.html @@ -13,11 +13,11 @@ - - + + -

    "log" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    CloudWatch

    +

    "log" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    CloudWatch

    AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
    지표를 감시하여 알림을 보내는 기능도 제공한다.
    프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
    @@ -49,7 +49,7 @@

    설치

    사용 설명서에 각 인스턴스 유형마다 다운로드 링크가 자세하게 안내되어 있다.

    Wizard

    -

    CloudWatch Wizard를 사용하면 간단하게 설정 파일 생성할 수 있다.
    +

    CloudWatch Wizard를 사용하면 간단하게 설정 파일 생성할 수 있다.
    로그를 수집하도록 설정하는 경우 Wizard 실행 명령어 입력 전 log 파일의 절대 경로를 복사해두는 것이 좋다.
    아래의 명령어를 입력하여 Wizard를 실행할 수 있다.

    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
    @@ -97,7 +97,7 @@ 

    참고 자료

    Amazon CloudWatch 요금
    Linux 인스턴스 지표
    서버에 CloudWatch 에이전트 설치 및 실행
    -CloudWatch Agent를 Parameter Store에서 관리해 보기
    +CloudWatch Agent를 Parameter Store에서 관리해 보기
    CloudWatch에이전트 구성 파일

    \ No newline at end of file diff --git a/tags/mock.html b/tags/mock.html index 1e9480d22..c72fd0dbf 100644 --- a/tags/mock.html +++ b/tags/mock.html @@ -13,11 +13,11 @@ - - + + -

    "Mock" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    테스트 대역이란?

    +

    "Mock" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    테스트 대역이란?

    모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
    Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

    테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
    @@ -28,7 +28,7 @@ Fake --> TestDouble">

    더미(Dummy)

    가장 단순하고, 원시적인 유형의 테스트 대역이다.
    -기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
    +기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
    만약 메서드가 무언가 반환을 해야하는 경우 0, null과 같은 값을 반환한다.

    스텁(Stub)

    시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
    @@ -48,7 +48,7 @@

    가짜(Fake)

    상호작용에 따른 목과 스텁 구분

    단위 테스트 p.149 에서는 테스트 대역을 크게 목과 스텁으로 구분한다.
    목은 SUT와 관련된 상호작용을 모방하고 검사하는 반면, 스텁은 단순 모방만 한다.

    -
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색
    +
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색

    테스트 대상 시스템
    테스트를 하려는 대상

    참고 자료

    diff --git a/tags/mockito.html b/tags/mockito.html index 83dfb5128..41cf8d533 100644 --- a/tags/mockito.html +++ b/tags/mockito.html @@ -13,11 +13,11 @@ - - + + -

    "Mockito" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 3분

    개요

    +

    "Mockito" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 3분

    개요

    정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
    하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

    예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

    diff --git a/tags/monitoring.html b/tags/monitoring.html index 26bdac8b1..0fc9ba989 100644 --- a/tags/monitoring.html +++ b/tags/monitoring.html @@ -13,11 +13,11 @@ - - + + -

    "monitoring" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    CloudWatch

    +

    "monitoring" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    CloudWatch

    AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
    지표를 감시하여 알림을 보내는 기능도 제공한다.
    프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
    @@ -49,7 +49,7 @@

    설치

    사용 설명서에 각 인스턴스 유형마다 다운로드 링크가 자세하게 안내되어 있다.

    Wizard

    -

    CloudWatch Wizard를 사용하면 간단하게 설정 파일 생성할 수 있다.
    +

    CloudWatch Wizard를 사용하면 간단하게 설정 파일 생성할 수 있다.
    로그를 수집하도록 설정하는 경우 Wizard 실행 명령어 입력 전 log 파일의 절대 경로를 복사해두는 것이 좋다.
    아래의 명령어를 입력하여 Wizard를 실행할 수 있다.

    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
    diff --git a/tags/my-sql.html b/tags/my-sql.html
    index 384b2d134..7d6e69197 100644
    --- a/tags/my-sql.html
    +++ b/tags/my-sql.html
    @@ -13,11 +13,11 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "MySQL" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    MySQL 엔진의 잠금

    +

    "MySQL" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    MySQL 엔진의 잠금

    MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
    MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

    글로벌 락(Global lock)

    @@ -70,7 +70,7 @@

    네임드 락(Named lock)

    SELECT RELEASE_ALL_LOCKS();

    메타데이터 락(Metadata lock)

    -

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    +

    데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금이다.
    명시적으로 획득 또는 해제 할 수 없지만 테이블의 이름을 변경하는 경우 자동으로 획득한다.
    보통 배치 프로그램에서 실시간으로 테이블을 바꿔야하는 경우에 사용된다.

    -- 배치 프로그램에서 별도의 임시 테이블에 서비스용 랭킹 데이터 생성 후 기존 테이블을 백업하는 경우
    diff --git a/tags/mysql.html b/tags/mysql.html
    index 7c22ee55b..95c7a1047 100644
    --- a/tags/mysql.html
    +++ b/tags/mysql.html
    @@ -13,11 +13,11 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "mysql" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 21분

    복제(Replication)

    +

    "mysql" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 21분

    복제(Replication)

    한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
    원본 데이터를 가지는 서버를 Primary 또는 Source 라고 부르고, 복제된 데이터를 가지는 서버를 Secondary 또는 Replica 라고 부른다.

    복제를 하는 이유

    @@ -26,7 +26,7 @@

    복제를 하는 이유

    이를 처리하기 위해 복제를 통한 스케일 아웃을 적용하여 애플리케이션에서 사용하는 쿼리들을 각각의 데이터베이스로 분산 시킬 수 있다.

    2. 데이터 백업

    실제 운영되는 서비스가 사용하고 있는 DB에서 백업을 진행하는 경우, 서비스에 영향을 미칠 수 있다.
    -따라서 실제 서비스에 영향이 가지 않도록 복제를 통해 Replica 서버를 구축하여, Replica 서버에서 복제를 진행하는 방법으로 영향을 최소화 할 수 있다.

    +따라서 실제 서비스에 영향이 가지 않도록 복제를 통해 Replica 서버를 구축하여, Replica 서버에서 복제를 진행하는 방법으로 영향을 최소화 할 수 있다.

    3. 데이터 분석

    백업과 마찬가지로 복잡하고 무거운 분석용 쿼리의 서비스에 영향을 미칠 수 있다.
    마찬가지로 복제를 사용해 분석용 쿼리를 사용할 수 있는 환경을 만들 수 있다.

    @@ -72,7 +72,7 @@

    글로벌 트랜잭

    복제 토폴로지

    싱글 레플리카 복제 구성

    가장 간단한 구성으로 제일 많이 사용하는 형태다.
    -replica 서버를 읽기 전용, 예비 서버, 백업 용도로 많이 사용한다.

    +replica 서버를 읽기 전용, 예비 서버, 백업 용도로 많이 사용한다.

    복제 토폴로지 W[Web Server] -- 읽기 + 쓰기 --> SR1 W -- 읽기 + 쓰기 --> SR2 SR1[Source/Replica 1] --> SR2[Source/Replica 2]"> -

    ACTIVE-ACTIVE: 2개의 서버 모두 쓰기 작업을 수행하는 형태
    +

    ACTIVE-ACTIVE: 2개의 서버 모두 쓰기 작업을 수행하는 형태
    ACTIVE-PASSIVE: 하나의 서버에서만 쓰기 작업을 수행하는 형태

    멀티 소스 복제 구성

    여러개의 source 서버와 하나의 replica 서버를 사용하는 구성이다.
    diff --git a/tags/oop.html b/tags/oop.html index bae12f057..16093f038 100644 --- a/tags/oop.html +++ b/tags/oop.html @@ -13,11 +13,11 @@ - - + + -

    "OOP" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 9분

    GRASP(General Responsibility Assignment Software Pattern)

    +

    "OOP" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 9분

    GRASP(General Responsibility Assignment Software Pattern)

    크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

    각 패턴마다 Solution과 Problem로 구성되어 있다.

    정보 전문가 패턴(Information Expert)

    @@ -27,7 +27,7 @@

    정보 전문가 패턴(Infor

    필요한 정보를 가진 객체들로 책임이 분산된다.

    창조자 패턴(Creator)

    Q: 누가 객체 A를 생성하는가?

    -

    A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

    +

    A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

    • B가 A 객체를 포함 또는 참조한다.
    • B가 A 객체를 기록한다.
    • @@ -67,7 +67,7 @@

      높은 응집도 패턴(High Cohes

      변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

        -
      • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
      • +
      • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
      • 유지보수가 쉬워진다.
      • 낮은 결합도 또한 지원한다.
      • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.
      • @@ -90,8 +90,8 @@

        변경 보호 패턴(Protected

        Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

        A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

        간접 참조 패턴(Indirection)

        -

        Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

        -

        A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

        +

        Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

        +

        A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

        중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

        중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

        순수한 가공물 패턴(Pure Fabrication)

        diff --git a/tags/pattern.html b/tags/pattern.html index ddebed146..fa69dc64e 100644 --- a/tags/pattern.html +++ b/tags/pattern.html @@ -13,11 +13,11 @@ - - + + -

        "Pattern" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

        모든 태그 보기

        · 약 5분

        요구사항

        +

        "Pattern" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

        모든 태그 보기

        · 약 5분

        요구사항

        지하철 미션에는 다음과 같은 요구사항이 있었다.

        • 거리별 추가 요금 정책
        • @@ -36,7 +36,7 @@

          인터페이스 사용

          public class AgeDiscountFarePolicy implements FarePolicy { ... }

    composite1

    -

    모든 요금 정책을 포함하는 새로운 요금 정책 만들기

    +

    모든 요금 정책을 포함하는 새로운 요금 정책 만들기

    나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
    이 또한 FarePolicy를 구현한 형태가 되고, 필드로는 나머지 구현체들을 가지고 있다.

    public class SubwayFarePolicy implements FarePolicy {
    @@ -112,7 +112,7 @@ 

    컴포지트 패턴의

    패턴 사용시 주의해야할 부분

    패턴은 공통으로 사용 가능한 역할, 책임, 협력의 템플릿이다.
    반복되는 문제를 효율적으로 해결할 수 있지만 패턴에 매몰되서는 안된다.
    -패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
    +패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
    항상 트레이드오프를 생각하자!

    참고 자료

    컴포지트 패턴, GoF의 디자인 패턴
    diff --git a/tags/performance-test.html b/tags/performance-test.html index a643bbcba..aad64be60 100644 --- a/tags/performance-test.html +++ b/tags/performance-test.html @@ -13,11 +13,11 @@ - - + + -

    "performance test" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    성능 테스트

    +

    "performance test" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    성능 테스트

    API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

    시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
    다양한 상황에 대비해서 성능 테스트를 해야한다.

    @@ -26,7 +26,7 @@

    스모크 테스트(Smoke Test)

    최소한의 부하를 주어 시스템이 정상적으로 동작하는지 확인하는 테스트

    VU를 최소한으로 두고, 짧은 시간을 가지고 테스트한다.
    다른 테스트를 시작하기 전에 스모크 테스트를 함으로써 테스트 스크립트에 오류가 없는지 확인할 수 있고, 성능 지표가 정상적으로 수집, 모니터링 되고 있는지 확인할 수 있다.

    -

    가상 사용자는 서버 애플리케이션에 대해 특정 테스트를 실행한다.
    +

    가상 사용자는 서버 애플리케이션에 대해 특정 테스트를 실행한다.
    이는 다른 가상 사용자와 독립적으로 실행되며, 여러 가상 사용자를 사용하여 동시 연결을 할 수 있다.
    스레드라고 생각하면 된다.

    스파이크 테스트(Spike Test)

    diff --git a/tags/python.html b/tags/python.html index 60b2fc571..b6b913c9c 100644 --- a/tags/python.html +++ b/tags/python.html @@ -13,11 +13,11 @@ - - + + -

    "Python" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 7분

    개요

    +

    "Python" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 7분

    개요

    이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

    사용 기술

    언어: Python 3.10
    @@ -36,8 +36,8 @@

    요구사항

  • 위도, 경도로 이루어진 배열을 입력받는다.
  • 이미지 생성
  • 선과 점 표현
  • -
  • 투명한 배경색
  • -
  • 위경도 차이가 크든 작든 제공하는 이미지 내에 경로가 다 포함되어 있어야 한다.
  • +
  • 투명한 배경색
  • +
  • 위경도 차이가 크든 작든 제공하는 이미지 내에 경로가 다 포함되어 있어야 한다.
  • 이미지 출력 방식

      diff --git a/tags/replication.html b/tags/replication.html index 2e266a066..8fe9823d0 100644 --- a/tags/replication.html +++ b/tags/replication.html @@ -13,11 +13,11 @@ - - + + -

      "replication" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 21분

      복제(Replication)

      +

      "replication" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 21분

      복제(Replication)

      한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
      원본 데이터를 가지는 서버를 Primary 또는 Source 라고 부르고, 복제된 데이터를 가지는 서버를 Secondary 또는 Replica 라고 부른다.

      복제를 하는 이유

      @@ -72,7 +72,7 @@

      글로벌 트랜잭

      복제 토폴로지

      싱글 레플리카 복제 구성

      가장 간단한 구성으로 제일 많이 사용하는 형태다.
      -replica 서버를 읽기 전용, 예비 서버, 백업 용도로 많이 사용한다.

      +replica 서버를 읽기 전용, 예비 서버, 백업 용도로 많이 사용한다.

      복제 토폴로지 W[Web Server] -- 읽기 + 쓰기 --> SR1 W -- 읽기 + 쓰기 --> SR2 SR1[Source/Replica 1] --> SR2[Source/Replica 2]"> -

      ACTIVE-ACTIVE: 2개의 서버 모두 쓰기 작업을 수행하는 형태
      +

      ACTIVE-ACTIVE: 2개의 서버 모두 쓰기 작업을 수행하는 형태
      ACTIVE-PASSIVE: 하나의 서버에서만 쓰기 작업을 수행하는 형태

      멀티 소스 복제 구성

      여러개의 source 서버와 하나의 replica 서버를 사용하는 구성이다.
      diff --git a/tags/retrospective.html b/tags/retrospective.html index 2dcb5bc29..9c4d60aab 100644 --- a/tags/retrospective.html +++ b/tags/retrospective.html @@ -13,65 +13,37 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 9분

      1단계: https://github.com/woowacourse/jwp-refactoring/pull/465
      -2단계: https://github.com/woowacourse/jwp-refactoring/pull/547
      -3단계: https://github.com/woowacourse/jwp-refactoring/pull/610
      -4단계: https://github.com/woowacourse/jwp-refactoring/pull/721

      -

      리팩터링 미션

      -

      요구사항 작성 → 테스트를 통한 코드 보호 → 리팩터링 → 의존성 리팩터링 → 멀티모듈 순서로 미션을 진행했다.
      -미션에 온전히 집중하고 싶었지만, 프로젝트와 병행하면서 진행했기에 어느정도 타협보고 진행한 부분이 많아서 아쉬웠다.

      -

      1, 2단계

      -

      1단계는 요구사항을 작성하고, 테스트 코드를 작성하여 추후에 리팩터링 할 때 안정감 있게 진행할 수 있도록 준비하는 과정이었다. -요구사항을 작성할 때 제공된 용어 사전을 최대한 활용하면서 기존의 코드를 보면서 요구사항을 정리했다. -테스트는 시간 관계상 API, 서비스 둘 중 하나만 통합 테스트를 진행해야겠다는 생각이 들었다.

      -

      최종적으로 서비스 기준으로 통합 테스트를 작성했는데 약간 후회되는 결정이었던 것 같다.
      -리팩터링 과정에서 API 명세가 바뀌지 않아야 한다는 것을 기준을 잡고 이번 미션을 한다고 가정했을 때 API 기준으로 테스트를 작성하고, 리팩터링을 진행하는 것이 더 안정감 있다고 생각한다.

      -

      2단계는 작성된 테스트 기반으로 리팩터링 하는 미션이었다.
      -서비스에서 도메인을 직접 반환하는 구조였는데, 도메인에 JPA를 적용하면 기존 명세와 달라질 것을 우려해서 DTO로 수정하는 작업을 먼저 진행했다. -DTO 이후에 서비스에 있는 로직을 도메인으로 이동시키고, 최종적으로 JPA를 적용하는 순서로 리팩터링을 진행했다. -이 과정에서 의존성 방향이 양방향인 부분도 생겨났다.

      -

      소프트웨어의 복잡성을 다루는 지혜

      -

      중간에 소프트웨어 복잡성을 다루는 지혜에 관한 제이슨의 강의가 있었다.
      -소프트웨어의 복잡성을 다루는 지혜는 에릭 에반스의 저서 도메인 주도 설계의 부제이다.

      -

      도메인 주도 설계는 유비쿼터스 언어, 전략적 설계, 전술적 설계가 중요하다고 한다.
      -유비쿼터스 언어, 전략적 설계가 전체의 90%에 해당할 정도로 중요하다고 한다. 또한 전술적 설계만 하는 경우를 DDD Lite 라고 한다.

      -

      간단히 도메인 주도 설계에서 나오는 단어를 정리한다면 다음과 같다.

      -
      단어설명
      도메인소프트웨어로 해결하고자 하는 문제 영역
      바운디드 컨텍스트해결 영역, 관심사를 분리하고 격리하여 문제 해결에 집중할 범위
      유비쿼터스 언어프로젝트에 이해관계자들의 공통된 언어로, 서로의 의사소통 비용을 줄이기 위해 사용하는 언어
      전략적 설계도메인 전문가와 개발자가 함께 유비쿼터스 언어를 이용하여 도메인과 관련된 지식을 이해하고 이를 바탕으로 경계를 나눠 바운디드 컨텍스트를 정의하고, 컨텍스트 맵을 생성하는 것을 포함하는 과정
      전술적 설계전략적 설계에서 정의한 바운디드 컨텍스트와 도메인을 이용하여 애그리거트, Entity와 VO, Repository 등을 구현하는 과정
      -

      이 외에도 다양한 내용들이 나왔지만, 지식을 제대로 흡수하지는 못했다.

      -

      3, 4단계

      -

      제이슨의 강의를 듣고, 조영호님의 우아한객체지향 유튜브 영상을 본 다음 3, 4단계를 진행했다.

      -

      3단계는 의존성 리팩터링에 관한 내용이었다. 클래스 간 방향, 패키지 간 방향을 단방향이 되도록 리팩터링을 진행해야 했었다. -함께 생성되고 삭제되는 객체들을 묶고, 결합도를 낮추기 위해 생명주기가 다르다면 id를 이용하여 참조하도록 변경했다.

      -

      의존성을 분리하기 위해 이벤트도 사용해보았다. 이벤트는 현재 기준으로 과거에 벌어진 것을 표현하기 때문에 이벤트명은 과거 시제가 되어야하는 것을 알았다. -처음에는 애플리케이션 이벤트를 사용했지만, 서비스 로직을 최대한 간단하게 하기 위해 도메인 이벤트도 사용해보았다.

      -

      4단계는 멀티모듈로 분리하는 미션이었는데 3단계에서 분리해둔 패키지 그대로 분리하지는 않았다.
      -3단계에서는 함께 생성되고 삭제되는 객체 기준으로 분리했다. 4단계에서는 내가 인식하기 편한 기준으로 분리를 했다. -아직 분리한 기준에 대한 근거가 모호했고, 이에 대한 공부를 조금 더 해야겠다고 생각했다.

      - -

      추가로 테스트 격리를 위한 직접 작성한 @ServiceTest 커스텀 애너테이션이 있었는데, 상위 모듈의 테스트에서 만든 클래스를 하위 모듈에서는 사용할 수 없었다. -따라서 TestFixtures를 사용하여 해결했다.

      -

      마무리

      -

      우아한테크코스의 마지막 미션이니 만큼, 가장 흥미로운 미션이었고 배울점도 많았던 것 같다.
      -바쁜 기간이라 많은 리뷰를 남기지 못했던 리뷰이 호이에게 미안하고, 코멘트 꼼꼼하게 달아주고 미션에 대한 이야기도 오프라인으로 많이 나눈 리뷰어 테오에게 너무 감사하다.

      -

      참고 자료

      -

      도메인 원정대, 우아콘 2021
      -우아한객체지향, 우아한테크세미나
      -TestFixtures, 권남님

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      적당한 전환점, 2022년을 돌아보며

      +

      전역

      +

      약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
      +조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

      +

      조금 더 미래에 대한 생각을 해볼걸 그랬다.
      +전역을 했지만 뭐 하나 제대로 할 줄 아는 것도 없으니 넓은 바닷속에 덩그러니 놓아진 기분이 괜히 들었었다.
      +일찍 생각을 정리하여 방향을 잡지 못했기에 아쉬움이 많이 남았다.

      +

      자바

      +

      전역을 하고 진로를 고민하다 향로님의 자바 공화국 포스팅을 읽고 나서 자바 공부를 시작했다.
      +유명한 인프런의 김영한님의 스프링 강의도 있고, 좋은 자바 개발 서적이 많아서 독학하기로 결정했다.
      +하다 보니 자바와 스프링을 공부하면서 “왜 진작하지 않았지”라는 생각도 많이 들었다.
      +양질의 자료도 많았기 때문에, 예전에 노드로 개발했을 때 풀지 못했던 답답함을 많이 해소했던 것 같다.

      +

      23년에는 조금 더 깊게 자바를 공부해볼 생각이다.
      +언어를 하나 깊게 공부하는 건 많은 도움이 되는 것 같다.

      +

      스터디

      +

      김영한님의 강의를 거의 다 들었을 때쯤, 항상 강의에서 언급되는 토비의 스프링을 읽어보고 싶어졌고
      +혼자 공부하기에는 동기부여도 부족했기 때문에 스터디를 시작했다.
      +다른 사람에게 설명을 해야 했기 때문에 더욱 꼼꼼하게 공부를 할 수 있어서 좋았지만 나에게는 내용이 꽤나 어려워서 시간을 많이 소비했다.
      +같이 스터디하시는 분과 7개월 동안 스터디를 꾸준히 이어나가 총 3권의 책을 읽을 수 있었다.

      +

      우아한 테크코스

      +

      군 복무 중일 때 지원했다 떨어진 우아한 테크코스를 다시 지원했다.
      +이번 연도에 취업을 하는 게 목표였지만 내가 가지고 있는 특별한 무기가 없다는 걸 깨달았다.
      +적지 않은 시간을 투자해 준비를 했고, 감사하게도 이번에는 최종 합격을 했다.

      +

      난 사람들과 소통하고, 협업하는 능력이 부족하다고 생각을 많이 했다.
      +우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

      +

      2023년에는

      +

      마음의 여유가 없었던 2022년이었던 것 같다.
      +하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

      \ No newline at end of file diff --git a/tags/retrospective/page/10.html b/tags/retrospective/page/10.html index c3258c63d..ccc3facc2 100644 --- a/tags/retrospective/page/10.html +++ b/tags/retrospective/page/10.html @@ -13,85 +13,46 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 8분

      1단계: https://github.com/woowacourse/jwp-subway-path/pull/16
      -2, 3단계: https://github.com/woowacourse/jwp-subway-path/pull/126

      -

      지하철 미션

      -

      점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
      -지하철 미션은 밀리랑 페어를 진행했다.
      -간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
      -이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
      -API와 테이블 구조를 우리가 정할 수 있는 상황이었고, 도메인 로직이 복잡했기 때문에 도메인을 먼저 구현했다.

      -

      노선의 구간 추가 및 삭제

      -

      노선을 저장하는 방법에 대해서 밀리와 이야기를 나눴다.

      -
        -
      1. 구간을 데이터베이스에서 전부 제거하고 전부 추가하는 방법
      2. -
      3. 변경된 요소만 데이터베이스에 반영하는 방법
      4. -
      -

      페어 시간이 짧아서 더욱 간단한 1번을 선택했고, 시간 내 요구사항을 만족시키기 위해 더 간단하게 구현하는 방법을 선택하는 것도 좋은 트레이드오프였던 것 같다.
      -추후 페어가 끝나고 리뷰어인 서브웨이가 일부분만 반영하는 것으로 개선해 보는 것도 좋을 것 같다고 코멘트를 남겨주셔서 추가 및 제거된 요소만 반영하도록 변경했다.

      -

      부족했던 부분

      -

      미션의 난이도가 올라간 만큼, 페어 할 땐 컨디션 관리도 잘하려고 노력하고 미션 할 때도 집중해서 잘 끝낸 것 같다.
      -우아한테크코스를 진행하면서 알아야 하는 게 많아지면서 가끔 조바심을 가질 때가 있는 것 같은데, 조바심을 경계할 필요가 있을 것 같다.
      -부족한 부분은 인정하고, 앞으로 나아가야겠다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      1단계: https://github.com/woowacourse/jwp-shopping-cart/pull/244
      +2단계: https://github.com/woowacourse/jwp-shopping-cart/pull/300

      +

      웹 장바구니 미션

      +

      장바구니 미션은 블랙캣이랑 진행했다.
      +요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
      +2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
      +Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
      +이전에 스프링 사용할 때는 아무 생각 없이 코드를 작성하는 경우가 많았는데, 코드를 작성할 때 근거가 생기고 있는 것 같다.

      새로 학습한 부분

      -

      컴포지트 패턴으로 요금 정책 추상화

      -

      요금 정책은 기본요금 정책, 거리별 요금 정책, 연령별 할인 정책이 있었다.
      -요금을 더하는 부분과, 할인하는 부분이 있어서 이 둘을 분리할까 생각했지만, 이 정도 크기의 애플리케이션에서는 오히려 분리하지 않고 하나로 합치는 게 더 좋다고 생각했다.
      -또한 분리하지 않는다면 정책의 순서가 중요한데, 연령별 할인 정책을 마지막에 두어야 했기 때문에 책임 연쇄 패턴도 고려를 했지만 조금 더 간결해 보이는 컴포지트 패턴을 선택했다.

      -

      도메인에 특정 기술의 의존성을 분리

      -

      처음에 도메인 패키지에 jgrapht 라이브러리를 의존하고 있는 클래스를 두어서 도메인 패키지가 jgrapht와 강결합이 되어버렸다.
      -따라서 도메인 패키지 내에는 경로 검색에 대한 인터페이스를 두고, 세부 구현은 도메인 패키지 외부로 분리했다.
      -최대한 간결하게 구현한다고 생각을 해도, 이런 부분은 인터페이스를 두어 결합을 피하는 것이 좋을 것 같다.

      -

      컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
      -이때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

      -

      인수 테스트 작성

      -

      인수 테스트는 사용자 스토리 시나리오 기반 테스트다.
      -브라운이 해주신 강의 + 유튜브에 있는 브라운의 강의를 보고 지하철 미션에 인수 테스트를 적용해 보았다.
      -메서드, 변수명을 전부 한글로 작성했는데 전체적인 흐름을 알기 편하고 읽기도 좋았다.
      -그리고 인수 테스트에 필요한 Steps를 만드는 과정이 너무 재밌었다.

      -

      결과는 아래와 같다.

      -
      @Nested
      -public class 노선을_전체_조회할_때 {
      -
      -    @Test
      -    void 상행종점역_부터_하행종점역으로_정렬된_결과를_반환한다() {
      -        // given
      -        노선_생성_요청("2호선", "초록", 0);
      -        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("2호선", "잠실", "잠실새내", 5);
      -        구간_생성_요청("2호선", "잠실새내", "종합운동장", 오른쪽, 5);
      -
      -        노선_생성_요청("9호선", "고동", 0);
      -        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("9호선", "봉은사", "종합운동장", 3);
      -        구간_생성_요청("9호선", "종합운동장", "삼전", 오른쪽, 7);
      -
      -        // when
      -        final var 조회_결과 = 노선_전체_조회_요청();
      -
      -        // then
      -        요청_결과의_상태를_검증한다(조회_결과, 정상_요청);
      -        노선_전체_조회_결과를_확인한다(
      -                조회_결과,
      -                노선_정보("2호선", "초록", 0, "잠실", "잠실새내", "종합운동장"),
      -                노선_정보("9호선", "고동", 0, "봉은사", "종합운동장", "삼전")
      -        );
      -    }
      -}
      -
      +

      DTO 우발적 중복

      +

      장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.

      +

      dto1

      +

      클래스명을 제외하고 필드와 검증 로직 그 외 모든 게 같은 DTO를 보며 중복이라고 생각을 했고, 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
      +로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러 가지 종류로 나누어 설명하고 있다.

      +
        +
      • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
      • +
      • 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.
      • +
      +

      추가와 수정은 초기에는 중복으로 보이지만 초기 생성 시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다.
      +따라서 리뷰어 웨지가 아래와 같이 의존 역전을 이용하는 방법도 있다고 알려주셨다.

      +

      dto2

      +

      Interceptor에서 인증한 값 재사용

      +

      사실 조회를 두 번 하기 싫어서 다양한 방법을 생각했었는데 이번 미션에서는 ThreadLocal을 사용했다.
      +일단 Tomcat은 요청마다 다른 스레드를 사용하고, Interceptor에서 조회해서 만든 Credential을 ThreadLocal에 넣어두었다가 ArgumentResolver에서 꺼낸 다음 ThreadLocal을 clear 하면 문제가 없을 거라 판단했다.

      +

      리뷰어인 웨지에게도 어떤 방법을 사용할지 궁금증을 작성했었다.
      +웨지는 email에 index를 걸어두고 dao 재조회를 사용할 것이라고 했다.
      +재사용하지 않고 db에 인덱스를 걸 생각은 하지 못했는데, 제일 직관적이고 좋은 방법이라고 생각했다.

      페어에게 배울 부분

      -

      의견 조율하기

      -

      밀리가 필요한 부분에서 의견을 적극적으로 내줘서 진행이 수월했다.
      -의사소통이 매우 잘 돼서 좋았고 덕분에 시간 내에 요구사항을 만족해 미션을 제출할 수 있었던 것 같다.

      -

      꼼꼼하게 코딩하기

      -

      밀리는 코딩을 엄청 꼼꼼하게 하는 것 같다.
      -변수명, 메서드명을 중요하게 생각했고, 좋은 변수명을 잘 짓는 것 같다.
      -또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

      -

      편한 분위기

      -

      전체적으로 페어 할 때 편하게 진행했던 것 같다.
      -일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
      -나는 과연 다른 사람들에게 편한 사람일까?

      +

      기록

      +

      블랙캣은 기록을 굉장히 잘 하는 크루였다.
      +노션에 페어를 진행하면서 했던 내용 + 고민했던 부분 + 회고를 꼼꼼하게 기록해서 공유해 주었다.
      +추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

      +

      의견 일치시키기

      +

      페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
      +따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
      +블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

      +

      빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

      \ No newline at end of file diff --git a/tags/retrospective/page/11.html b/tags/retrospective/page/11.html index 4b0d810bb..1ffe33d17 100644 --- a/tags/retrospective/page/11.html +++ b/tags/retrospective/page/11.html @@ -13,46 +13,85 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      1단계: https://github.com/woowacourse/jwp-shopping-cart/pull/244
      -2단계: https://github.com/woowacourse/jwp-shopping-cart/pull/300

      -

      웹 장바구니 미션

      -

      장바구니 미션은 블랙캣이랑 진행했다.
      -요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
      -2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
      -Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
      -이전에 스프링 사용할 때는 아무 생각 없이 코드를 작성하는 경우가 많았는데, 코드를 작성할 때 근거가 생기고 있는 것 같다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 8분

      1단계: https://github.com/woowacourse/jwp-subway-path/pull/16
      +2, 3단계: https://github.com/woowacourse/jwp-subway-path/pull/126

      +

      지하철 미션

      +

      점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
      +지하철 미션은 밀리랑 페어를 진행했다.
      +간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
      +이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
      +API와 테이블 구조를 우리가 정할 수 있는 상황이었고, 도메인 로직이 복잡했기 때문에 도메인을 먼저 구현했다.

      +

      노선의 구간 추가 및 삭제

      +

      노선을 저장하는 방법에 대해서 밀리와 이야기를 나눴다.

      +
        +
      1. 구간을 데이터베이스에서 전부 제거하고 전부 추가하는 방법
      2. +
      3. 변경된 요소만 데이터베이스에 반영하는 방법
      4. +
      +

      페어 시간이 짧아서 더욱 간단한 1번을 선택했고, 시간 내 요구사항을 만족시키기 위해 더 간단하게 구현하는 방법을 선택하는 것도 좋은 트레이드오프였던 것 같다.
      +추후 페어가 끝나고 리뷰어인 서브웨이가 일부분만 반영하는 것으로 개선해 보는 것도 좋을 것 같다고 코멘트를 남겨주셔서 추가 및 제거된 요소만 반영하도록 변경했다.

      +

      부족했던 부분

      +

      미션의 난이도가 올라간 만큼, 페어 할 땐 컨디션 관리도 잘하려고 노력하고 미션 할 때도 집중해서 잘 끝낸 것 같다.
      +우아한테크코스를 진행하면서 알아야 하는 게 많아지면서 가끔 조바심을 가질 때가 있는 것 같은데, 조바심을 경계할 필요가 있을 것 같다.
      +부족한 부분은 인정하고, 앞으로 나아가야겠다.

      새로 학습한 부분

      -

      DTO 우발적 중복

      -

      장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.

      -

      dto1

      -

      클래스명을 제외하고 필드와 검증 로직 그 외 모든 게 같은 DTO를 보며 중복이라고 생각을 했고, 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
      -로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러 가지 종류로 나누어 설명하고 있다.

      -
        -
      • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
      • -
      • 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.
      • -
      -

      추가와 수정은 초기에는 중복으로 보이지만 초기 생성 시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다.
      -따라서 리뷰어 웨지가 아래와 같이 의존 역전을 이용하는 방법도 있다고 알려주셨다.

      -

      dto2

      -

      Interceptor에서 인증한 값 재사용

      -

      사실 조회를 두 번 하기 싫어서 다양한 방법을 생각했었는데 이번 미션에서는 ThreadLocal을 사용했다.
      -일단 Tomcat은 요청마다 다른 스레드를 사용하고, Interceptor에서 조회해서 만든 Credential을 ThreadLocal에 넣어두었다가 ArgumentResolver에서 꺼낸 다음 ThreadLocal을 clear 하면 문제가 없을 거라 판단했다.

      -

      리뷰어인 웨지에게도 어떤 방법을 사용할지 궁금증을 작성했었다.
      -웨지는 email에 index를 걸어두고 dao 재조회를 사용할 것이라고 했다.
      -재사용하지 않고 db에 인덱스를 걸 생각은 하지 못했는데, 제일 직관적이고 좋은 방법이라고 생각했다.

      +

      컴포지트 패턴으로 요금 정책 추상화

      +

      요금 정책은 기본요금 정책, 거리별 요금 정책, 연령별 할인 정책이 있었다.
      +요금을 더하는 부분과, 할인하는 부분이 있어서 이 둘을 분리할까 생각했지만, 이 정도 크기의 애플리케이션에서는 오히려 분리하지 않고 하나로 합치는 게 더 좋다고 생각했다.
      +또한 분리하지 않는다면 정책의 순서가 중요한데, 연령별 할인 정책을 마지막에 두어야 했기 때문에 책임 연쇄 패턴도 고려를 했지만 조금 더 간결해 보이는 컴포지트 패턴을 선택했다.

      +

      도메인에 특정 기술의 의존성을 분리

      +

      처음에 도메인 패키지에 jgrapht 라이브러리를 의존하고 있는 클래스를 두어서 도메인 패키지가 jgrapht와 강결합이 되어버렸다.
      +따라서 도메인 패키지 내에는 경로 검색에 대한 인터페이스를 두고, 세부 구현은 도메인 패키지 외부로 분리했다.
      +최대한 간결하게 구현한다고 생각을 해도, 이런 부분은 인터페이스를 두어 결합을 피하는 것이 좋을 것 같다.

      +

      컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
      +이때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

      +

      인수 테스트 작성

      +

      인수 테스트는 사용자 스토리 시나리오 기반 테스트다.
      +브라운이 해주신 강의 + 유튜브에 있는 브라운의 강의를 보고 지하철 미션에 인수 테스트를 적용해 보았다.
      +메서드, 변수명을 전부 한글로 작성했는데 전체적인 흐름을 알기 편하고 읽기도 좋았다.
      +그리고 인수 테스트에 필요한 Steps를 만드는 과정이 너무 재밌었다.

      +

      결과는 아래와 같다.

      +
      @Nested
      +public class 노선을_전체_조회할_때 {
      +
      +    @Test
      +    void 상행종점역_부터_하행종점역으로_정렬된_결과를_반환한다() {
      +        // given
      +        노선_생성_요청("2호선", "초록", 0);
      +        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("2호선", "잠실", "잠실새내", 5);
      +        구간_생성_요청("2호선", "잠실새내", "종합운동장", 오른쪽, 5);
      +
      +        노선_생성_요청("9호선", "고동", 0);
      +        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("9호선", "봉은사", "종합운동장", 3);
      +        구간_생성_요청("9호선", "종합운동장", "삼전", 오른쪽, 7);
      +
      +        // when
      +        final var 조회_결과 = 노선_전체_조회_요청();
      +
      +        // then
      +        요청_결과의_상태를_검증한다(조회_결과, 정상_요청);
      +        노선_전체_조회_결과를_확인한다(
      +                조회_결과,
      +                노선_정보("2호선", "초록", 0, "잠실", "잠실새내", "종합운동장"),
      +                노선_정보("9호선", "고동", 0, "봉은사", "종합운동장", "삼전")
      +        );
      +    }
      +}
      +

      페어에게 배울 부분

      -

      기록

      -

      블랙캣은 기록을 굉장히 잘 하는 크루였다.
      -노션에 페어를 진행하면서 했던 내용 + 고민했던 부분 + 회고를 꼼꼼하게 기록해서 공유해 주었다.
      -추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

      -

      의견 일치시키기

      -

      페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
      -따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
      -블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

      -

      빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

      +

      의견 조율하기

      +

      밀리가 필요한 부분에서 의견을 적극적으로 내줘서 진행이 수월했다.
      +의사소통이 매우 잘 돼서 좋았고 덕분에 시간 내에 요구사항을 만족해 미션을 제출할 수 있었던 것 같다.

      +

      꼼꼼하게 코딩하기

      +

      밀리는 코딩을 엄청 꼼꼼하게 하는 것 같다.
      +변수명, 메서드명을 중요하게 생각했고, 좋은 변수명을 잘 짓는 것 같다.
      +또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

      +

      편한 분위기

      +

      전체적으로 페어 할 때 편하게 진행했던 것 같다.
      +일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
      +나는 과연 다른 사람들에게 편한 사람일까?

      \ No newline at end of file diff --git a/tags/retrospective/page/12.html b/tags/retrospective/page/12.html index 932fa3603..764217179 100644 --- a/tags/retrospective/page/12.html +++ b/tags/retrospective/page/12.html @@ -13,49 +13,39 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      1단계: https://github.com/woowacourse/jwp-racingcar/pull/24
      -2단계: https://github.com/woowacourse/jwp-racingcar/pull/128

      -

      웹 자동차 미션

      -

      사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
      -웹 자동차 미션에서는 비버와 페어가 매칭되었다.
      -레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

      -

      스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
      -첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
      -난이도 높은 미션이 아니었지만 리뷰어인 라빈에게 칭찬을 많이 받아서 기분이 좋았다.
      -라빈 감사합니다!

      -

      부족했던 부분

      -

      컨디션도 좋지 않고 열정도 식은 것 같은 느낌이 들었다.
      -미션이 다소 여유롭다고 느껴져서, 시간에 대한 부분도 잘 관리하지 못한 것 같다.
      -미션에 잘 집중하지 못해서 페어에게 많이 미안했고, 나 자신에게 아쉬웠던 부분이 많았다.

      -

      지난번 회고를 다시 보는데 집중을 잘 못한 경우가 많은 것 같다.
      -도전적이지 않거나 시간이 부족하지 않으면 집중을 잘 못하는 것 같다.
      -머릿속에서 시간적 여유가 있다고 생각할 때가 가장 위험한 순간인 것 같다.

      -

      함께 자라기에서 나온 난이도 높이기가 필요해지는 순간이다.

      -

      새로 학습한 부분

      -

      중요도가 있는 어노테이션부터 클래스 이름에 가깝게 명시하기

      -
      @SuppressWarnings("NonAsciiCharacters")
      -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
      -@Transactional
      -@AutoConfigureMockMvc
      -@SpringBootTest
      -public class RacingGameIntegrationTest {
      -
      -

      페어에게 배울 부분

      -

      비버의 성격
      -비버가 성격이 좋아서 편하게 페어를 할 수 있었다.
      -미션을 진행하면서 성급하지 않고 여유로워서 좋았다.

      -

      미션에 집중하는 부분
      -내가 미션에 잘 집중하지 못했는데도 같이 페어를 잘 진행한 것 같아서 좋았다.
      -비버가 미션에 잘 집중해서 그렇지 않았나 생각했다.
      -근육맨 비버라 그런지 체력이 좋아서 그런가?
      -중간에 잘 안 쉬고도 집중해서 미션을 진행하는 걸 보고 대단하다고 생각했다.

      -

      학습에 대한 열정
      -추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
      -비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
      -나도 5월부터 조금 더 화이팅 해야겠다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      개요

      +

      원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
      +레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

      +

      나의 채팅 확인하고 이어하는 기능

      +

      GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
      +예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

      +

      chat1

      +

      좋아요와 댓글 기능

      +

      다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
      +누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
      +또한 댓글 추가 및 삭제 기능도 추가했다.

      +

      키워드 추출

      +

      어떻게 키워드 추출을 할지 고민을 많이 했는데, 일단 GPT를 이용해서 키워드를 추출하기로 했다.
      +해당 부분은 첫 질문에 대한 키워드만 추출하도록 했다.
      +백엔드에선 말랑이 이벤트 이용해서 첫 채팅 요청이 이루어지면, 비동기로 키워드를 추출하는 질문을 추가로 날리도록 구현하였다.
      +CSV 형식으로 GPT에게 답변을 입력해달라고 요청받는데, 이 부분이 문제(프롬프트 엔지니어링 부분이 반환된다.)가 좀 있는 것 같아서 개선이 필요한 것 같다.

      +

      chat2

      +

      다른 크루의 채팅 복사해서 이어하는 기능

      +

      다른 크루들의 채팅을 읽다가 궁금한 점이 있다면 복사해서 바로 질문을 할 수 있는 기능을 추가했다.
      +채팅이 복사된 후 바로 GPT와 대화를 할 수 있는 메인 화면으로 이동한다.

      +

      사용성 고려하기

      +

      chat3

      +

      위 화면은 회원가입 창이다.
      +사실 가장 마음에 드는 부분이고, 회원가입(닉네임만 입력하지만)할 때 익명을 원하는 사람들의 고민을 도와주게 끔 음식, 과일, 과자 등의 요소들을 입력하도록 유도했다! +추가로 GPT의 답변이 오면 자동으로 화면을 스크롤 해주는 것과 같이 사용성을 개선해 보려고 노력했지만 쉽지 않았다.
      +제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

      +

      향후 계획

      +

      실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
      +크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
      +일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

      \ No newline at end of file diff --git a/tags/retrospective/page/13.html b/tags/retrospective/page/13.html index 85e823c21..ced9c85a0 100644 --- a/tags/retrospective/page/13.html +++ b/tags/retrospective/page/13.html @@ -13,54 +13,76 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      프론트엔트

      -

      닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
      -추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
      -자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
      -여유가 된다면 자신의 채팅을 볼 수 있는 기능이나, 채팅을 이어서 할 수 있는 기능, 댓글 기능도 추가할 예정이다.

      -

      백엔드

      -

      최대한 빨리 서비스를 크루들에게 제공하기로 정해서, 백엔드는 말랑이 일단 다 만들고 있다.
      -말랑이 한 부분이 너무 많아서 내가 못 따라가는 것 같다.
      -나중에 백엔드 코드를 이해하는 시간을 가져야겠다.

      -

      Http Request Header

      -

      아직 인증에 대한 부분을 하지 않아서 요청 헤더에 이름을 보내기로 했다.
      -말랑이 한글은 안된다고 말해줘서 Base64로 인코딩하고, 백엔드에서 디코딩 하여 사용하기로 했다.
      -아래는 pinia에 있는 name 값을 인코딩 하는 코드다. deprecated 되었다는데, 다른 방법을 사용할 줄 몰라서 일단 이걸 사용했다.

      -
      const encodedName = () => {
      -  const uriComponent = unescape(encodeURIComponent(name.value));
      -  return btoa(uriComponent);
      -};
      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      1단계: AWS 배포
      +2단계: https://github.com/woowacourse/jwp-shopping-order/pull/7

      +

      장바구니 주문 미션

      +

      배포 및 협업을 할 수 있는 미션이었다.
      +마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

      +

      배포

      +

      이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
      +각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
      +배포 스크립트를 작성하는 경험을 해볼 수 있었다.
      +배포 스크립트에 시간을 많이 투자하진 않았고, 다음과 같이 간단하게 작성했다.

      +
      echo "Start Deploy Script"
      +REPOSITORY_NAME=/home/ubuntu/jwp-shopping-order
      +PROJECT_NAME=jwp-shopping-order
      +
      +echo "Change Directory"
      +cd $REPOSITORY_NAME
      +
      +echo "Git Pull"
      +git pull origin step2
      +
      +echo "Build"
      +./gradlew bootJar
      +
      +echo "Copy, Start Server"
      +mv ./build/libs/$PROJECT_NAME.jar .
      +
      +PID=$(pgrep -f $PROJECT_NAME)
      +
      +if [ -n $PID ]; then
      +        kill -9 $PID
      +	sleep 5
      +fi
      +
      +nohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &
       
      -

      Elastic Beanstalk

      -

      가장 빠르게 백엔드를 배포할 수 있는 방법이 뭘지 고민하다가 Elastic Beanstalk를 사용하기로 했다.
      -Elastic Beanstalk를 사용하면 인프라에 대해 잘 알지 못해도 애플리케이션을 빠르게 배포하고 관리할 수 있다.
      -모니터링, 로깅, 로드 밸런싱 등 다양한 기능을 제공한다.

      -

      Elastic Beanstalk RDS 설정 후 분리

      -

      초기 설정 시 RDS를 연결하고 설정 완료 후 분리한다면, Beanstalk 인스턴스 -> RDS 요청 시 인바운드 설정을 안 해도 된다.
      -RDS 분리 시 Beanstalk에 기본적으로 설정되어 있는 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD와 같은 환경 변수가 같이 제거된다.
      -추가로 Elastic Beanstalk로 RDS를 설정하면 기본 데이터베이스 명은 ebdb다.

      -

      Elastic Beanstalk nginx 설정

      -

      업로드하는 zip 파일 내부에 .platform/nginx/conf.d/ 경로에 설정 파일을 추가하면 nginx 설정을 할 수 있다.

      -

      Jenkins

      -

      백엔드 코드를 일일히 배포하기 불편해서 Jenkins를 이용하여 Repository에 코드를 push 할 때 자동으로 배포가 되게 설정하기로 했다.
      -작년에 확인했을 땐 2022년 12월 31일까지 EC2 ARM 기반 t4g.small이 무료였는데, 다시 들어가 보니 2023년까지 12월 31일까지 t4g.small을 무료로 사용할 수 있었다.
      -t4g.small은 램이 2G인데, 예전에는 부족하지 않았다고 생각했는데 Java 17을 써서 그런가 빌드 할 때 램이 많이 부족한 것 같아서 Swap 메모리 2기가를 추가로 설정했다.
      -추가로 build.gradle에서 아래와 같이 설정한다면 테스트 시 사용하는 램을 늘릴 수 있다. 기본값은 512MB라고 한다.

      -
      test {
      -    maxHeapSize = "1024m"
      -}
      +

      협업

      +

      일단 우스랑 우코가 먼저 잠실로 와줘서 너무 감사했다.
      +백엔드가 아닌 다른 크루들과 해보는 첫 협업이라 약간 두근거렸다.
      +예상외로 대화가 잘 되어서, 빠르게 명세를 정할 수 있었다.

      +

      부족했던 부분

      +

      여러가지 방법에 대한 장단점을 고려해보기

      +

      백엔드와 테이블 명세나 쿠폰 구현에 대해서 이야기할 때 장단에 대해 많이 고려하지 못한 것 같다.
      +조금 더 시간을 많이 들여서 장단점을 고려했다면 더 좋은 결과물이 나오지 않았을까?
      +앞으로 선택의 순간에서 조금 더 시간을 들여보는 것도 좋을 것 같다.

      +

      새로 배운 부분

      +

      expose headers

      +

      웹 페이지에서 Location 헤더를 받을 수 없는 문제가 있었다.
      +기본적으로 허용 목록에 존재하는 응답헤더만 반환한다는 것을 모르고 있었다.
      +이를 expose headers 설정을 통해 해결할 수 있었다.
      +nginx 설정에 다음과 같이 추가해 주었다.

      +
      add_header 'Access-Control-Expose-Headers' 'Location'
       
      -

      Jenkins Blue Ocean

      -

      Blue Ocean은 Jenkins Pipeline을 구성하는 데에 있어 편리하게 해주는 도구다.
      -시각화도 잘 되어있고, 설정도 편리한 것 같다.
      -오늘 적용해 보니 램이 부족하여 중간에 잘 안되기도 하고 그래서 그냥 "Pipeline만 사용할 걸 그랬나?" 라는 생각이 든다.

      -

      참고 자료

      -

      Elastic Beanstalk, AWS
      -EC2 AWS Graviton, AWS
      -Default Memory Settings, AWS

      +

      읽기 전용 트랜잭션

      +

      단순 조회 요청에 대한 성능을 향상시켜준다는 것이라고 간단히만 알고 있었다.
      +이번에 코멘트가 달려서 조금 더 자세히 공부해 보기로 했다.
      +Transactional(readOnly = true)를 사용하는 경우 다음과 같이 동작한다.

      +

      setReadOnly(true) 설정이 된 Connection으로 연결을 시도를 한다. 이 설정을 하는 경우 DB마다 다르게 동작한다.

      +
        +
      • h2의 Connection 구현체는 readOnly 설정을 무시하는 방향으로 구현되어 Transactional 적용되지 않는다.
      • +
      • MySQL 8.0(InnoDB 사용 시)의 경우 읽기 전용으로 알려진 트랜잭션의 경우 트랜잭션 ID를 설정하지 않기 때문에 조회 속도가 더 빨라진다.
      • +
      +

      ORM 프레임워크를 사용한다면 prepareTransactionalConnection를 호출한다고 한다.
      +추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

      +

      DAO에 @Transactional 적용

      +

      DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
      +Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
      +DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

      \ No newline at end of file diff --git a/tags/retrospective/page/14.html b/tags/retrospective/page/14.html index 9de02540c..c21181f8f 100644 --- a/tags/retrospective/page/14.html +++ b/tags/retrospective/page/14.html @@ -13,63 +13,35 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      4월 21일 금요일

      -

      레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
      -레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
      -단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
      -글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

      -

      나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
      -Chat-GPT 서비스를 크루들에게 제공하고, 해당 크루들이 질문한 내용을 공유할 수 있는 건 어떤지?

      -

      기술이 목적인 사이드 프로젝트를 진행하면 좋을 것 같다는 답변을 들었고, 혼자 아니면 페어할 수 있을 정도의 인원으로 진행하면 좋겠다고 하셨다.
      -프론트랑 간단하게 배포까지 해본 경험이 있어서 혼자해도 크게 어렵지 않을 것 같아서 혼자 하기로 마음을 먹었다.

      -

      이건 못참지

      -

      도메인 구입 성공?

      -

      커피챗이 끝나고 집으로 돌아가는 길에 바로 도메인을 구매하려고 namecheap에서 적당한 도메인이 없을까 검색을 계속했다.
      -마치 어릴 때 했던 게임 닉네임 정하는 것처럼 시간이 오래 걸렸다.
      -dev, io, chat 도메인이 후보였고 집 가는 길에 결정만 하다가 구매하지 못했다.

      -

      말랑의 DM

      -

      집에 가서 밥을 먹고 말랑이랑 DM 하다 프로젝트를 같이 하자는 이야기가 나왔다.
      -우테코 최고 고수 말랑의 요구라 수락하지 않으면 후폭풍을 감당할 수 없었다.

      -

      이런저런 대화를 나누다가 난 빠르게 프로토타입을 만들어 보고 싶어서 프론트를 구현한다고 했고, 말랑은 GPT api를 조사하기로 했다.
      -추가로 도메인에 관한 이야기를 하다가 woowachat이 언급되었고, namecheap에서 chat 도메인을 사용한 woowa.chat으로 구매했다.
      -이후에 teco.chat으로 변경했다!

      -

      도메인 설정 및 배포

      -

      토요일에 구매한 도메인을 CDN, 보안 등 다양한 기능을 제공하는 Cloudflare에 도메인 등록을 했다.
      -나에게 익숙한 Nuxt3를 사용하기로 했고, Cloudflare Pages를 이용하여 배포했다.

      -

      GPT

      -

      무료 크레딧을 사용하니 api limit이 있어 분당 3번밖에 사용할 수 없었다.
      -일단 백엔드를 구축하기 전에는 무료 크레딧을 사용할 생각이다.

      -

      Sonarcloud

      -

      정적 코드 분석 도구로 Sonarcloud를 적용했다.
      -Sonarcloud는 SonarQube의 SaaS 버전이고 사용이 매우 편하다.
      -예전에 Sonarcloud를 사용할 땐 버튼 몇 번 누르면 적용할 수 있었는데, 이번에는 바로 github action을 사용하라는 안내 페이지로 이동했다.
      -Sonarcloud가 자체적으로 github repository에 push 하면 정적 분석을 해주는 기능을 원했고, Administration -> Analysis Method에 Automatic Analysis를 설정하니 되었다.
      -너무 꽁꽁 숨겨져있네

      -

      Tiptap

      -

      코드 하이라이팅 기능을 넣고 싶어서 Tiptap을 사용했다.
      -Tiptap은 Headless WYSIWYG 에디터로 사용자 정의 기능에 특화되어있는 에디터다.
      -아직 Tiptap이 제공하는 모든 기능을 자연스럽게 사용하지는 못하지만 CodeBlockLowlight 플러그인을 사용하여 코드 블록을 예쁘게 출력할 수 있었다.
      -api 반환값 그대로 tiptap의 content에 설정했더니 코드 블록이 설정되지 않아서 백 틱 3개를 <pre><code>로 변환했다.
      -추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
      -변환하는 로직은 GPT의 도움을 많이 받았다.

      -
      const replaceCodeFences = (input: String) => {
      -    const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
      -    return input
      -        .replace(codeFencesRegex, (match, p1, p2) => {
      -        const languageClass = p1 ? ` class="language-${p1}"` : "";
      -        return `<pre><code${languageClass}>${p2}</code></pre>`;
      -        })
      -        .replace(/\n/g, "<br>");
      -};
      -
      -

      Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

      -

      tecochat

      -

      폰트 및 favicon 적용

      -

      타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
      -추가로 favicon도 간단하게 적용해서 만족스러웠다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      레벨 인터뷰

      +

      레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
      +따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
      +이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
      +기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

      +

      API 문서 도구 선택

      +

      큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
      +백엔드 팀원이 함께 의사결정을 했고, 미션 기간이 짧은 만큼 팀 차원에서 비교적 학습하기 쉬운 Swagger를 선택했다.
      +추가로 들어가는 시간 대비 하이 리턴이라고 생각했다고 답변했다.

      +

      팀 차원의 학습 비용을 언급해서, 다음과 같은 좋은 피드백을 받았다.

      +
      +

      특히 팀으로 의사결정하는 과정을 공유해 준 점이 좋았고 기술적 의사결정 과정에서 팀의 학습비용을 고려한 점이 좋았음.
      +앞으로도 학습 비용은 주요하게 고려해야 할 사항

      +
      +

      PUT과 PATCH & 토큰과 세션

      +

      PUT과 PATCH 차이를 설명하는 부분에서는 PATCH를 사용할 때 페이로드가 적어진다는 내용을 빼먹고 답변을 했다.
      +토큰과 세션의 경우 기술을 잘 모르는 사람에게 설명해달라는 제약조건이 추가되었다.

      +

      해당 내용을 답변하면서 기술적인 깊이가 많이 부족했다는 생각이 든다.
      +실제로 레벨 2 때 이론적인 학습 시간이 매우 적었고, 집중력도 많이 부족했다.
      +앞으로 어떻게 깊이를 채울지 고민을 할 수 있는 질문들이었다.

      +

      추가로 기술을 잘 모르는 사람에게 설명하는 가정을 두고 학습을 한다면 큰 도움이 될 거라는 피드백을 받았다.

      +

      그 외 개선할 점

      +

      인터뷰할 때 특유의 말버릇을 개선하기
      +생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
      +기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
      +이전에 공부했던거 되돌아 보는 시간 가지기

      \ No newline at end of file diff --git a/tags/retrospective/page/15.html b/tags/retrospective/page/15.html index 06936f84c..8c4d594b0 100644 --- a/tags/retrospective/page/15.html +++ b/tags/retrospective/page/15.html @@ -13,77 +13,31 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 8분

      레벨 1이 끝났다.
      -우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
      -혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
      -하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

      -

      Keep

      -

      나만의 루틴 만들기

      -

      스스로가 외부의 영향을 많이 받는다고 생각한다.
      -최대한 꾸준히 할 수 있는 시간을 만드는 것이 중요하다고 생각한다.

      -

      매일 8시에 도착하여 아침에 해야 할 일을 정리하거나, 우선순위에 따라 처리하고
      -소화능력이 부족하기 때문에 점심은 도시락(그래봤자 계란2개)을 준비하고
      -항상 똑같은 컨디션을 유지하기 위해 항상 6시에 집에 간다.
      -이제 바빠질 테니 일찍 집에 가는 일은 어쩔 수 없이 줄어들겠지만😢

      -

      선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

      -

      크루들과 친하게 지내기

      -

      10명 정도의 크루의 닉네임을 외우고 친하게 지낸다면 성공적이라고 생각했었다.
      -하다 보니 더 많은 크루들의 닉네임을 외운 것 같다.
      -앞으로도 크루들과 친하게 지내고 아무 때나 말을 걸 수 있는 크루가 늘어나길 :)

      -

      글쓰기

      -

      글을 잘 쓰는 편은 아니지만 꾸준히 작성하려고 노력했다.
      -매 미션마다 회고를 작성하니 생각도 정리되고 개선점도 찾을 수 있어서 좋았다.

      -

      우아한테크코스에는 레벨마다 글쓰기를 진행하는데, 운이 좋게 글쓰기 상을 받았다.
      -사실 겉으로 드러내지 않았지만 꼭 받아보고 싶었다.
      -글쓰기 조원, 투표해 준 크루들에게 너무 감사하다.

      -

      코드 리뷰 스터디

      -

      누누, 주노, 다즐, 말랑, 박스터, 오잉, 깃짱와 코드 리뷰 스터디를 진행했다.
      -과연 도움이 될까 생각했지만 결과적으로는 코드 리뷰를 하면서 성장을 많이 한 것 같다.
      -투자한 시간 대비 가성비가 좋은 활동이었다.
      -누누가 스터디장인데 과연 꾸준히 이어나가려나?

      -

      레벨 인터뷰

      -

      인터뷰할 때 많이 떨지 않아서 좋았다.
      -남들 앞에서 이야기를 하거나, 면접을 보면 항상 엄청 떨어서 걱정했는데
      -기술적인 질문을 받았을 때 떨지 않고 잘 대답할 수 있었다.
      -우아한테크코스 생활을 하면서 다른 크루가 질문했을 때, 최대한 이해하기 쉽게 설명하려고 했던 경험이 도움이 된 것 같다.
      -이후 레벨 인터뷰를 진행할 때 다음과 같은 부분을 고려하면 더 좋을 것 같다.

      -
        -
      • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
      • -
      • 두괄식 표현
      • -
      • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
      • -
      • 설명할 수 있을만큼 시간 충분히 가지기
      • -
      • 인터뷰어의 질문 의도를 명확히 이해하지 못했다면 의도 다시 물어보기
      • -
      • 끝맺는 부분 연습하기(자신감 있게)
      • -
      • 기술적인 집착가지기
      • -
      • 기술적인 부분을 꼼꼼히 준비했으면 협업 관련 질문도 준비하기
      • -
      -

      Problem

      -

      페어프로그래밍

      -

      우아한테크코스를 진행하면서 가장 어려운 활동 중 하나라고 생각한다.
      -페어는 매번 바뀌고, 미션의 복잡도도 증가하기 때문인 것 같다.
      -소통 능력, 시간관리가 부족했고, 만족스럽지 않았다.
      -하지만 페어를 진행하고, 회고를 하다 보니 나만의 노하우가 쌓이는 느낌이다.
      -레벨 2에서는 부족했던 부분을 개선하여 함께하고 싶은 페어가 되고 싶다.

      -

      집중하는 시간⏱️ 부족

      -

      레벨 1을 진행하면서 집중하는 시간이 많이 부족했다.
      -이른 아침과 오후에 개인적으로 집중할 수 있는 공간을 예약해서 온전히 나만의 시간을 가져야겠다.

      -

      Try

      -

      허브🌿와의 티타임?

      -

      소프트 스킬을 늘릴 방법을 생각하다가 대화를 나누지 못한 다른 크루들과 깜짝 커피챗을 하면 어떨까 생각했다.
      -예를 들어 잡담방에 저와 커피챗 하실 분 :) 하면서 올릴 수 있을 것 같다.
      -참여하는 사람이 있을지, 안 좋게 보는 게 아닐지 걱정되지만 그래도 재밌을 것 같다.
      -저랑 허브티 한잔 하실래요?

      -

      기술적인 부분

      -

      우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
      -시간의 여유가 될 때 책을 조금씩 읽어야겠다.
      -블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

      -

      레벨 1을 마무리하며

      -

      시간이 빠르게 흘러갔다.
      -타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
      -또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 3분

      23년의 6월이 오고, 레벨 2가 끝났다.
      +빠르게 지나가서 조금 아쉽다.

      +

      학습

      +

      회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
      +항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
      +미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

      +

      고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
      +방학 그리고 레벨 3 때는 조금 더 이론적인 부분을 학습하는데 집중해야겠다.

      +

      점차 학습 범위가 넓어지면서 자연스럽게 모르는 내용이 쌓여간다.
      +필요한 내용은 앞으로 천천히 학습하면 되니까 조급해지지 말아야겠다.

      +

      수면

      +

      레벨 2를 진행하는 동안 수면이 많이 부족했었고, 결과적으로는 그날의 컨디션을 많이 좌우했던 것 같다.
      +앞으로 수면 시간을 늘리고, 좋은 수면 습관을 가지도록 노력해야겠다.

      +

      협업

      +

      레벨 2 마지막에 협업 미션이 있었다.
      +지금까지는 백엔드 크루들과 페어 프로그래밍을 하면서 협업을 경험했다.
      +이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

      +

      레벨 3 때부터 본격적으로 프로젝트가 시작된다.
      +팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

      +

      레벨 2를 마무리하며

      +

      회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. +읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

      \ No newline at end of file diff --git a/tags/retrospective/page/16.html b/tags/retrospective/page/16.html index e10194579..d92854d91 100644 --- a/tags/retrospective/page/16.html +++ b/tags/retrospective/page/16.html @@ -13,83 +13,42 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 8분

      1, 2단계: https://github.com/woowacourse/java-chess/pull/441
      -3, 4단계: https://github.com/woowacourse/java-chess/pull/529

      -

      체스

      -

      체스 미션에는 가비와 페어가 매칭되었다!
      -체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
      -하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
      -미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

      -

      가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
      -최종적으로 결정한 부분은 다음과 같다.

      -

      각 기물의 이동 가능여부
      -Rank와 File은 각각 위치값을 가지고 있고, 값의 차이를 이용해서 각 기물의 이동 가능 여부를 계산했다.
      -직선 → Rank와 File 차이 중 하나가 0이어야 한다.
      -대각선 → Rank와 File 차이의 절대값이 같아야 한다. ex) abs(-2) == abs(2)
      -나이트 → 차이의 절대값이 하나는 2 나머지 하나는 1이어야 한다.

      -

      도착 칸의 기물 여부
      -아군 → 이동이 불가능하다.
      -적군 → 이동이 가능하다. 적군을 잡는다.

      -

      중간에 기물 존재 여부
      -이동 경로에 기물이 존재하면 안된다.

      -

      데이터베이스 사용
      -체스 미션은 특별하게 데이터베이스와 연결하는 부분이 있었다.
      -체스 게임의 상태를 다음의 두가지 방법으로 정할 수 있다고 생각했다.

      -
        -
      • 기물 전체를 저장하는 방법
      • -
      • 기보를 저장하고 게임을 불러와 기보대로 이동시키는 방법
      • -
      -

      기물이 이동할 때마다 값을 저장하고 싶었고, 기보를 저장하는 방법을 선택했다.
      -기물 전체를 저장하지 않은 이유는 다음과 같다.

      -
        -
      • 턴과 같은 부가적인 요소를 저장해야 한다.
      • -
      • 이동을 할 때 기물이 잡히는 경우 update 쿼리(이동 기물)와 delete(잡힌 기물) 2개의 쿼리를 날려야 한다.
      • -
      • 현재 구조에서 도메인의 변경이 크게(초기 상태를 구성하는 부분) 일어나야 한다.
      • -
      -

      정리하자면 기물 전체 저장과 기보 저장은 다음과 차이가 있다.
      -보드저장: 초기상태에서 32개의 Insert 쿼리(기물의 위치) + 기물 이동 시 움직임 변경(잡히는 경우 2개의 쿼리)
      -기보저장: 초기상태 애플리케이션에서 구성 + 저장된 기보를 select 쿼리로 조회해서 사용(1회) + insert 쿼리(이동 당 1회)

      -

      추가로 기보저장이 구현도 더욱 간단하다. 👍

      -

      부가적인 부분

      -

      리뷰어인 찰리🍫가 동시에 여러 게임이 진행된다면 어떨지? 에 대한 코멘트를 남겨주셔서 다양한 시도를 해봤다.

      -
        -
      • 누누의 도움으로 ConnectionPool 구현
      • -
      • ThreadLocal 사용해서 쓰레드 별 세션 관리
      • -
      • 실제로 애플리케이션 내에서 체스 게임이 진행되는 Board를 ConcurrentHashMap으로 저장(사실 이 부분은 현재 구조에서 필요없지만 2명이 서로 게임하는 경우를 생각해서 넣어보았다.)
      • -
      -

      두 명이 서로 같은 방에 입장하여 게임을 진행한다면 출력하는 부분이 까다로워질 것 같다고 예상되어(Board에 옵저버 패턴을 사용해야되나?) 해볼 엄두가 나지 않았다.

      -

      부족했던 부분

      -

      꼼꼼하게 코드를 작성하지 못한 부분
      -DB 관련 부분을 꼼꼼하게 코딩을 하지 못했다.
      -도메인 로직에만 집중하다보니 정적 중요한 DB의 코드의 예외처리, 빈 값을 반환 하는 부분을 꼼꼼하게 처리하지 못했다.
      -하지만 찰리의 꼼꼼한 리뷰로 DB부분과 나만의 JdbcTemplate을 깔끔하게 구현할 수 있었다.

      -

      시간에 대한 부담감
      -초반에는 여유롭지만 제출 마감에 가까워질 수록 사람이 급해지는 것 같다.
      -다음 페어프로그래밍할 땐 속도를 조절하고, 마음에 여유를 가져야겠다.

      -

      새로 학습한 부분

      -

      DAO 중복 제거

      -

      프롤로그에 을 작성했다.
      -DAO를 작성하는데 try-catch-resources와 여러 코드가 중복되서 제거하고싶었다.
      -템플릿 콜백 패턴으로 깔끔하게 중복을 제거할 수 있었다.👍

      -

      페어에게 배울 부분

      -

      페어 생각하기
      -가비는 누구보다 페어를 생각하고, 배려해주는 페어였다.
      -중간 중간 당 떨어질까봐 걱정도 해주고, 나의 컨디션도 확인해줬다!

      -

      미션 몰입하기
      -최근에 미션에 잘 몰입하지 못했다.
      -가비는 페어를 진행할 때 미션에 대한 몰입도가 매우 좋았다.
      -집에가서도 체스 이동에 대한 로직을 어떻게 구현할 지 생각한 뒤 꼼꼼해서 정리해서 나에게 보내주었다.
      -덕분에 나도 가비의 생각을 알 수 있어서 미션을 진행하는데 가속도가 붙은 것 같다.
      -또한 미션을 잘 마무리하고 싶은 마음이 전달되서 그런지 나도 덩달아 열심히 미션을 할 수 있었다.😄

      -

      솔직함
      -먼저 회고하자고 말 걸어줘서 정말 고마웠다고 표현해주는 부분
      -모르는게 있으면 솔직하게 말해주는 부분
      -나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
      -솔직함은 페어할 때 중요한 부분인 것 같다.

      -

      마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      회고

      +

      지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
      +레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
      +부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
      +내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

      +

      아쉬운 점

      +

      문서화

      +

      개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
      +프로젝트를 진행하면서 내가 한 부분을 조금 더 꼼꼼하게, 이해하기 쉽게 문서화를 했더라면 팀원들에게 더욱 도움이 되었을 텐데 이 부분에 시간을 조금 더 투자하지 못했던 부분에서 아쉬움이 많이 들었다.
      +방학 기간 동안 문서화를 하지 못했던 부분을 개인 블로그 올리면서 조금 더 채워보려고 한다.

      +

      내가 못하는 부분이라면 시간을 들이자

      +

      잘 못하는 부분이라면 시간을 들여서라도 중간은 가도록 해야겠다는 생각이 많이 들었다.
      +말을 하기 전에 정리해서 의견을 내는 것, 발표 준비, 감정 조절 등등 +못하는 부분을 인지하고, 개선하자.

      +

      컴포트 존 벗어나기

      +

      조금 더 도전적으로 목표를 잡았으면 좋았을 것 같다.
      +매번 근거를 가지고 기술을 도입하고, 코드를 작성하려고 노력했다.
      +하지만 지속적으로 개선하려고 하는 부분이 다소 부족했다.

      +

      좋았던 점

      +

      좋았던 점도 문서화

      +

      팀 블로그도 먼저 도입하자고 제안하고, 내가 했던 부분은 문서화를 꽤 많이 해서 팀원들과 공유할 수 있었다.
      +백엔드 크루 4명이서 같이 한 부분에 대해서는 기능 구현한다고 문서화가 조금 미흡해서 보충을 해야겠다.

      +

      내가 디자인한 트립드로우 로고

      + +

      트립드로우 로고를 만들었다.
      +팀원들이 대표 색상(파란색)을 정해줬고, 주말 동안 신나게 로고 디자인을 했던 것 같다.
      +아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

      +

      기술 선택의 이유

      +

      기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
      +100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

      +

      마치며

      +

      플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
      +안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

      \ No newline at end of file diff --git a/tags/retrospective/page/17.html b/tags/retrospective/page/17.html index c262b3602..2454b29a4 100644 --- a/tags/retrospective/page/17.html +++ b/tags/retrospective/page/17.html @@ -13,59 +13,209 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      1단계: https://github.com/woowacourse/java-blackjack/pull/427
      -2단계: https://github.com/woowacourse/java-blackjack/pull/537

      -

      블랙잭

      -

      블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
      -이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

      -

      블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
      -후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

      -

      미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
      -"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

      -

      곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
      -중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
      -부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

      -

      이 부분에 대해 생각이 많아져서 전 리뷰어인 터틀🐢과도 대화를 나누었다.
      -터틀은 제어할 수 없는 부분보다 제어할 수 있는 부분(궁극적인 목표인 좋은 코드를 작성하는 것)에 집중해보라고 하셨다.

      -

      좋은 코드, 좋은 페어에 대한 부분을 일단 지속적으로 생각해봐야겠다.

      -

      부족했던 부분

      -

      페어 신경쓰기
      -이번 페어할 때 적극적으로 의견을 내보도록 했다. 그렇기에 너무 의견을 강하게 밀어붙인 느낌이 들어서 미안했다.
      -후추가 압박을 느꼈을 수도 있을 것 같다는 생각이 든다.
      -중간 중간 작은 회고를 진행해보는 것이 좋을까?

      -

      체력 관리
      -요즘 잘 못먹는 것 같다.
      -앞으로 살 날이 많은데 잘 챙겨먹고, 힘내야겠다.

      -

      중간 중간 돌아보기
      -이번 미션과 관련된 내용은 아니지만 우테코를 잘 활용 하고 있는지 생각을 해봐야겠다.
      -내가 우테코에 지원한 이유를 항상 잊지 않아야겠다.

      -

      새로 학습한 부분

      -

      상태 패턴
      -객체의 내부 상태에 따라 스스로 행동을 변경하도록 하는 패턴으로 if/else/switch와 같은 조건문을 효과적으로 제거할 수 있다.
      -블랙잭 미션을 진행하면서 상태 패턴에 대한 부분을 처음 적용해보았다.
      -처음 적용하기 전에는 별로라고 생각했는데, 생각보다 괜찮은 것 같다.

      -

      일관성, 가독성, 추상화
      -이번 리뷰어는 검프🍫 였다!
      -검프의 리뷰는 간결함에 관련된 내용이 많았다.
      -일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
      -읽기 좋고, 간결한 방향으로 코드를 작성하는 방법을 배운 것 같다.
      -코드를 바라보는 시점이 하나 늘어난 기분이다!(앞으로 적용하는 것은 나의 몫이지만)

      -

      페어에게 배울 부분

      -

      생각 정리
      -중간 중간 현재 상황에 대해 그림을 그리거나, 글을 적으면서 정리한다.
      -페어와 동일한 부분을 이해하고 있는지 확인한다.
      -진행하는데 매우 도움이 되었던 것 같다.
      -나도 다음 페어때부터 펜이랑 종이를 준비해야겠다.

      -

      가감없이 의견을 말해주는 부분
      -진행 상황에 대한 부분, 진행 속도, 지금 자신이 이해하고 있는 부분을 말해줘서 편했다.
      -회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

      -

      도메인 언어에 신경쓰는 부분
      -클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
      -요구사항 정리도 깔끔하게 잘하는 것 같다.

      -

      후추 최고 👍

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 13분

      1, 2단계: https://github.com/woowacourse/jwp-dashboard-http/pull/302
      +3, 4단계: https://github.com/woowacourse/jwp-dashboard-http/pull/431

      +

      톰캣 구현

      +

      우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
      +그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

      +

      이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
      +톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

      +

      다이어그램

      +

      Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
      +사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
      +또한 적절하게 인터페이스를 사용하여 의존성 방향을 단방향으로 하려고 노력했다.

      + +

      코드 리뷰

      +

      크루 중 한 명이 나의 리뷰어가 되고, 내가 다른 크루의 리뷰어가 되는 형태로 진행이 되었다.
      +나의 리뷰어는 디노, 리뷰이는 필립이었다.

      +

      디노(매의 눈이 아닌 공룡의 눈?)가 매우 꼼꼼하게 코드 리뷰를 해주어서 조금 더 나은 코드를 작성할 수 있었고, 필립의 코드에서는 꼼꼼하게 예외처리 하는 부분을 배울 수 있었다.
      +한 가지 아쉬운 점은 필립에게 작성한 나의 코멘트들이 미션을 진행하면서 경험 기반으로 작성한 내용이 많아 근거가 조금 부족했고, 정리되지 않은 부분이 많았던 것 같다.
      +다음 미션부터 리뷰할 때 조금 더 시간을 투자해서 더 좋은 내용을 크루들과 공유할 수 있도록 노력해야겠다.

      +

      SessionConfig

      +

      미션을 진행 중 catalina 패키지의 Session 관련 부분을 보면서 중복 로직을 개선해 볼 수 있을 것 같아 컨트리뷰트를 시도했다.
      +세션 쿠키의 이름을 가져오는 Util 클래스의 코드를 수정했는데 기본 값은 JSESSIONID 지만 설정에 따라서 세션 쿠키명을 다르게 사용할 수 있기 때문에 해당 로직이 있는 것으로 생각했다.
      +기존의 코드는 명시된 주석의 내용과 코드의 흐름이 일치하지 않아서 약간 이해하기 어려웠다.

      +

      초기에 요청했던 PR은 기존의 코드보다 전체적으로 비교 연산을 한 번 줄일 수 있었고, context가 null인 경우 바로 기본 값을 반환함으로써 성능 개선의 효과가 있을 거라고 생각했다.
      +메인테이너인 Mark Thomas 형이 해당 로직의 경우 컴파일러가 해당 부분을 최적화 할 수 있을 거라고 기대한다고 했고, 가독성을 개선시켜보라고 조언해주셨다.
      +컴파일러 최적화는 고려해보지 못한 부분인데, 앞으로 학습해야 할 부분이 산더미라고 생각했다.

      +

      남겨준 코멘트에 따라 최종적으로는 중복된 코드를 줄이는 방향으로 코드를 수정했다.
      +결과적으로 기존 로직 대비 비교 연산을 한 번 줄일 수 있었고, 명시된 주석의 내용과 유사한 흐름의 코드를 작성하여 좋은 방향으로 리팩터링을 했다고 생각한다.

      + + +
      public static String getSessionCookieName(Context context) {
      +
      +    String result = getConfiguredSessionCookieName(context);
      +
      +    if (result == null) {
      +        result = DEFAULT_SESSION_COOKIE_NAME;
      +    }
      +
      +    return result;
      +}
      +
      +public static String getSessionUriParamName(Context context) {
      +
      +    String result = getConfiguredSessionCookieName(context);
      +
      +    if (result == null) {
      +        result = DEFAULT_SESSION_PARAMETER_NAME;
      +    }
      +
      +    return result;
      +}
      +
      +private static String getConfiguredSessionCookieName(Context context) {
      +
      +    // Priority is:
      +    // 1. Cookie name defined in context
      +    // 2. Cookie name configured for app
      +    // 3. Default defined by spec
      +    if (context != null) {
      +        String cookieName = context.getSessionCookieName();
      +        if (cookieName != null && cookieName.length() > 0) {
      +            return cookieName;
      +        }
      +
      +        SessionCookieConfig scc =
      +            context.getServletContext().getSessionCookieConfig();
      +        cookieName = scc.getName();
      +        if (cookieName != null && cookieName.length() > 0) {
      +            return cookieName;
      +        }
      +    }
      +
      +    return null;
      +}
      +
      +

      HTTP 수업

      +

      미션 중간에 진행되었던 HTTP 수업에는 HTTP를 적절하게 활용하는 부분에 대해 학습했다.
      +항상 성능 개선을 위해 애플리케이션 단에서 최적화해보려고 노력을 했지만, 더 적은 시간을 투자해서 효율적으로 성능을 개선할 수 있는 방법에 대해 알 수 있었던 수업이었다.
      +HTTP 압축, HTTP 캐싱, 리소스 최적화 기법에 대해 학습했다.

      +

      스프링 부트에서는 다음 옵션을 설정하여 http의 송수신의 압축을 진행할 수 있다.

      +
      server:
      +  compression:
      +    enabled: true
      +
      +

      수업 중 해당 압축 성능이 좋다면 왜 스프링 부트에서는 기본 값으로 설정을 하지 않았는지 궁금해졌다.
      +궁금증을 해소하지 못했는데 말랑이 잡담 채널에 다음과 같은 issue를 찾아주었다.
      +내용을 요약해 보자면 WAS 별로 압축을 하기 위해 설정해야 하는 것이 다르고, 무조건 압축을 하는 것이 최적의 경우가 아닐 수 있기 때문에 기본값으로 설정하지 않는 것 같다.

      +
      +

      If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.

      +
      +

      Phil Webb 형님의 말에 따르면 일반적인 애플리케이션을 개발하는 경우 gzip 압축을 사용하는 것이 좋지만, MSA 환경 + 데이터 센터에서 사용하는 경우 오직 다른 MSA 애플리케이션과 통신하고, 고성능 네트워크가 있기 때문에 CPU 부하를 줄이는 것이 우선시 될 수도 있다는 것이었다.

      +

      이외에도 의도하지 않은 캐싱을 막기 위해 휴리스틱 캐싱을 제거하거나, 개인 정보 유출을 막기 위해 응답 헤더에 private을 설정, ETag도 학습했다.

      +

      ETag HTTP 응답 헤더는 특정 버전의 리소스를 식별하는 식별자다.
      +웹 서버가 내용을 확인하고 변하지 않았으면, 웹 서버로 full 요청을 보내지 않기 때문에, 캐시가 더 효율적이게 된다.
      +MDN

      +

      Thread 수업

      +

      스레드에 대한 수업을 들었지만, 복잡한 내용도 워낙 많았기 때문에 설명하라고 하면 잘 못할 것 같은 느낌이 든다.
      +현재 프로젝트, 미션, 테코톡 준비를 병행해야 해서 세부적인 내용은 시간 날 때 복습하려고 한다.

      +

      스레드를 이해하고, WAS에 스레드 설정 관련한 실습이 있었는데 테오와 같이 1시간 정도 페어로 Thread 실습을 진행해 보았다.
      +학습한 내용은 다음과 같다.

      +

      threads.max: Tomcat의 최대 스레드 개수
      +max-connections: Tomcat이 유지할 수 있는 최대 커넥션 개수
      +accept-count: 최대 연결 수에 도달했을 때 연결 요청에 대해 운영 체제에서 제공하는 대기열의 최대 길이. 해당 Queue에 요청이 쌓이는 것은 Tomcat이 더 이상 요청을 받을 수 없다는 뜻이다. accpet-count queue에도 요청이 가득차면 그 이후에 오는 요청은 거부된다.

      + +

      마치며

      +

      시간은 너무 빠르게 가고 할 일은 많은 것 같다.
      +우선순위를 잘 정하고 학습을 진행해야겠다.
      +현재 데이터 다루는 부분(DB)에 대한 학습이 많이 부족한 것 같다. 해당 부분은 테코톡이 끝나는대로 채워야겠다.

      +

      참고 자료

      +

      RFC 2616
      +ETag, mdn
      +Apache Tomcat 8 Configuration Reference
      +Apache Tomcat Tuning, Terry Cho
      +maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

      \ No newline at end of file diff --git a/tags/retrospective/page/18.html b/tags/retrospective/page/18.html index 8782c1e02..8a048861b 100644 --- a/tags/retrospective/page/18.html +++ b/tags/retrospective/page/18.html @@ -13,149 +13,95 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 11분

      1단계: https://github.com/woowacourse/java-ladder/pull/97
      -2단계: https://github.com/woowacourse/java-ladder/pull/234

      -

      사다리 타기

      -

      사다리 타기 미션에서는 우가와 페어가 매칭되었다.
      -이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

      -

      우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

      -

      2단계에서는 2가지 방법으로 구현해봤다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
      +2단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465
      +3단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580

      +

      MVC 구현

      +

      Reflection을 이용하여 Spring MVC와 유사한 기능을 구현하는 미션이었다.
      +미션의 목표는 다음과 같았다.

      +
        +
      • MVC 프레임워크를 구현하면서 내부 동작 원리를 학습한다.
      • +
      • 점진적인 리팩토링을 경험한다.
      • +
      +

      미션의 목표와 더불어 각 클래스들이 역할과 책임을 적절히 가지도록 하고, 패키지의 의존 방향을 고민하면서 미션을 진행하는 것에 중점을 두었다.

      +

      애너테이션 기반 프레임워크 만들기

      +

      기존 코드에 ManualHandlerMapping이라는 서블릿을 직접 등록해서 사용하는 HandlerMapping 클래스가 있었고, 1단계에서는 애너테이션 기반의 AnnotationHandlerMapping을 구현해야 했기 때문에 @Controller, @RequestMapping을 Reflection을 이용하여 스캔하고, 핸들러 매핑을 등록하는 부분까지 진행해야 했다.
      +테오가 @GetMapping이나 @PostMapping 부분도 진행하면 재밌을 것 같다고 해서 같이 진행해 보았다.
      +추가로 미션 요구사항은 아니었지만 클래스 레벨에 적용된 @RequestMapping도 동작하도록 구현해보았다.

      + +

      다음과 같은 Flow로 Handler(실제 요청을 처리하는 메서드) 등록을 진행한다.

        -
      1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
      2. -
      3. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법
      4. +
      5. @Controller가 적용된 클래스의 정보를 스캔하여 반환한다.
      6. +
      7. @Controller가 적용된 클래스의 @RequestMapping이 적용된 메서드들의 정보를 반환한다.
      8. +
      9. 각 메서드들을 순회하며 HandlerKey(uri + httpMethod 정보)와 HandlerExecution(인스턴스 + 실행하려는 메서드)을 생성하여 Map<HandlerKey, HandlerExecution>에 추가한다.
      -

      Position 기준으로 사다리 게임을 진행하는 방법

      -

      사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
      -구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
      -또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

      - -
      public LadderGameResult play() {
      -    final Map<Player, Item> result = new LinkedHashMap<>();
      -    // 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
      -    for (Position position : Position.range(players.count())) {
      -        final Position resultPosition = ladder.play(position);
      -        result.put(players.get(position), items.get(resultPosition));
      +

      AnnotationHandlerMapping의 initialize 메서드에서 Handler를 등록한다. 코드는 다음과 같다.

      +
      public void initialize() {
      +    if (!initialized.compareAndSet(false, true)) {
      +        return;
           }
      -    return new LadderGameResult(result);
      -}
      -
      -

      Player에게 Ladder를 전달하여 게임을 진행하는 방법

      -

      Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
      -이 방법이 사다리 게임을 위해서 객체들이 긴밀하게 협력하고, 조금 더 책임의 분배가 잘 되어있다고 생각이 되었다.

      - -
      public LadderGameResult play() {
      -    // 참가자들에게 사다리를 전달해서 사다리에게 메시지를 보내도록 한다.
      -    final Map<Player, Position> playResult = players.play(ladder);
      -
      -    final Map<Player, Item> result = new LinkedHashMap<>();
      -    for (Player player : playResult.keySet()) {
      -        result.put(player, toItem(playResult.get(player)));
      +    final Map<Class<?>, ControllerInstance> controllers = annotationScanner.scanControllers();
      +    final Set<Method> methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());
      +    for (final Method method : methods) {
      +        final ControllerInstance controller = controllers.get(method.getDeclaringClass());
      +        final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);
      +        final List<HandlerKey> handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);
      +        handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));
           }
      -    return new LadderGameResult(result);
      +
      +    log.info("Initialized AnnotationHandlerMapping!");
      +    handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));
       }
       
      -

      부족했던 부분

      -

      유비쿼터스 언어에 시간을 들이기
      -유비쿼터스 언어를 정하는데 시간을 조금 더 들여야겠다고 생각했다.
      -사다리 타기의 실행 결과를 Item으로 짓다니.. 뭔가 만족스럽지 않다.
      -이전 미션과 마찬가지로, 명명하는 부분에서 부족함을 많이 느꼈다.

      -

      페어와 조금 더 친해지기
      -첫날은 페어와 친해지는 시간을 조금 더 가져야겠다고 생각했다.
      -우가랑 회고할 때 내가 시작하자마자 컨벤션 정하자고 해서 많이 당황스러웠다고 한다. 우가 미안.. 🥲

      -

      README를 조금 더 꼼꼼하게
      -이상하게 코딩에 집중하면 README를 업데이트하면서 같이 커밋 하는 걸 항상 까먹는다.
      -다음 미션에는 조금 더 신경 써야겠다.

      -

      좋은 질문을 생각하기
      -첫 PR때 리뷰어에게 질문을 남기지 못했다.
      -리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

      -

      PR 후에도 꼼꼼하게 확인하기
      -분명 알고 있는 부분이지만, 놓친 부분이 많은 것 같았다.
      -PR 하기 전에도 계속 확인을 했지만, 아무래도 IntelliJ에서 보니 코드에 익숙해져서 그런지 변경해야 할 부분이 잘 안보였다.
      -github pr에서는 전체 변경사항을 확인할 수 있으니 PR 후에도 꼭 확인해야겠다.

      -

      적극적으로 나의 의견을 말하기
      -의견을 적극적으로 내는 부분에 대해서 페어의 의견이 괜찮다고 생각하면 수용 후 개선을 하는 방향으로 진행을 했었는데, 조금 더 개선할 수 있는 방향이 있다면 나도 적극적으로 의견을 말해야겠다고 생각이 든다.
      -나도 설득하는 힘을 기르고, 페어도 좋은 방향을 알 수 있고, 결과물도 좋은 방향으로 나오지 않을까? (고민 들어주신 리뷰어 터틀🐢 감사합니다.)

      -

      새로 학습한 부분

      -

      객체의 생성 책임
      -Players가 Position을 생성하고 Player의 생성자에 넣어주었다. 하지만 이 부분에 대해서 생성 책임에 관련된 코멘트가 달렸다. -시간을 가지고 생각해 보니 Position을 가지고 있는 건 Player기 때문에 생성 책임을 Player가 담당하는 것이 좋다고 생각되었다.

      -

      생성 책임에 관한 패턴으로 GRASP의 Creator 패턴이 있는데 다음의 요소를 최대한 만족하는 클래스에 생성 책임을 할당하는 것이 좋다.

      -
        -
      • B가 A 객체를 포함 또는 참조한다.
      • -
      • B가 A 객체를 기록한다.
      • -
      • B가 A를 긴밀하게 사용한다.
      • -
      • B가 A의 초깃값을 가지고 있다.
      • -
      -

      실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

      -

      패키지 분리 기준
      -패키지 분리에 대한 나만의 기준이 아직 명확하지 않아 질문이 들어와도 명확하게 답변을 하지 못했다.
      -마지막 제출 전에 도메인 패키지 내부를 분리해 봤는데, 기준이 명확하지 않았기 때문에 좋지 않은 선택이었던 것 같다. -현재 진행하는 미션의 애플리케이션 크기가 그렇게 크지 않으니, domain 패키지에서 세부 패키지로 분리하지 않아도 될 것 같다.

      -

      사용하는 쪽에서 생각하기 & 예측가능한 코드 작성하기
      -Position에서 다음 위치나 이전 위치를 반환하는 메서드를 허용 범위(019)가 벗어난다면, 의미 없는 값이 들어간 Position을 반환하도록 했다.
      -이건 Position을 사용하는 입장을 고려하지 못한 코딩이었는데, 사용하는 입장에서는 0
      19의 값이 보장되어 있다고 생각할 것이기 때문이다.
      -따라서 hasNext, hasPrevious라는 이전 값, 이후 값이 범위 내에 있는지 확인하는 메서드를 추가하고, 기존의 값을 가져오는 메서드는 범위가 벗어나면 예외를 던지는 방향으로 해결하였다.

      -

      페어에게 배울 부분

      -

      밝은 기운을 가지고 있고 다른 사람들과 친화력이 좋은 것 같았다.
      -이번에 페어 할 때 컨디션 관리를 제대로 못해서 많이 미안했다. 다음에는 최상의 컨디션으로 페어를 준비해 봐야겠다.
      -그리고 우가랑 페어를 하고 나서, 나도 다른 사람들과 더 잘 지내봐야겠다는 생각이 들어 조금 더 용기를 내 잡담 중이다!

      -

      의견을 적극적으로 내줘서 페어프로그래밍 진행이 잘 되었다.
      -또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
      -페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

      -

      항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
      -웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

      +

      Legacy MVC와 @MVC 통합

      +

      2단계는 Legacy MVC와 AnnotationHandlerMapping을 통합하는 부분이었다.
      +기존의 MVC와 애너테이션이 적용된 MVC 두 개를 같이 사용할 수 있어야 헀다.
      +대략적인 흐름은 다음과 같다.

      +
        +
      1. DispatcherServlet.service(request, response) 호출
      2. +
      3. HandlerMappings를 통해 입력받은 request에 해당하는 Handler 조회
      4. +
      5. HandlerAdapters를 통해 Handler를 실행시킬 수 있는 HandlerAdapter 조회
      6. +
      7. HandlerAdapter의.handle 메서드 실행
      8. +
      9. View의 render 호출
      10. +
      + +

      웹 애플리케이션 발전 과정

      +

      웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
      +간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.

      + +

      내용이 길어져서 다음 문서에 정리했다.

      +

      추상적인 개념 학습 방법

      +

      직관적이지 않은 추상적인 개념을 학습할 때는 개념의 구현을 참고하면 학습에 도움이 된다고 한다.

      +
      개념구현
      OOPJava
      WASTomcat, Jetty
      IoCSpring BeanFactory, Servlet Container, Framework
      DISpring BeanFactory
      +

      정리

      +

      지금까지 스프링의 DispatcherServlet의 동작을 이론적으로만 알고 있었는데, 실제로 구현해 보니 조금 더 이해가 잘 가는 것 같다.
      +이번 미션에서 나의 리뷰어는 루카, 리뷰이는 헤나였다.
      +매 단계마다 꼼꼼하게 리뷰해 준 루카에게 너무 감사하고, 헤나에게 이상한 리뷰를 많이 남긴 것 같은데 꼼꼼히 반영해줘서 감사하다.
      +오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

      \ No newline at end of file diff --git a/tags/retrospective/page/19.html b/tags/retrospective/page/19.html index a1abab685..10ba7ad32 100644 --- a/tags/retrospective/page/19.html +++ b/tags/retrospective/page/19.html @@ -13,89 +13,93 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 8분

      1단계: https://github.com/woowacourse/java-racingcar/pull/510
      -2단계: https://github.com/woowacourse/java-racingcar/pull/538

      -

      자동차 경주

      -

      자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
      -우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

      -

      첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
      -시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

      -

      시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
      -mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
      +2단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358
      +3단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448
      +4단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515

      +

      Jdbc 구현

      +

      이번 미션은 Jdbc 라이브러리를 구현하고, Transaction 경계 설정과 동기화하는 부분을 구현해 보는 미션이었다.
      +미션 목표는 다음과 같다.

        -
      • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
      • -
      • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.
      • +
      • JDBC 라이브러리를 구현하면서 중복을 제거하는 연습을 한다.
      • +
      • 데이터베이스에 대한 이해도를 높인다.
      - -

      미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

      -

      페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
      -리팩터링을 어떻게 했는지? 이런 리뷰에 대해 어떻게 생각하는지 깊게 고민하는 시간을 가질 수 있었다.

      -

      부족했던 부분

      -

      리팩터링이 끝난 후 메서드명, 테스트시 출력하는 메시지에 대한 코멘트가 많이 달렸다.
      -객체가 어떤 책임과 역할을 가지는지 생각하는 시간을 가지고 명확한 메서드명을 작성해야겠다고 생각했다.

      -

      평소에 프로그래밍 이야기가 아닌 다른 주제로 이야기하면 잘 들으려고 하는 편이지만
      -내가 좋아하는 주제, 관심가는 주제인 프로그래밍에 대한 이야기를 할 땐 말이 많아진다.
      -다음 미션부터는 더 많은 시간을 페어의 의견과 이야기를 듣는 곳에 사용해야겠다.

      -

      새로 학습한 부분

      -

      Assertions extracting

      -

      결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
      -이전에는 필요에 따라 stream을 이용하여 검증할 값을 생성했지만, 해당 방법을 이용해서 절차를 줄일 수 있었다.

      -
      @Test
      -void extracting() {
      -    final Cars cars = new Cars(List.of("car1", "car2"));
      +

      최대한 Java가 제공하는 기능을 사용하여 리팩터링 하는 방향으로 코드를 작성했다.

      +

      JdbcTemplate

      +

      JdbcTemplate은 Connection을 이용하여 PreparedStatement를 생성하는 부분, 그리고 PreparedStatement가 어떻게 동작하는지에 대한 부분을 분리했다.
      +템플릿 콜백 패턴을 적절하게 적용하여 중복을 비교적 간단하게 제거할 수 있었다.
      +예전에도 미션을 진행하면서 JdbcTemplate을 구현한 적이 있었는데, 이번에는 자원 할당과 해제 부분에 대한 중복도 제거했다.

      +
      public class JdbcTemplate {
       
      -    assertThat(cars.getCars())
      -            .extracting(Car::getName)
      -            .containsExactly("car1", "car2");
      +    private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);
      +
      +    private final DataSource dataSource;
      +    private final StatementCreator statementCreator;
      +    private final StatementExecutor statementExecutor;
      +
      +    public JdbcTemplate(final DataSource dataSource) {
      +        this(dataSource, new StatementCreator(), new StatementExecutor());
      +    }
      +
      +    JdbcTemplate(
      +            final DataSource dataSource,
      +            final StatementCreator statementCreator,
      +            final StatementExecutor statementExecutor
      +    ) {
      +        this.dataSource = dataSource;
      +        this.statementCreator = statementCreator;
      +        this.statementExecutor = statementExecutor;
      +    }
      +
      +    private <T> T query(
      +            final String sql,
      +            final PreparedStatementCallback<T> preparedStatementCallback,
      +            final Object... parameters
      +    ) {
      +        final Connection connection = DataSourceUtils.getConnection(dataSource);
      +        try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {
      +            return preparedStatementCallback.execute(preparedStatement);
      +        } catch (final SQLException e) {
      +            log.error(e.getMessage(), e);
      +            throw new DataAccessException(e);
      +        } finally {
      +            DataSourceUtils.releaseConnection(connection, dataSource);
      +        }
      +    }
      +
      +    public void update(final String sql, final Object... parameters) {
      +        query(sql, PreparedStatement::executeUpdate, parameters);
      +    }
      +
      +    public <T> Optional<T> queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
      +        final List<T> results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
      +        if (results.size() > 1) {
      +            throw new DataAccessException("2개 이상의 결과를 반환할 수 없습니다.");
      +        }
      +        return results.stream().findAny();
      +    }
      +
      +    public <T> List<T> queryForList(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
      +        return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
      +    }
       }
       
      -
      -

      아래는 리뷰어님과 대화를 나누면서 얻은 답변 + 나의 의견이다.

      -

      제어할 수 없는 부분에 대한 테스트

      -

      테스트 대상이 검증된 것이라면 작성하지 않거나, 제어할 수 있는 부분에 대한 테스트를 더욱 꼼꼼하게 작성한다.
      -이건 개인적인 생각이지만 내가 안정감이 들 수 있을 정도로 출력 범위 내의 결과를 반환하는지 정도 테스트할 수 있지 않을까?

      -

      단순 위임을 하는 메서드에 대한 테스트

      -

      위임이라는 것은 역할과 책임을 넘겨준다는 것이다.
      -호출 횟수를 검증하는 것보다 결과에 대한 테스트하는 것이 좋다.
      -단순히 위임만 하는 테스트의 경우 결과를 검증한다면 테스트가 중복되지 않을까 생각했었다.
      -따라서 중복된 테스트를 줄이기 위해 내부의 메서드를 호출하는지 검증하는 방법도 있다는 것을 알게 되었지만
      -안정적으로 결과를 테스트 하는 것이 더 좋은 방법인 것 같다.

      -

      테스트를 위한 getter 사용

      -

      테스트 용도로 도메인에 새로운 메서드가 생성되는 것은 좋지 못하다.
      -필요의 경우 생성해서 사용할 수 있지만, 기존에 있는 메서드들을 활용해보는 것이 더 좋은 방법이다.
      -이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

      -

      페어에게 배울 부분

      -

      질문이나 생각할 점이 있을 때 매우 깊게 고민하는 것 같았다.
      -생각을 정리한 후 자신의 의견을 명료하게 전달해주었다.
      -그렇기 때문에 지식을 효율적으로 습득한다.
      -난 생각을 잘 정리하지 않은 채로 내버려 둔 얕은 지식이 많은 것 같다. (이런 것도 아는 것이라고 할 수 있을까?)
      -앞으로 조금 더 머릿속에서 정리하고, 문제에 대해 깊게 고민하는 시간을 늘려야겠다.

      -

      개발에 열정을 가진 게 느껴진다.
      -나도 개발을 좋아하지만, 최근에는 의지가 약해졌었다.
      -열정이 가득한 사람을 만나니 나도 열정적인 사람이 되는 것 같다.

      -

      칭찬을 많이 해준다. 단순히 많이 해주는 것이 아니라, 진심을 담긴 칭찬을 해줬다.
      -칭찬은 고래도 춤추게 하던가?
      -그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

      -

      어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
      -이건 바로 배울 수 없지만.
      -나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

      +

      트랜잭션 적용

      +

      3, 4단계는 기존의 코드에 트랜잭션을 시작하고 끝나는 부분인 트랜잭션 경계를 설정하고 ThreadLocal을 이용하여 트랜잭션 동기화(Transaction synchronization)를 적용하는 미션이었다.
      +트랜잭션 동기화란 트랜잭션을 시작하기 위한 Connection 객체를 ThreadLocal과 같은 공간에 따로 저장 후, 필요할 때 저장된 Connection을 가져다 사용하는 방식이다.
      +아래와 같은 구조로 미션을 진행했는데, ThreadLocal에 Connection 객체가 아닌, Connection 객체와 Transaction이 진행 중인지 확인할 수 있는 flag를 가지고 있는 클래스를 저장해서 사용하도록 했다.

      + +

      마무리

      +

      Jdbc 미션을 진행하면서 AOP나 Transactional에 대한 학습 테스트도 진행하고, 약간 알찬 미션이었던 것 같다.
      +꼼꼼히 코드를 봐준 리뷰어 호이 그리고 연휴 동안 계속 티키타카 하면서 재밌게 리뷰한 민트에게 감사하다.
      +회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

      \ No newline at end of file diff --git a/tags/retrospective/page/2.html b/tags/retrospective/page/2.html index 0cf6eeba2..fb1b0c66c 100644 --- a/tags/retrospective/page/2.html +++ b/tags/retrospective/page/2.html @@ -13,93 +13,89 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
      -2단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358
      -3단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448
      -4단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515

      -

      Jdbc 구현

      -

      이번 미션은 Jdbc 라이브러리를 구현하고, Transaction 경계 설정과 동기화하는 부분을 구현해 보는 미션이었다.
      -미션 목표는 다음과 같다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 8분

      1단계: https://github.com/woowacourse/java-racingcar/pull/510
      +2단계: https://github.com/woowacourse/java-racingcar/pull/538

      +

      자동차 경주

      +

      자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
      +우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

      +

      첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
      +시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

      +

      시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
      +mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

        -
      • JDBC 라이브러리를 구현하면서 중복을 제거하는 연습을 한다.
      • -
      • 데이터베이스에 대한 이해도를 높인다.
      • +
      • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
      • +
      • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.
      -

      최대한 Java가 제공하는 기능을 사용하여 리팩터링 하는 방향으로 코드를 작성했다.

      -

      JdbcTemplate

      -

      JdbcTemplate은 Connection을 이용하여 PreparedStatement를 생성하는 부분, 그리고 PreparedStatement가 어떻게 동작하는지에 대한 부분을 분리했다.
      -템플릿 콜백 패턴을 적절하게 적용하여 중복을 비교적 간단하게 제거할 수 있었다.
      -예전에도 미션을 진행하면서 JdbcTemplate을 구현한 적이 있었는데, 이번에는 자원 할당과 해제 부분에 대한 중복도 제거했다.

      -
      public class JdbcTemplate {
      +
      +

      미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

      +

      페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
      +리팩터링을 어떻게 했는지? 이런 리뷰에 대해 어떻게 생각하는지 깊게 고민하는 시간을 가질 수 있었다.

      +

      부족했던 부분

      +

      리팩터링이 끝난 후 메서드명, 테스트시 출력하는 메시지에 대한 코멘트가 많이 달렸다.
      +객체가 어떤 책임과 역할을 가지는지 생각하는 시간을 가지고 명확한 메서드명을 작성해야겠다고 생각했다.

      +

      평소에 프로그래밍 이야기가 아닌 다른 주제로 이야기하면 잘 들으려고 하는 편이지만
      +내가 좋아하는 주제, 관심가는 주제인 프로그래밍에 대한 이야기를 할 땐 말이 많아진다.
      +다음 미션부터는 더 많은 시간을 페어의 의견과 이야기를 듣는 곳에 사용해야겠다.

      +

      새로 학습한 부분

      +

      Assertions extracting

      +

      결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
      +이전에는 필요에 따라 stream을 이용하여 검증할 값을 생성했지만, 해당 방법을 이용해서 절차를 줄일 수 있었다.

      +
      @Test
      +void extracting() {
      +    final Cars cars = new Cars(List.of("car1", "car2"));
       
      -    private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);
      -
      -    private final DataSource dataSource;
      -    private final StatementCreator statementCreator;
      -    private final StatementExecutor statementExecutor;
      -
      -    public JdbcTemplate(final DataSource dataSource) {
      -        this(dataSource, new StatementCreator(), new StatementExecutor());
      -    }
      -
      -    JdbcTemplate(
      -            final DataSource dataSource,
      -            final StatementCreator statementCreator,
      -            final StatementExecutor statementExecutor
      -    ) {
      -        this.dataSource = dataSource;
      -        this.statementCreator = statementCreator;
      -        this.statementExecutor = statementExecutor;
      -    }
      -
      -    private <T> T query(
      -            final String sql,
      -            final PreparedStatementCallback<T> preparedStatementCallback,
      -            final Object... parameters
      -    ) {
      -        final Connection connection = DataSourceUtils.getConnection(dataSource);
      -        try (final PreparedStatement preparedStatement = statementCreator.create(connection, sql, parameters)) {
      -            return preparedStatementCallback.execute(preparedStatement);
      -        } catch (final SQLException e) {
      -            log.error(e.getMessage(), e);
      -            throw new DataAccessException(e);
      -        } finally {
      -            DataSourceUtils.releaseConnection(connection, dataSource);
      -        }
      -    }
      -
      -    public void update(final String sql, final Object... parameters) {
      -        query(sql, PreparedStatement::executeUpdate, parameters);
      -    }
      -
      -    public <T> Optional<T> queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
      -        final List<T> results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
      -        if (results.size() > 1) {
      -            throw new DataAccessException("2개 이상의 결과를 반환할 수 없습니다.");
      -        }
      -        return results.stream().findAny();
      -    }
      -
      -    public <T> List<T> queryForList(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
      -        return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
      -    }
      +    assertThat(cars.getCars())
      +            .extracting(Car::getName)
      +            .containsExactly("car1", "car2");
       }
       
      -

      트랜잭션 적용

      -

      3, 4단계는 기존의 코드에 트랜잭션을 시작하고 끝나는 부분인 트랜잭션 경계를 설정하고 ThreadLocal을 이용하여 트랜잭션 동기화(Transaction synchronization)를 적용하는 미션이었다.
      -트랜잭션 동기화란 트랜잭션을 시작하기 위한 Connection 객체를 ThreadLocal과 같은 공간에 따로 저장 후, 필요할 때 저장된 Connection을 가져다 사용하는 방식이다.
      -아래와 같은 구조로 미션을 진행했는데, ThreadLocal에 Connection 객체가 아닌, Connection 객체와 Transaction이 진행 중인지 확인할 수 있는 flag를 가지고 있는 클래스를 저장해서 사용하도록 했다.

      - -

      마무리

      -

      Jdbc 미션을 진행하면서 AOP나 Transactional에 대한 학습 테스트도 진행하고, 약간 알찬 미션이었던 것 같다.
      -꼼꼼히 코드를 봐준 리뷰어 호이 그리고 연휴 동안 계속 티키타카 하면서 재밌게 리뷰한 민트에게 감사하다.
      -회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

      +
      +

      아래는 리뷰어님과 대화를 나누면서 얻은 답변 + 나의 의견이다.

      +

      제어할 수 없는 부분에 대한 테스트

      +

      테스트 대상이 검증된 것이라면 작성하지 않거나, 제어할 수 있는 부분에 대한 테스트를 더욱 꼼꼼하게 작성한다.
      +이건 개인적인 생각이지만 내가 안정감이 들 수 있을 정도로 출력 범위 내의 결과를 반환하는지 정도 테스트할 수 있지 않을까?

      +

      단순 위임을 하는 메서드에 대한 테스트

      +

      위임이라는 것은 역할과 책임을 넘겨준다는 것이다.
      +호출 횟수를 검증하는 것보다 결과에 대한 테스트하는 것이 좋다.
      +단순히 위임만 하는 테스트의 경우 결과를 검증한다면 테스트가 중복되지 않을까 생각했었다.
      +따라서 중복된 테스트를 줄이기 위해 내부의 메서드를 호출하는지 검증하는 방법도 있다는 것을 알게 되었지만
      +안정적으로 결과를 테스트 하는 것이 더 좋은 방법인 것 같다.

      +

      테스트를 위한 getter 사용

      +

      테스트 용도로 도메인에 새로운 메서드가 생성되는 것은 좋지 못하다.
      +필요의 경우 생성해서 사용할 수 있지만, 기존에 있는 메서드들을 활용해보는 것이 더 좋은 방법이다.
      +이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

      +

      페어에게 배울 부분

      +

      질문이나 생각할 점이 있을 때 매우 깊게 고민하는 것 같았다.
      +생각을 정리한 후 자신의 의견을 명료하게 전달해주었다.
      +그렇기 때문에 지식을 효율적으로 습득한다.
      +난 생각을 잘 정리하지 않은 채로 내버려 둔 얕은 지식이 많은 것 같다. (이런 것도 아는 것이라고 할 수 있을까?)
      +앞으로 조금 더 머릿속에서 정리하고, 문제에 대해 깊게 고민하는 시간을 늘려야겠다.

      +

      개발에 열정을 가진 게 느껴진다.
      +나도 개발을 좋아하지만, 최근에는 의지가 약해졌었다.
      +열정이 가득한 사람을 만나니 나도 열정적인 사람이 되는 것 같다.

      +

      칭찬을 많이 해준다. 단순히 많이 해주는 것이 아니라, 진심을 담긴 칭찬을 해줬다.
      +칭찬은 고래도 춤추게 하던가?
      +그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

      +

      어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
      +이건 바로 배울 수 없지만.
      +나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

      \ No newline at end of file diff --git a/tags/retrospective/page/20.html b/tags/retrospective/page/20.html index 653cced53..178f7ee99 100644 --- a/tags/retrospective/page/20.html +++ b/tags/retrospective/page/20.html @@ -13,37 +13,65 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      적당한 전환점, 2022년을 돌아보며

      -

      전역

      -

      약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
      -조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

      -

      조금 더 미래에 대한 생각을 해볼걸 그랬다.
      -전역을 했지만 뭐 하나 제대로 할 줄 아는 것도 없으니 넓은 바닷속에 덩그러니 놓아진 기분이 괜히 들었었다.
      -일찍 생각을 정리하여 방향을 잡지 못했기에 아쉬움이 많이 남았다.

      -

      자바

      -

      전역을 하고 진로를 고민하다 향로님의 자바 공화국 포스팅을 읽고 나서 자바 공부를 시작했다.
      -유명한 인프런의 김영한님의 스프링 강의도 있고, 좋은 자바 개발 서적이 많아서 독학하기로 결정했다.
      -하다 보니 자바와 스프링을 공부하면서 “왜 진작하지 않았지”라는 생각도 많이 들었다.
      -양질의 자료도 많았기 때문에, 예전에 노드로 개발했을 때 풀지 못했던 답답함을 많이 해소했던 것 같다.

      -

      23년에는 조금 더 깊게 자바를 공부해볼 생각이다.
      -언어를 하나 깊게 공부하는 건 많은 도움이 되는 것 같다.

      -

      스터디

      -

      김영한님의 강의를 거의 다 들었을 때쯤, 항상 강의에서 언급되는 토비의 스프링을 읽어보고 싶어졌고
      -혼자 공부하기에는 동기부여도 부족했기 때문에 스터디를 시작했다.
      -다른 사람에게 설명을 해야 했기 때문에 더욱 꼼꼼하게 공부를 할 수 있어서 좋았지만 나에게는 내용이 꽤나 어려워서 시간을 많이 소비했다.
      -같이 스터디하시는 분과 7개월 동안 스터디를 꾸준히 이어나가 총 3권의 책을 읽을 수 있었다.

      -

      우아한 테크코스

      -

      군 복무 중일 때 지원했다 떨어진 우아한 테크코스를 다시 지원했다.
      -이번 연도에 취업을 하는 게 목표였지만 내가 가지고 있는 특별한 무기가 없다는 걸 깨달았다.
      -적지 않은 시간을 투자해 준비를 했고, 감사하게도 이번에는 최종 합격을 했다.

      -

      난 사람들과 소통하고, 협업하는 능력이 부족하다고 생각을 많이 했다.
      -우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

      -

      2023년에는

      -

      마음의 여유가 없었던 2022년이었던 것 같다.
      -하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 9분

      1단계: https://github.com/woowacourse/jwp-refactoring/pull/465
      +2단계: https://github.com/woowacourse/jwp-refactoring/pull/547
      +3단계: https://github.com/woowacourse/jwp-refactoring/pull/610
      +4단계: https://github.com/woowacourse/jwp-refactoring/pull/721

      +

      리팩터링 미션

      +

      요구사항 작성 → 테스트를 통한 코드 보호 → 리팩터링 → 의존성 리팩터링 → 멀티모듈 순서로 미션을 진행했다.
      +미션에 온전히 집중하고 싶었지만, 프로젝트와 병행하면서 진행했기에 어느정도 타협보고 진행한 부분이 많아서 아쉬웠다.

      +

      1, 2단계

      +

      1단계는 요구사항을 작성하고, 테스트 코드를 작성하여 추후에 리팩터링 할 때 안정감 있게 진행할 수 있도록 준비하는 과정이었다. +요구사항을 작성할 때 제공된 용어 사전을 최대한 활용하면서 기존의 코드를 보면서 요구사항을 정리했다. +테스트는 시간 관계상 API, 서비스 둘 중 하나만 통합 테스트를 진행해야겠다는 생각이 들었다.

      +

      최종적으로 서비스 기준으로 통합 테스트를 작성했는데 약간 후회되는 결정이었던 것 같다.
      +리팩터링 과정에서 API 명세가 바뀌지 않아야 한다는 것을 기준을 잡고 이번 미션을 한다고 가정했을 때 API 기준으로 테스트를 작성하고, 리팩터링을 진행하는 것이 더 안정감 있다고 생각한다.

      +

      2단계는 작성된 테스트 기반으로 리팩터링 하는 미션이었다.
      +서비스에서 도메인을 직접 반환하는 구조였는데, 도메인에 JPA를 적용하면 기존 명세와 달라질 것을 우려해서 DTO로 수정하는 작업을 먼저 진행했다. +DTO 이후에 서비스에 있는 로직을 도메인으로 이동시키고, 최종적으로 JPA를 적용하는 순서로 리팩터링을 진행했다. +이 과정에서 의존성 방향이 양방향인 부분도 생겨났다.

      +

      소프트웨어의 복잡성을 다루는 지혜

      +

      중간에 소프트웨어 복잡성을 다루는 지혜에 관한 제이슨의 강의가 있었다.
      +소프트웨어의 복잡성을 다루는 지혜는 에릭 에반스의 저서 도메인 주도 설계의 부제이다.

      +

      도메인 주도 설계는 유비쿼터스 언어, 전략적 설계, 전술적 설계가 중요하다고 한다.
      +유비쿼터스 언어, 전략적 설계가 전체의 90%에 해당할 정도로 중요하다고 한다. 또한 전술적 설계만 하는 경우를 DDD Lite 라고 한다.

      +

      간단히 도메인 주도 설계에서 나오는 단어를 정리한다면 다음과 같다.

      +
      단어설명
      도메인소프트웨어로 해결하고자 하는 문제 영역
      바운디드 컨텍스트해결 영역, 관심사를 분리하고 격리하여 문제 해결에 집중할 범위
      유비쿼터스 언어프로젝트에 이해관계자들의 공통된 언어로, 서로의 의사소통 비용을 줄이기 위해 사용하는 언어
      전략적 설계도메인 전문가와 개발자가 함께 유비쿼터스 언어를 이용하여 도메인과 관련된 지식을 이해하고 이를 바탕으로 경계를 나눠 바운디드 컨텍스트를 정의하고, 컨텍스트 맵을 생성하는 것을 포함하는 과정
      전술적 설계전략적 설계에서 정의한 바운디드 컨텍스트와 도메인을 이용하여 애그리거트, Entity와 VO, Repository 등을 구현하는 과정
      +

      이 외에도 다양한 내용들이 나왔지만, 지식을 제대로 흡수하지는 못했다.

      +

      3, 4단계

      +

      제이슨의 강의를 듣고, 조영호님의 우아한객체지향 유튜브 영상을 본 다음 3, 4단계를 진행했다.

      +

      3단계는 의존성 리팩터링에 관한 내용이었다. 클래스 간 방향, 패키지 간 방향을 단방향이 되도록 리팩터링을 진행해야 했었다. +함께 생성되고 삭제되는 객체들을 묶고, 결합도를 낮추기 위해 생명주기가 다르다면 id를 이용하여 참조하도록 변경했다.

      +

      의존성을 분리하기 위해 이벤트도 사용해보았다. 이벤트는 현재 기준으로 과거에 벌어진 것을 표현하기 때문에 이벤트명은 과거 시제가 되어야하는 것을 알았다. +처음에는 애플리케이션 이벤트를 사용했지만, 서비스 로직을 최대한 간단하게 하기 위해 도메인 이벤트도 사용해보았다.

      +

      4단계는 멀티모듈로 분리하는 미션이었는데 3단계에서 분리해둔 패키지 그대로 분리하지는 않았다.
      +3단계에서는 함께 생성되고 삭제되는 객체 기준으로 분리했다. 4단계에서는 내가 인식하기 편한 기준으로 분리를 했다. +아직 분리한 기준에 대한 근거가 모호했고, 이에 대한 공부를 조금 더 해야겠다고 생각했다.

      + +

      추가로 테스트 격리를 위한 직접 작성한 @ServiceTest 커스텀 애너테이션이 있었는데, 상위 모듈의 테스트에서 만든 클래스를 하위 모듈에서는 사용할 수 없었다. +따라서 TestFixtures를 사용하여 해결했다.

      +

      마무리

      +

      우아한테크코스의 마지막 미션이니 만큼, 가장 흥미로운 미션이었고 배울점도 많았던 것 같다.
      +바쁜 기간이라 많은 리뷰를 남기지 못했던 리뷰이 호이에게 미안하고, 코멘트 꼼꼼하게 달아주고 미션에 대한 이야기도 오프라인으로 많이 나눈 리뷰어 테오에게 너무 감사하다.

      +

      참고 자료

      +

      도메인 원정대, 우아콘 2021
      +우아한객체지향, 우아한테크세미나
      +TestFixtures, 권남님

      \ No newline at end of file diff --git a/tags/retrospective/page/3.html b/tags/retrospective/page/3.html index 8e470742f..49a5a0840 100644 --- a/tags/retrospective/page/3.html +++ b/tags/retrospective/page/3.html @@ -13,95 +13,149 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
      -2단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465
      -3단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580

      -

      MVC 구현

      -

      Reflection을 이용하여 Spring MVC와 유사한 기능을 구현하는 미션이었다.
      -미션의 목표는 다음과 같았다.

      -
        -
      • MVC 프레임워크를 구현하면서 내부 동작 원리를 학습한다.
      • -
      • 점진적인 리팩토링을 경험한다.
      • -
      -

      미션의 목표와 더불어 각 클래스들이 역할과 책임을 적절히 가지도록 하고, 패키지의 의존 방향을 고민하면서 미션을 진행하는 것에 중점을 두었다.

      -

      애너테이션 기반 프레임워크 만들기

      -

      기존 코드에 ManualHandlerMapping이라는 서블릿을 직접 등록해서 사용하는 HandlerMapping 클래스가 있었고, 1단계에서는 애너테이션 기반의 AnnotationHandlerMapping을 구현해야 했기 때문에 @Controller, @RequestMapping을 Reflection을 이용하여 스캔하고, 핸들러 매핑을 등록하는 부분까지 진행해야 했다.
      -테오가 @GetMapping이나 @PostMapping 부분도 진행하면 재밌을 것 같다고 해서 같이 진행해 보았다.
      -추가로 미션 요구사항은 아니었지만 클래스 레벨에 적용된 @RequestMapping도 동작하도록 구현해보았다.

      - -

      다음과 같은 Flow로 Handler(실제 요청을 처리하는 메서드) 등록을 진행한다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 11분

      1단계: https://github.com/woowacourse/java-ladder/pull/97
      +2단계: https://github.com/woowacourse/java-ladder/pull/234

      +

      사다리 타기

      +

      사다리 타기 미션에서는 우가와 페어가 매칭되었다.
      +이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

      +

      우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

      +

      2단계에서는 2가지 방법으로 구현해봤다.

        -
      1. @Controller가 적용된 클래스의 정보를 스캔하여 반환한다.
      2. -
      3. @Controller가 적용된 클래스의 @RequestMapping이 적용된 메서드들의 정보를 반환한다.
      4. -
      5. 각 메서드들을 순회하며 HandlerKey(uri + httpMethod 정보)와 HandlerExecution(인스턴스 + 실행하려는 메서드)을 생성하여 Map<HandlerKey, HandlerExecution>에 추가한다.
      6. +
      7. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
      8. +
      9. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법
      -

      AnnotationHandlerMapping의 initialize 메서드에서 Handler를 등록한다. 코드는 다음과 같다.

      -
      public void initialize() {
      -    if (!initialized.compareAndSet(false, true)) {
      -        return;
      -    }
      +

      Position 기준으로 사다리 게임을 진행하는 방법

      +

      사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
      +구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
      +또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

      + +
      public LadderGameResult play() {
      +    final Map<Player, Item> result = new LinkedHashMap<>();
      +    // 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
      +    for (Position position : Position.range(players.count())) {
      +        final Position resultPosition = ladder.play(position);
      +        result.put(players.get(position), items.get(resultPosition));
           }
      +    return new LadderGameResult(result);
      +}
      +
      +

      Player에게 Ladder를 전달하여 게임을 진행하는 방법

      +

      Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
      +이 방법이 사다리 게임을 위해서 객체들이 긴밀하게 협력하고, 조금 더 책임의 분배가 잘 되어있다고 생각이 되었다.

      + +
      public LadderGameResult play() {
      +    // 참가자들에게 사다리를 전달해서 사다리에게 메시지를 보내도록 한다.
      +    final Map<Player, Position> playResult = players.play(ladder);
      +
      +    final Map<Player, Item> result = new LinkedHashMap<>();
      +    for (Player player : playResult.keySet()) {
      +        result.put(player, toItem(playResult.get(player)));
      +    }
      +    return new LadderGameResult(result);
       }
       
      -

      Legacy MVC와 @MVC 통합

      -

      2단계는 Legacy MVC와 AnnotationHandlerMapping을 통합하는 부분이었다.
      -기존의 MVC와 애너테이션이 적용된 MVC 두 개를 같이 사용할 수 있어야 헀다.
      -대략적인 흐름은 다음과 같다.

      -
        -
      1. DispatcherServlet.service(request, response) 호출
      2. -
      3. HandlerMappings를 통해 입력받은 request에 해당하는 Handler 조회
      4. -
      5. HandlerAdapters를 통해 Handler를 실행시킬 수 있는 HandlerAdapter 조회
      6. -
      7. HandlerAdapter의.handle 메서드 실행
      8. -
      9. View의 render 호출
      10. -
      - -

      웹 애플리케이션 발전 과정

      -

      웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
      -간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.

      - -

      내용이 길어져서 다음 문서에 정리했다.

      -

      추상적인 개념 학습 방법

      -

      직관적이지 않은 추상적인 개념을 학습할 때는 개념의 구현을 참고하면 학습에 도움이 된다고 한다.

      -
      개념구현
      OOPJava
      WASTomcat, Jetty
      IoCSpring BeanFactory, Servlet Container, Framework
      DISpring BeanFactory
      -

      정리

      -

      지금까지 스프링의 DispatcherServlet의 동작을 이론적으로만 알고 있었는데, 실제로 구현해 보니 조금 더 이해가 잘 가는 것 같다.
      -이번 미션에서 나의 리뷰어는 루카, 리뷰이는 헤나였다.
      -매 단계마다 꼼꼼하게 리뷰해 준 루카에게 너무 감사하고, 헤나에게 이상한 리뷰를 많이 남긴 것 같은데 꼼꼼히 반영해줘서 감사하다.
      -오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

      +

      부족했던 부분

      +

      유비쿼터스 언어에 시간을 들이기
      +유비쿼터스 언어를 정하는데 시간을 조금 더 들여야겠다고 생각했다.
      +사다리 타기의 실행 결과를 Item으로 짓다니.. 뭔가 만족스럽지 않다.
      +이전 미션과 마찬가지로, 명명하는 부분에서 부족함을 많이 느꼈다.

      +

      페어와 조금 더 친해지기
      +첫날은 페어와 친해지는 시간을 조금 더 가져야겠다고 생각했다.
      +우가랑 회고할 때 내가 시작하자마자 컨벤션 정하자고 해서 많이 당황스러웠다고 한다. 우가 미안.. 🥲

      +

      README를 조금 더 꼼꼼하게
      +이상하게 코딩에 집중하면 README를 업데이트하면서 같이 커밋 하는 걸 항상 까먹는다.
      +다음 미션에는 조금 더 신경 써야겠다.

      +

      좋은 질문을 생각하기
      +첫 PR때 리뷰어에게 질문을 남기지 못했다.
      +리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

      +

      PR 후에도 꼼꼼하게 확인하기
      +분명 알고 있는 부분이지만, 놓친 부분이 많은 것 같았다.
      +PR 하기 전에도 계속 확인을 했지만, 아무래도 IntelliJ에서 보니 코드에 익숙해져서 그런지 변경해야 할 부분이 잘 안보였다.
      +github pr에서는 전체 변경사항을 확인할 수 있으니 PR 후에도 꼭 확인해야겠다.

      +

      적극적으로 나의 의견을 말하기
      +의견을 적극적으로 내는 부분에 대해서 페어의 의견이 괜찮다고 생각하면 수용 후 개선을 하는 방향으로 진행을 했었는데, 조금 더 개선할 수 있는 방향이 있다면 나도 적극적으로 의견을 말해야겠다고 생각이 든다.
      +나도 설득하는 힘을 기르고, 페어도 좋은 방향을 알 수 있고, 결과물도 좋은 방향으로 나오지 않을까? (고민 들어주신 리뷰어 터틀🐢 감사합니다.)

      +

      새로 학습한 부분

      +

      객체의 생성 책임
      +Players가 Position을 생성하고 Player의 생성자에 넣어주었다. 하지만 이 부분에 대해서 생성 책임에 관련된 코멘트가 달렸다. +시간을 가지고 생각해 보니 Position을 가지고 있는 건 Player기 때문에 생성 책임을 Player가 담당하는 것이 좋다고 생각되었다.

      +

      생성 책임에 관한 패턴으로 GRASP의 Creator 패턴이 있는데 다음의 요소를 최대한 만족하는 클래스에 생성 책임을 할당하는 것이 좋다.

      +
        +
      • B가 A 객체를 포함 또는 참조한다.
      • +
      • B가 A 객체를 기록한다.
      • +
      • B가 A를 긴밀하게 사용한다.
      • +
      • B가 A의 초깃값을 가지고 있다.
      • +
      +

      실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

      +

      패키지 분리 기준
      +패키지 분리에 대한 나만의 기준이 아직 명확하지 않아 질문이 들어와도 명확하게 답변을 하지 못했다.
      +마지막 제출 전에 도메인 패키지 내부를 분리해 봤는데, 기준이 명확하지 않았기 때문에 좋지 않은 선택이었던 것 같다. +현재 진행하는 미션의 애플리케이션 크기가 그렇게 크지 않으니, domain 패키지에서 세부 패키지로 분리하지 않아도 될 것 같다.

      +

      사용하는 쪽에서 생각하기 & 예측가능한 코드 작성하기
      +Position에서 다음 위치나 이전 위치를 반환하는 메서드를 허용 범위(019)가 벗어난다면, 의미 없는 값이 들어간 Position을 반환하도록 했다.
      +이건 Position을 사용하는 입장을 고려하지 못한 코딩이었는데, 사용하는 입장에서는 0
      19의 값이 보장되어 있다고 생각할 것이기 때문이다.
      +따라서 hasNext, hasPrevious라는 이전 값, 이후 값이 범위 내에 있는지 확인하는 메서드를 추가하고, 기존의 값을 가져오는 메서드는 범위가 벗어나면 예외를 던지는 방향으로 해결하였다.

      +

      페어에게 배울 부분

      +

      밝은 기운을 가지고 있고 다른 사람들과 친화력이 좋은 것 같았다.
      +이번에 페어 할 때 컨디션 관리를 제대로 못해서 많이 미안했다. 다음에는 최상의 컨디션으로 페어를 준비해 봐야겠다.
      +그리고 우가랑 페어를 하고 나서, 나도 다른 사람들과 더 잘 지내봐야겠다는 생각이 들어 조금 더 용기를 내 잡담 중이다!

      +

      의견을 적극적으로 내줘서 페어프로그래밍 진행이 잘 되었다.
      +또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
      +페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

      +

      항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
      +웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

      \ No newline at end of file diff --git a/tags/retrospective/page/4.html b/tags/retrospective/page/4.html index 07d1821b5..b28fad52a 100644 --- a/tags/retrospective/page/4.html +++ b/tags/retrospective/page/4.html @@ -13,209 +13,59 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 13분

      1, 2단계: https://github.com/woowacourse/jwp-dashboard-http/pull/302
      -3, 4단계: https://github.com/woowacourse/jwp-dashboard-http/pull/431

      -

      톰캣 구현

      -

      우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
      -그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

      -

      이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
      -톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

      -

      다이어그램

      -

      Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
      -사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
      -또한 적절하게 인터페이스를 사용하여 의존성 방향을 단방향으로 하려고 노력했다.

      - -

      코드 리뷰

      -

      크루 중 한 명이 나의 리뷰어가 되고, 내가 다른 크루의 리뷰어가 되는 형태로 진행이 되었다.
      -나의 리뷰어는 디노, 리뷰이는 필립이었다.

      -

      디노(매의 눈이 아닌 공룡의 눈?)가 매우 꼼꼼하게 코드 리뷰를 해주어서 조금 더 나은 코드를 작성할 수 있었고, 필립의 코드에서는 꼼꼼하게 예외처리 하는 부분을 배울 수 있었다.
      -한 가지 아쉬운 점은 필립에게 작성한 나의 코멘트들이 미션을 진행하면서 경험 기반으로 작성한 내용이 많아 근거가 조금 부족했고, 정리되지 않은 부분이 많았던 것 같다.
      -다음 미션부터 리뷰할 때 조금 더 시간을 투자해서 더 좋은 내용을 크루들과 공유할 수 있도록 노력해야겠다.

      -

      SessionConfig

      -

      미션을 진행 중 catalina 패키지의 Session 관련 부분을 보면서 중복 로직을 개선해 볼 수 있을 것 같아 컨트리뷰트를 시도했다.
      -세션 쿠키의 이름을 가져오는 Util 클래스의 코드를 수정했는데 기본 값은 JSESSIONID 지만 설정에 따라서 세션 쿠키명을 다르게 사용할 수 있기 때문에 해당 로직이 있는 것으로 생각했다.
      -기존의 코드는 명시된 주석의 내용과 코드의 흐름이 일치하지 않아서 약간 이해하기 어려웠다.

      -

      초기에 요청했던 PR은 기존의 코드보다 전체적으로 비교 연산을 한 번 줄일 수 있었고, context가 null인 경우 바로 기본 값을 반환함으로써 성능 개선의 효과가 있을 거라고 생각했다.
      -메인테이너인 Mark Thomas 형이 해당 로직의 경우 컴파일러가 해당 부분을 최적화 할 수 있을 거라고 기대한다고 했고, 가독성을 개선시켜보라고 조언해주셨다.
      -컴파일러 최적화는 고려해보지 못한 부분인데, 앞으로 학습해야 할 부분이 산더미라고 생각했다.

      -

      남겨준 코멘트에 따라 최종적으로는 중복된 코드를 줄이는 방향으로 코드를 수정했다.
      -결과적으로 기존 로직 대비 비교 연산을 한 번 줄일 수 있었고, 명시된 주석의 내용과 유사한 흐름의 코드를 작성하여 좋은 방향으로 리팩터링을 했다고 생각한다.

      - - -
      public static String getSessionCookieName(Context context) {
      -
      -    String result = getConfiguredSessionCookieName(context);
      -
      -    if (result == null) {
      -        result = DEFAULT_SESSION_COOKIE_NAME;
      -    }
      -
      -    return result;
      -}
      -
      -public static String getSessionUriParamName(Context context) {
      -
      -    String result = getConfiguredSessionCookieName(context);
      -
      -    if (result == null) {
      -        result = DEFAULT_SESSION_PARAMETER_NAME;
      -    }
      -
      -    return result;
      -}
      -
      -private static String getConfiguredSessionCookieName(Context context) {
      -
      -    // Priority is:
      -    // 1. Cookie name defined in context
      -    // 2. Cookie name configured for app
      -    // 3. Default defined by spec
      -    if (context != null) {
      -        String cookieName = context.getSessionCookieName();
      -        if (cookieName != null && cookieName.length() > 0) {
      -            return cookieName;
      -        }
      -
      -        SessionCookieConfig scc =
      -            context.getServletContext().getSessionCookieConfig();
      -        cookieName = scc.getName();
      -        if (cookieName != null && cookieName.length() > 0) {
      -            return cookieName;
      -        }
      -    }
      -
      -    return null;
      -}
      -
      -

      HTTP 수업

      -

      미션 중간에 진행되었던 HTTP 수업에는 HTTP를 적절하게 활용하는 부분에 대해 학습했다.
      -항상 성능 개선을 위해 애플리케이션 단에서 최적화해보려고 노력을 했지만, 더 적은 시간을 투자해서 효율적으로 성능을 개선할 수 있는 방법에 대해 알 수 있었던 수업이었다.
      -HTTP 압축, HTTP 캐싱, 리소스 최적화 기법에 대해 학습했다.

      -

      스프링 부트에서는 다음 옵션을 설정하여 http의 송수신의 압축을 진행할 수 있다.

      -
      server:
      -  compression:
      -    enabled: true
      -
      -

      수업 중 해당 압축 성능이 좋다면 왜 스프링 부트에서는 기본 값으로 설정을 하지 않았는지 궁금해졌다.
      -궁금증을 해소하지 못했는데 말랑이 잡담 채널에 다음과 같은 issue를 찾아주었다.
      -내용을 요약해 보자면 WAS 별로 압축을 하기 위해 설정해야 하는 것이 다르고, 무조건 압축을 하는 것이 최적의 경우가 아닐 수 있기 때문에 기본값으로 설정하지 않는 것 같다.

      -
      -

      If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.

      -
      -

      Phil Webb 형님의 말에 따르면 일반적인 애플리케이션을 개발하는 경우 gzip 압축을 사용하는 것이 좋지만, MSA 환경 + 데이터 센터에서 사용하는 경우 오직 다른 MSA 애플리케이션과 통신하고, 고성능 네트워크가 있기 때문에 CPU 부하를 줄이는 것이 우선시 될 수도 있다는 것이었다.

      -

      이외에도 의도하지 않은 캐싱을 막기 위해 휴리스틱 캐싱을 제거하거나, 개인 정보 유출을 막기 위해 응답 헤더에 private을 설정, ETag도 학습했다.

      -

      ETag HTTP 응답 헤더는 특정 버전의 리소스를 식별하는 식별자다.
      -웹 서버가 내용을 확인하고 변하지 않았으면, 웹 서버로 full 요청을 보내지 않기 때문에, 캐시가 더 효율적이게 된다.
      -MDN

      -

      Thread 수업

      -

      스레드에 대한 수업을 들었지만, 복잡한 내용도 워낙 많았기 때문에 설명하라고 하면 잘 못할 것 같은 느낌이 든다.
      -현재 프로젝트, 미션, 테코톡 준비를 병행해야 해서 세부적인 내용은 시간 날 때 복습하려고 한다.

      -

      스레드를 이해하고, WAS에 스레드 설정 관련한 실습이 있었는데 테오와 같이 1시간 정도 페어로 Thread 실습을 진행해 보았다.
      -학습한 내용은 다음과 같다.

      -

      threads.max: Tomcat의 최대 스레드 개수
      -max-connections: Tomcat이 유지할 수 있는 최대 커넥션 개수
      -accept-count: 최대 연결 수에 도달했을 때 연결 요청에 대해 운영 체제에서 제공하는 대기열의 최대 길이. 해당 Queue에 요청이 쌓이는 것은 Tomcat이 더 이상 요청을 받을 수 없다는 뜻이다. accpet-count queue에도 요청이 가득차면 그 이후에 오는 요청은 거부된다.

      - -

      마치며

      -

      시간은 너무 빠르게 가고 할 일은 많은 것 같다.
      -우선순위를 잘 정하고 학습을 진행해야겠다.
      -현재 데이터 다루는 부분(DB)에 대한 학습이 많이 부족한 것 같다. 해당 부분은 테코톡이 끝나는대로 채워야겠다.

      -

      참고 자료

      -

      RFC 2616
      -ETag, mdn
      -Apache Tomcat 8 Configuration Reference
      -Apache Tomcat Tuning, Terry Cho
      -maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      1단계: https://github.com/woowacourse/java-blackjack/pull/427
      +2단계: https://github.com/woowacourse/java-blackjack/pull/537

      +

      블랙잭

      +

      블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
      +이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

      +

      블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
      +후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

      +

      미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
      +"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

      +

      곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
      +중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
      +부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

      +

      이 부분에 대해 생각이 많아져서 전 리뷰어인 터틀🐢과도 대화를 나누었다.
      +터틀은 제어할 수 없는 부분보다 제어할 수 있는 부분(궁극적인 목표인 좋은 코드를 작성하는 것)에 집중해보라고 하셨다.

      +

      좋은 코드, 좋은 페어에 대한 부분을 일단 지속적으로 생각해봐야겠다.

      +

      부족했던 부분

      +

      페어 신경쓰기
      +이번 페어할 때 적극적으로 의견을 내보도록 했다. 그렇기에 너무 의견을 강하게 밀어붙인 느낌이 들어서 미안했다.
      +후추가 압박을 느꼈을 수도 있을 것 같다는 생각이 든다.
      +중간 중간 작은 회고를 진행해보는 것이 좋을까?

      +

      체력 관리
      +요즘 잘 못먹는 것 같다.
      +앞으로 살 날이 많은데 잘 챙겨먹고, 힘내야겠다.

      +

      중간 중간 돌아보기
      +이번 미션과 관련된 내용은 아니지만 우테코를 잘 활용 하고 있는지 생각을 해봐야겠다.
      +내가 우테코에 지원한 이유를 항상 잊지 않아야겠다.

      +

      새로 학습한 부분

      +

      상태 패턴
      +객체의 내부 상태에 따라 스스로 행동을 변경하도록 하는 패턴으로 if/else/switch와 같은 조건문을 효과적으로 제거할 수 있다.
      +블랙잭 미션을 진행하면서 상태 패턴에 대한 부분을 처음 적용해보았다.
      +처음 적용하기 전에는 별로라고 생각했는데, 생각보다 괜찮은 것 같다.

      +

      일관성, 가독성, 추상화
      +이번 리뷰어는 검프🍫 였다!
      +검프의 리뷰는 간결함에 관련된 내용이 많았다.
      +일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
      +읽기 좋고, 간결한 방향으로 코드를 작성하는 방법을 배운 것 같다.
      +코드를 바라보는 시점이 하나 늘어난 기분이다!(앞으로 적용하는 것은 나의 몫이지만)

      +

      페어에게 배울 부분

      +

      생각 정리
      +중간 중간 현재 상황에 대해 그림을 그리거나, 글을 적으면서 정리한다.
      +페어와 동일한 부분을 이해하고 있는지 확인한다.
      +진행하는데 매우 도움이 되었던 것 같다.
      +나도 다음 페어때부터 펜이랑 종이를 준비해야겠다.

      +

      가감없이 의견을 말해주는 부분
      +진행 상황에 대한 부분, 진행 속도, 지금 자신이 이해하고 있는 부분을 말해줘서 편했다.
      +회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

      +

      도메인 언어에 신경쓰는 부분
      +클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
      +요구사항 정리도 깔끔하게 잘하는 것 같다.

      +

      후추 최고 👍

      \ No newline at end of file diff --git a/tags/retrospective/page/5.html b/tags/retrospective/page/5.html index 598ab0fb9..b60077204 100644 --- a/tags/retrospective/page/5.html +++ b/tags/retrospective/page/5.html @@ -13,42 +13,83 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      회고

      -

      지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
      -레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
      -부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
      -내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

      -

      아쉬운 점

      -

      문서화

      -

      개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
      -프로젝트를 진행하면서 내가 한 부분을 조금 더 꼼꼼하게, 이해하기 쉽게 문서화를 했더라면 팀원들에게 더욱 도움이 되었을 텐데 이 부분에 시간을 조금 더 투자하지 못했던 부분에서 아쉬움이 많이 들었다.
      -방학 기간 동안 문서화를 하지 못했던 부분을 개인 블로그 올리면서 조금 더 채워보려고 한다.

      -

      내가 못하는 부분이라면 시간을 들이자

      -

      잘 못하는 부분이라면 시간을 들여서라도 중간은 가도록 해야겠다는 생각이 많이 들었다.
      -말을 하기 전에 정리해서 의견을 내는 것, 발표 준비, 감정 조절 등등 -못하는 부분을 인지하고, 개선하자.

      -

      컴포트 존 벗어나기

      -

      조금 더 도전적으로 목표를 잡았으면 좋았을 것 같다.
      -매번 근거를 가지고 기술을 도입하고, 코드를 작성하려고 노력했다.
      -하지만 지속적으로 개선하려고 하는 부분이 다소 부족했다.

      -

      좋았던 점

      -

      좋았던 점도 문서화

      -

      팀 블로그도 먼저 도입하자고 제안하고, 내가 했던 부분은 문서화를 꽤 많이 해서 팀원들과 공유할 수 있었다.
      -백엔드 크루 4명이서 같이 한 부분에 대해서는 기능 구현한다고 문서화가 조금 미흡해서 보충을 해야겠다.

      -

      내가 디자인한 트립드로우 로고

      - -

      트립드로우 로고를 만들었다.
      -팀원들이 대표 색상(파란색)을 정해줬고, 주말 동안 신나게 로고 디자인을 했던 것 같다.
      -아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

      -

      기술 선택의 이유

      -

      기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
      -100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

      -

      마치며

      -

      플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
      -안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 8분

      1, 2단계: https://github.com/woowacourse/java-chess/pull/441
      +3, 4단계: https://github.com/woowacourse/java-chess/pull/529

      +

      체스

      +

      체스 미션에는 가비와 페어가 매칭되었다!
      +체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
      +하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
      +미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

      +

      가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
      +최종적으로 결정한 부분은 다음과 같다.

      +

      각 기물의 이동 가능여부
      +Rank와 File은 각각 위치값을 가지고 있고, 값의 차이를 이용해서 각 기물의 이동 가능 여부를 계산했다.
      +직선 → Rank와 File 차이 중 하나가 0이어야 한다.
      +대각선 → Rank와 File 차이의 절대값이 같아야 한다. ex) abs(-2) == abs(2)
      +나이트 → 차이의 절대값이 하나는 2 나머지 하나는 1이어야 한다.

      +

      도착 칸의 기물 여부
      +아군 → 이동이 불가능하다.
      +적군 → 이동이 가능하다. 적군을 잡는다.

      +

      중간에 기물 존재 여부
      +이동 경로에 기물이 존재하면 안된다.

      +

      데이터베이스 사용
      +체스 미션은 특별하게 데이터베이스와 연결하는 부분이 있었다.
      +체스 게임의 상태를 다음의 두가지 방법으로 정할 수 있다고 생각했다.

      +
        +
      • 기물 전체를 저장하는 방법
      • +
      • 기보를 저장하고 게임을 불러와 기보대로 이동시키는 방법
      • +
      +

      기물이 이동할 때마다 값을 저장하고 싶었고, 기보를 저장하는 방법을 선택했다.
      +기물 전체를 저장하지 않은 이유는 다음과 같다.

      +
        +
      • 턴과 같은 부가적인 요소를 저장해야 한다.
      • +
      • 이동을 할 때 기물이 잡히는 경우 update 쿼리(이동 기물)와 delete(잡힌 기물) 2개의 쿼리를 날려야 한다.
      • +
      • 현재 구조에서 도메인의 변경이 크게(초기 상태를 구성하는 부분) 일어나야 한다.
      • +
      +

      정리하자면 기물 전체 저장과 기보 저장은 다음과 차이가 있다.
      +보드저장: 초기상태에서 32개의 Insert 쿼리(기물의 위치) + 기물 이동 시 움직임 변경(잡히는 경우 2개의 쿼리)
      +기보저장: 초기상태 애플리케이션에서 구성 + 저장된 기보를 select 쿼리로 조회해서 사용(1회) + insert 쿼리(이동 당 1회)

      +

      추가로 기보저장이 구현도 더욱 간단하다. 👍

      +

      부가적인 부분

      +

      리뷰어인 찰리🍫가 동시에 여러 게임이 진행된다면 어떨지? 에 대한 코멘트를 남겨주셔서 다양한 시도를 해봤다.

      +
        +
      • 누누의 도움으로 ConnectionPool 구현
      • +
      • ThreadLocal 사용해서 쓰레드 별 세션 관리
      • +
      • 실제로 애플리케이션 내에서 체스 게임이 진행되는 Board를 ConcurrentHashMap으로 저장(사실 이 부분은 현재 구조에서 필요없지만 2명이 서로 게임하는 경우를 생각해서 넣어보았다.)
      • +
      +

      두 명이 서로 같은 방에 입장하여 게임을 진행한다면 출력하는 부분이 까다로워질 것 같다고 예상되어(Board에 옵저버 패턴을 사용해야되나?) 해볼 엄두가 나지 않았다.

      +

      부족했던 부분

      +

      꼼꼼하게 코드를 작성하지 못한 부분
      +DB 관련 부분을 꼼꼼하게 코딩을 하지 못했다.
      +도메인 로직에만 집중하다보니 정적 중요한 DB의 코드의 예외처리, 빈 값을 반환 하는 부분을 꼼꼼하게 처리하지 못했다.
      +하지만 찰리의 꼼꼼한 리뷰로 DB부분과 나만의 JdbcTemplate을 깔끔하게 구현할 수 있었다.

      +

      시간에 대한 부담감
      +초반에는 여유롭지만 제출 마감에 가까워질 수록 사람이 급해지는 것 같다.
      +다음 페어프로그래밍할 땐 속도를 조절하고, 마음에 여유를 가져야겠다.

      +

      새로 학습한 부분

      +

      DAO 중복 제거

      +

      프롤로그에 을 작성했다.
      +DAO를 작성하는데 try-catch-resources와 여러 코드가 중복되서 제거하고싶었다.
      +템플릿 콜백 패턴으로 깔끔하게 중복을 제거할 수 있었다.👍

      +

      페어에게 배울 부분

      +

      페어 생각하기
      +가비는 누구보다 페어를 생각하고, 배려해주는 페어였다.
      +중간 중간 당 떨어질까봐 걱정도 해주고, 나의 컨디션도 확인해줬다!

      +

      미션 몰입하기
      +최근에 미션에 잘 몰입하지 못했다.
      +가비는 페어를 진행할 때 미션에 대한 몰입도가 매우 좋았다.
      +집에가서도 체스 이동에 대한 로직을 어떻게 구현할 지 생각한 뒤 꼼꼼해서 정리해서 나에게 보내주었다.
      +덕분에 나도 가비의 생각을 알 수 있어서 미션을 진행하는데 가속도가 붙은 것 같다.
      +또한 미션을 잘 마무리하고 싶은 마음이 전달되서 그런지 나도 덩달아 열심히 미션을 할 수 있었다.😄

      +

      솔직함
      +먼저 회고하자고 말 걸어줘서 정말 고마웠다고 표현해주는 부분
      +모르는게 있으면 솔직하게 말해주는 부분
      +나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
      +솔직함은 페어할 때 중요한 부분인 것 같다.

      +

      마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

      \ No newline at end of file diff --git a/tags/retrospective/page/6.html b/tags/retrospective/page/6.html index a13936e26..a8fc702c1 100644 --- a/tags/retrospective/page/6.html +++ b/tags/retrospective/page/6.html @@ -13,31 +13,77 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 3분

      23년의 6월이 오고, 레벨 2가 끝났다.
      -빠르게 지나가서 조금 아쉽다.

      -

      학습

      -

      회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
      -항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
      -미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

      -

      고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
      -방학 그리고 레벨 3 때는 조금 더 이론적인 부분을 학습하는데 집중해야겠다.

      -

      점차 학습 범위가 넓어지면서 자연스럽게 모르는 내용이 쌓여간다.
      -필요한 내용은 앞으로 천천히 학습하면 되니까 조급해지지 말아야겠다.

      -

      수면

      -

      레벨 2를 진행하는 동안 수면이 많이 부족했었고, 결과적으로는 그날의 컨디션을 많이 좌우했던 것 같다.
      -앞으로 수면 시간을 늘리고, 좋은 수면 습관을 가지도록 노력해야겠다.

      -

      협업

      -

      레벨 2 마지막에 협업 미션이 있었다.
      -지금까지는 백엔드 크루들과 페어 프로그래밍을 하면서 협업을 경험했다.
      -이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

      -

      레벨 3 때부터 본격적으로 프로젝트가 시작된다.
      -팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

      -

      레벨 2를 마무리하며

      -

      회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. -읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 8분

      레벨 1이 끝났다.
      +우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
      +혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
      +하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

      +

      Keep

      +

      나만의 루틴 만들기

      +

      스스로가 외부의 영향을 많이 받는다고 생각한다.
      +최대한 꾸준히 할 수 있는 시간을 만드는 것이 중요하다고 생각한다.

      +

      매일 8시에 도착하여 아침에 해야 할 일을 정리하거나, 우선순위에 따라 처리하고
      +소화능력이 부족하기 때문에 점심은 도시락(그래봤자 계란2개)을 준비하고
      +항상 똑같은 컨디션을 유지하기 위해 항상 6시에 집에 간다.
      +이제 바빠질 테니 일찍 집에 가는 일은 어쩔 수 없이 줄어들겠지만😢

      +

      선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

      +

      크루들과 친하게 지내기

      +

      10명 정도의 크루의 닉네임을 외우고 친하게 지낸다면 성공적이라고 생각했었다.
      +하다 보니 더 많은 크루들의 닉네임을 외운 것 같다.
      +앞으로도 크루들과 친하게 지내고 아무 때나 말을 걸 수 있는 크루가 늘어나길 :)

      +

      글쓰기

      +

      글을 잘 쓰는 편은 아니지만 꾸준히 작성하려고 노력했다.
      +매 미션마다 회고를 작성하니 생각도 정리되고 개선점도 찾을 수 있어서 좋았다.

      +

      우아한테크코스에는 레벨마다 글쓰기를 진행하는데, 운이 좋게 글쓰기 상을 받았다.
      +사실 겉으로 드러내지 않았지만 꼭 받아보고 싶었다.
      +글쓰기 조원, 투표해 준 크루들에게 너무 감사하다.

      +

      코드 리뷰 스터디

      +

      누누, 주노, 다즐, 말랑, 박스터, 오잉, 깃짱와 코드 리뷰 스터디를 진행했다.
      +과연 도움이 될까 생각했지만 결과적으로는 코드 리뷰를 하면서 성장을 많이 한 것 같다.
      +투자한 시간 대비 가성비가 좋은 활동이었다.
      +누누가 스터디장인데 과연 꾸준히 이어나가려나?

      +

      레벨 인터뷰

      +

      인터뷰할 때 많이 떨지 않아서 좋았다.
      +남들 앞에서 이야기를 하거나, 면접을 보면 항상 엄청 떨어서 걱정했는데
      +기술적인 질문을 받았을 때 떨지 않고 잘 대답할 수 있었다.
      +우아한테크코스 생활을 하면서 다른 크루가 질문했을 때, 최대한 이해하기 쉽게 설명하려고 했던 경험이 도움이 된 것 같다.
      +이후 레벨 인터뷰를 진행할 때 다음과 같은 부분을 고려하면 더 좋을 것 같다.

      +
        +
      • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
      • +
      • 두괄식 표현
      • +
      • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
      • +
      • 설명할 수 있을만큼 시간 충분히 가지기
      • +
      • 인터뷰어의 질문 의도를 명확히 이해하지 못했다면 의도 다시 물어보기
      • +
      • 끝맺는 부분 연습하기(자신감 있게)
      • +
      • 기술적인 집착가지기
      • +
      • 기술적인 부분을 꼼꼼히 준비했으면 협업 관련 질문도 준비하기
      • +
      +

      Problem

      +

      페어프로그래밍

      +

      우아한테크코스를 진행하면서 가장 어려운 활동 중 하나라고 생각한다.
      +페어는 매번 바뀌고, 미션의 복잡도도 증가하기 때문인 것 같다.
      +소통 능력, 시간관리가 부족했고, 만족스럽지 않았다.
      +하지만 페어를 진행하고, 회고를 하다 보니 나만의 노하우가 쌓이는 느낌이다.
      +레벨 2에서는 부족했던 부분을 개선하여 함께하고 싶은 페어가 되고 싶다.

      +

      집중하는 시간⏱️ 부족

      +

      레벨 1을 진행하면서 집중하는 시간이 많이 부족했다.
      +이른 아침과 오후에 개인적으로 집중할 수 있는 공간을 예약해서 온전히 나만의 시간을 가져야겠다.

      +

      Try

      +

      허브🌿와의 티타임?

      +

      소프트 스킬을 늘릴 방법을 생각하다가 대화를 나누지 못한 다른 크루들과 깜짝 커피챗을 하면 어떨까 생각했다.
      +예를 들어 잡담방에 저와 커피챗 하실 분 :) 하면서 올릴 수 있을 것 같다.
      +참여하는 사람이 있을지, 안 좋게 보는 게 아닐지 걱정되지만 그래도 재밌을 것 같다.
      +저랑 허브티 한잔 하실래요?

      +

      기술적인 부분

      +

      우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
      +시간의 여유가 될 때 책을 조금씩 읽어야겠다.
      +블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

      +

      레벨 1을 마무리하며

      +

      시간이 빠르게 흘러갔다.
      +타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
      +또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

      \ No newline at end of file diff --git a/tags/retrospective/page/7.html b/tags/retrospective/page/7.html index 954d03a7b..ab8f62446 100644 --- a/tags/retrospective/page/7.html +++ b/tags/retrospective/page/7.html @@ -13,35 +13,63 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      레벨 인터뷰

      -

      레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
      -따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
      -이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
      -기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

      -

      API 문서 도구 선택

      -

      큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
      -백엔드 팀원이 함께 의사결정을 했고, 미션 기간이 짧은 만큼 팀 차원에서 비교적 학습하기 쉬운 Swagger를 선택했다.
      -추가로 들어가는 시간 대비 하이 리턴이라고 생각했다고 답변했다.

      -

      팀 차원의 학습 비용을 언급해서, 다음과 같은 좋은 피드백을 받았다.

      -
      -

      특히 팀으로 의사결정하는 과정을 공유해 준 점이 좋았고 기술적 의사결정 과정에서 팀의 학습비용을 고려한 점이 좋았음.
      -앞으로도 학습 비용은 주요하게 고려해야 할 사항

      -
      -

      PUT과 PATCH & 토큰과 세션

      -

      PUT과 PATCH 차이를 설명하는 부분에서는 PATCH를 사용할 때 페이로드가 적어진다는 내용을 빼먹고 답변을 했다.
      -토큰과 세션의 경우 기술을 잘 모르는 사람에게 설명해달라는 제약조건이 추가되었다.

      -

      해당 내용을 답변하면서 기술적인 깊이가 많이 부족했다는 생각이 든다.
      -실제로 레벨 2 때 이론적인 학습 시간이 매우 적었고, 집중력도 많이 부족했다.
      -앞으로 어떻게 깊이를 채울지 고민을 할 수 있는 질문들이었다.

      -

      추가로 기술을 잘 모르는 사람에게 설명하는 가정을 두고 학습을 한다면 큰 도움이 될 거라는 피드백을 받았다.

      -

      그 외 개선할 점

      -

      인터뷰할 때 특유의 말버릇을 개선하기
      -생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
      -기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
      -이전에 공부했던거 되돌아 보는 시간 가지기

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 6분

      4월 21일 금요일

      +

      레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
      +레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
      +단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
      +글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

      +

      나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
      +Chat-GPT 서비스를 크루들에게 제공하고, 해당 크루들이 질문한 내용을 공유할 수 있는 건 어떤지?

      +

      기술이 목적인 사이드 프로젝트를 진행하면 좋을 것 같다는 답변을 들었고, 혼자 아니면 페어할 수 있을 정도의 인원으로 진행하면 좋겠다고 하셨다.
      +프론트랑 간단하게 배포까지 해본 경험이 있어서 혼자해도 크게 어렵지 않을 것 같아서 혼자 하기로 마음을 먹었다.

      +

      이건 못참지

      +

      도메인 구입 성공?

      +

      커피챗이 끝나고 집으로 돌아가는 길에 바로 도메인을 구매하려고 namecheap에서 적당한 도메인이 없을까 검색을 계속했다.
      +마치 어릴 때 했던 게임 닉네임 정하는 것처럼 시간이 오래 걸렸다.
      +dev, io, chat 도메인이 후보였고 집 가는 길에 결정만 하다가 구매하지 못했다.

      +

      말랑의 DM

      +

      집에 가서 밥을 먹고 말랑이랑 DM 하다 프로젝트를 같이 하자는 이야기가 나왔다.
      +우테코 최고 고수 말랑의 요구라 수락하지 않으면 후폭풍을 감당할 수 없었다.

      +

      이런저런 대화를 나누다가 난 빠르게 프로토타입을 만들어 보고 싶어서 프론트를 구현한다고 했고, 말랑은 GPT api를 조사하기로 했다.
      +추가로 도메인에 관한 이야기를 하다가 woowachat이 언급되었고, namecheap에서 chat 도메인을 사용한 woowa.chat으로 구매했다.
      +이후에 teco.chat으로 변경했다!

      +

      도메인 설정 및 배포

      +

      토요일에 구매한 도메인을 CDN, 보안 등 다양한 기능을 제공하는 Cloudflare에 도메인 등록을 했다.
      +나에게 익숙한 Nuxt3를 사용하기로 했고, Cloudflare Pages를 이용하여 배포했다.

      +

      GPT

      +

      무료 크레딧을 사용하니 api limit이 있어 분당 3번밖에 사용할 수 없었다.
      +일단 백엔드를 구축하기 전에는 무료 크레딧을 사용할 생각이다.

      +

      Sonarcloud

      +

      정적 코드 분석 도구로 Sonarcloud를 적용했다.
      +Sonarcloud는 SonarQube의 SaaS 버전이고 사용이 매우 편하다.
      +예전에 Sonarcloud를 사용할 땐 버튼 몇 번 누르면 적용할 수 있었는데, 이번에는 바로 github action을 사용하라는 안내 페이지로 이동했다.
      +Sonarcloud가 자체적으로 github repository에 push 하면 정적 분석을 해주는 기능을 원했고, Administration -> Analysis Method에 Automatic Analysis를 설정하니 되었다.
      +너무 꽁꽁 숨겨져있네

      +

      Tiptap

      +

      코드 하이라이팅 기능을 넣고 싶어서 Tiptap을 사용했다.
      +Tiptap은 Headless WYSIWYG 에디터로 사용자 정의 기능에 특화되어있는 에디터다.
      +아직 Tiptap이 제공하는 모든 기능을 자연스럽게 사용하지는 못하지만 CodeBlockLowlight 플러그인을 사용하여 코드 블록을 예쁘게 출력할 수 있었다.
      +api 반환값 그대로 tiptap의 content에 설정했더니 코드 블록이 설정되지 않아서 백 틱 3개를 <pre><code>로 변환했다.
      +추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
      +변환하는 로직은 GPT의 도움을 많이 받았다.

      +
      const replaceCodeFences = (input: String) => {
      +    const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
      +    return input
      +        .replace(codeFencesRegex, (match, p1, p2) => {
      +        const languageClass = p1 ? ` class="language-${p1}"` : "";
      +        return `<pre><code${languageClass}>${p2}</code></pre>`;
      +        })
      +        .replace(/\n/g, "<br>");
      +};
      +
      +

      Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

      +

      tecochat

      +

      폰트 및 favicon 적용

      +

      타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
      +추가로 favicon도 간단하게 적용해서 만족스러웠다.

      \ No newline at end of file diff --git a/tags/retrospective/page/8.html b/tags/retrospective/page/8.html index e1a3195ca..0ce99dca2 100644 --- a/tags/retrospective/page/8.html +++ b/tags/retrospective/page/8.html @@ -13,76 +13,54 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      1단계: AWS 배포
      -2단계: https://github.com/woowacourse/jwp-shopping-order/pull/7

      -

      장바구니 주문 미션

      -

      배포 및 협업을 할 수 있는 미션이었다.
      -마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

      -

      배포

      -

      이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
      -각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
      -배포 스크립트를 작성하는 경험을 해볼 수 있었다.
      -배포 스크립트에 시간을 많이 투자하진 않았고, 다음과 같이 간단하게 작성했다.

      -
      echo "Start Deploy Script"
      -REPOSITORY_NAME=/home/ubuntu/jwp-shopping-order
      -PROJECT_NAME=jwp-shopping-order
      -
      -echo "Change Directory"
      -cd $REPOSITORY_NAME
      -
      -echo "Git Pull"
      -git pull origin step2
      -
      -echo "Build"
      -./gradlew bootJar
      -
      -echo "Copy, Start Server"
      -mv ./build/libs/$PROJECT_NAME.jar .
      -
      -PID=$(pgrep -f $PROJECT_NAME)
      -
      -if [ -n $PID ]; then
      -        kill -9 $PID
      -	sleep 5
      -fi
      -
      -nohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &
      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      프론트엔트

      +

      닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
      +추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
      +자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
      +여유가 된다면 자신의 채팅을 볼 수 있는 기능이나, 채팅을 이어서 할 수 있는 기능, 댓글 기능도 추가할 예정이다.

      +

      백엔드

      +

      최대한 빨리 서비스를 크루들에게 제공하기로 정해서, 백엔드는 말랑이 일단 다 만들고 있다.
      +말랑이 한 부분이 너무 많아서 내가 못 따라가는 것 같다.
      +나중에 백엔드 코드를 이해하는 시간을 가져야겠다.

      +

      Http Request Header

      +

      아직 인증에 대한 부분을 하지 않아서 요청 헤더에 이름을 보내기로 했다.
      +말랑이 한글은 안된다고 말해줘서 Base64로 인코딩하고, 백엔드에서 디코딩 하여 사용하기로 했다.
      +아래는 pinia에 있는 name 값을 인코딩 하는 코드다. deprecated 되었다는데, 다른 방법을 사용할 줄 몰라서 일단 이걸 사용했다.

      +
      const encodedName = () => {
      +  const uriComponent = unescape(encodeURIComponent(name.value));
      +  return btoa(uriComponent);
      +};
       
      -

      협업

      -

      일단 우스랑 우코가 먼저 잠실로 와줘서 너무 감사했다.
      -백엔드가 아닌 다른 크루들과 해보는 첫 협업이라 약간 두근거렸다.
      -예상외로 대화가 잘 되어서, 빠르게 명세를 정할 수 있었다.

      -

      부족했던 부분

      -

      여러가지 방법에 대한 장단점을 고려해보기

      -

      백엔드와 테이블 명세나 쿠폰 구현에 대해서 이야기할 때 장단에 대해 많이 고려하지 못한 것 같다.
      -조금 더 시간을 많이 들여서 장단점을 고려했다면 더 좋은 결과물이 나오지 않았을까?
      -앞으로 선택의 순간에서 조금 더 시간을 들여보는 것도 좋을 것 같다.

      -

      새로 배운 부분

      -

      expose headers

      -

      웹 페이지에서 Location 헤더를 받을 수 없는 문제가 있었다.
      -기본적으로 허용 목록에 존재하는 응답헤더만 반환한다는 것을 모르고 있었다.
      -이를 expose headers 설정을 통해 해결할 수 있었다.
      -nginx 설정에 다음과 같이 추가해 주었다.

      -
      add_header 'Access-Control-Expose-Headers' 'Location'
      +

      Elastic Beanstalk

      +

      가장 빠르게 백엔드를 배포할 수 있는 방법이 뭘지 고민하다가 Elastic Beanstalk를 사용하기로 했다.
      +Elastic Beanstalk를 사용하면 인프라에 대해 잘 알지 못해도 애플리케이션을 빠르게 배포하고 관리할 수 있다.
      +모니터링, 로깅, 로드 밸런싱 등 다양한 기능을 제공한다.

      +

      Elastic Beanstalk RDS 설정 후 분리

      +

      초기 설정 시 RDS를 연결하고 설정 완료 후 분리한다면, Beanstalk 인스턴스 -> RDS 요청 시 인바운드 설정을 안 해도 된다.
      +RDS 분리 시 Beanstalk에 기본적으로 설정되어 있는 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD와 같은 환경 변수가 같이 제거된다.
      +추가로 Elastic Beanstalk로 RDS를 설정하면 기본 데이터베이스 명은 ebdb다.

      +

      Elastic Beanstalk nginx 설정

      +

      업로드하는 zip 파일 내부에 .platform/nginx/conf.d/ 경로에 설정 파일을 추가하면 nginx 설정을 할 수 있다.

      +

      Jenkins

      +

      백엔드 코드를 일일히 배포하기 불편해서 Jenkins를 이용하여 Repository에 코드를 push 할 때 자동으로 배포가 되게 설정하기로 했다.
      +작년에 확인했을 땐 2022년 12월 31일까지 EC2 ARM 기반 t4g.small이 무료였는데, 다시 들어가 보니 2023년까지 12월 31일까지 t4g.small을 무료로 사용할 수 있었다.
      +t4g.small은 램이 2G인데, 예전에는 부족하지 않았다고 생각했는데 Java 17을 써서 그런가 빌드 할 때 램이 많이 부족한 것 같아서 Swap 메모리 2기가를 추가로 설정했다.
      +추가로 build.gradle에서 아래와 같이 설정한다면 테스트 시 사용하는 램을 늘릴 수 있다. 기본값은 512MB라고 한다.

      +
      test {
      +    maxHeapSize = "1024m"
      +}
       
      -

      읽기 전용 트랜잭션

      -

      단순 조회 요청에 대한 성능을 향상시켜준다는 것이라고 간단히만 알고 있었다.
      -이번에 코멘트가 달려서 조금 더 자세히 공부해 보기로 했다.
      -Transactional(readOnly = true)를 사용하는 경우 다음과 같이 동작한다.

      -

      setReadOnly(true) 설정이 된 Connection으로 연결을 시도를 한다. 이 설정을 하는 경우 DB마다 다르게 동작한다.

      -
        -
      • h2의 Connection 구현체는 readOnly 설정을 무시하는 방향으로 구현되어 Transactional 적용되지 않는다.
      • -
      • MySQL 8.0(InnoDB 사용 시)의 경우 읽기 전용으로 알려진 트랜잭션의 경우 트랜잭션 ID를 설정하지 않기 때문에 조회 속도가 더 빨라진다.
      • -
      -

      ORM 프레임워크를 사용한다면 prepareTransactionalConnection를 호출한다고 한다.
      -추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

      -

      DAO에 @Transactional 적용

      -

      DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
      -Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
      -DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

      +

      Jenkins Blue Ocean

      +

      Blue Ocean은 Jenkins Pipeline을 구성하는 데에 있어 편리하게 해주는 도구다.
      +시각화도 잘 되어있고, 설정도 편리한 것 같다.
      +오늘 적용해 보니 램이 부족하여 중간에 잘 안되기도 하고 그래서 그냥 "Pipeline만 사용할 걸 그랬나?" 라는 생각이 든다.

      +

      참고 자료

      +

      Elastic Beanstalk, AWS
      +EC2 AWS Graviton, AWS
      +Default Memory Settings, AWS

      \ No newline at end of file diff --git a/tags/retrospective/page/9.html b/tags/retrospective/page/9.html index 1b7fd174c..38a355524 100644 --- a/tags/retrospective/page/9.html +++ b/tags/retrospective/page/9.html @@ -13,39 +13,49 @@ - - + + -

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      개요

      -

      원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
      -레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

      -

      나의 채팅 확인하고 이어하는 기능

      -

      GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
      -예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

      -

      chat1

      -

      좋아요와 댓글 기능

      -

      다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
      -누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
      -또한 댓글 추가 및 삭제 기능도 추가했다.

      -

      키워드 추출

      -

      어떻게 키워드 추출을 할지 고민을 많이 했는데, 일단 GPT를 이용해서 키워드를 추출하기로 했다.
      -해당 부분은 첫 질문에 대한 키워드만 추출하도록 했다.
      -백엔드에선 말랑이 이벤트 이용해서 첫 채팅 요청이 이루어지면, 비동기로 키워드를 추출하는 질문을 추가로 날리도록 구현하였다.
      -CSV 형식으로 GPT에게 답변을 입력해달라고 요청받는데, 이 부분이 문제(프롬프트 엔지니어링 부분이 반환된다.)가 좀 있는 것 같아서 개선이 필요한 것 같다.

      -

      chat2

      -

      다른 크루의 채팅 복사해서 이어하는 기능

      -

      다른 크루들의 채팅을 읽다가 궁금한 점이 있다면 복사해서 바로 질문을 할 수 있는 기능을 추가했다.
      -채팅이 복사된 후 바로 GPT와 대화를 할 수 있는 메인 화면으로 이동한다.

      -

      사용성 고려하기

      -

      chat3

      -

      위 화면은 회원가입 창이다.
      -사실 가장 마음에 드는 부분이고, 회원가입(닉네임만 입력하지만)할 때 익명을 원하는 사람들의 고민을 도와주게 끔 음식, 과일, 과자 등의 요소들을 입력하도록 유도했다! -추가로 GPT의 답변이 오면 자동으로 화면을 스크롤 해주는 것과 같이 사용성을 개선해 보려고 노력했지만 쉽지 않았다.
      -제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

      -

      향후 계획

      -

      실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
      -크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
      -일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

      +

      "Retrospective" 태그로 연결된 20개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 4분

      1단계: https://github.com/woowacourse/jwp-racingcar/pull/24
      +2단계: https://github.com/woowacourse/jwp-racingcar/pull/128

      +

      웹 자동차 미션

      +

      사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
      +웹 자동차 미션에서는 비버와 페어가 매칭되었다.
      +레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

      +

      스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
      +첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
      +난이도 높은 미션이 아니었지만 리뷰어인 라빈에게 칭찬을 많이 받아서 기분이 좋았다.
      +라빈 감사합니다!

      +

      부족했던 부분

      +

      컨디션도 좋지 않고 열정도 식은 것 같은 느낌이 들었다.
      +미션이 다소 여유롭다고 느껴져서, 시간에 대한 부분도 잘 관리하지 못한 것 같다.
      +미션에 잘 집중하지 못해서 페어에게 많이 미안했고, 나 자신에게 아쉬웠던 부분이 많았다.

      +

      지난번 회고를 다시 보는데 집중을 잘 못한 경우가 많은 것 같다.
      +도전적이지 않거나 시간이 부족하지 않으면 집중을 잘 못하는 것 같다.
      +머릿속에서 시간적 여유가 있다고 생각할 때가 가장 위험한 순간인 것 같다.

      +

      함께 자라기에서 나온 난이도 높이기가 필요해지는 순간이다.

      +

      새로 학습한 부분

      +

      중요도가 있는 어노테이션부터 클래스 이름에 가깝게 명시하기

      +
      @SuppressWarnings("NonAsciiCharacters")
      +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
      +@Transactional
      +@AutoConfigureMockMvc
      +@SpringBootTest
      +public class RacingGameIntegrationTest {
      +
      +

      페어에게 배울 부분

      +

      비버의 성격
      +비버가 성격이 좋아서 편하게 페어를 할 수 있었다.
      +미션을 진행하면서 성급하지 않고 여유로워서 좋았다.

      +

      미션에 집중하는 부분
      +내가 미션에 잘 집중하지 못했는데도 같이 페어를 잘 진행한 것 같아서 좋았다.
      +비버가 미션에 잘 집중해서 그렇지 않았나 생각했다.
      +근육맨 비버라 그런지 체력이 좋아서 그런가?
      +중간에 잘 안 쉬고도 집중해서 미션을 진행하는 걸 보고 대단하다고 생각했다.

      +

      학습에 대한 열정
      +추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
      +비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
      +나도 5월부터 조금 더 화이팅 해야겠다.

      \ No newline at end of file diff --git a/tags/spring-boot.html b/tags/spring-boot.html index 4647f011a..f62822eec 100644 --- a/tags/spring-boot.html +++ b/tags/spring-boot.html @@ -13,11 +13,11 @@ - - + + -

      "Spring Boot" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      자바 17, 스프링 6.0, 스프링 부트 3.1

      +

      "Spring Boot" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

      모든 태그 보기

      · 약 5분

      자바 17, 스프링 6.0, 스프링 부트 3.1

      팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
      2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

      자바 변경 사항

      @@ -79,7 +79,7 @@

      Record(Java 16)

      }

    추가적인 변경사항

    -

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    +

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    스프링, 스프링 부트 변경 사항

    스프링과 스프링 부트에도 많은 변경 사항이 있었다.
    따라서 필요해보이는 몇개 정도만 정리했다.

    diff --git a/tags/spring.html b/tags/spring.html index 740c8c4e9..28a071b6f 100644 --- a/tags/spring.html +++ b/tags/spring.html @@ -13,11 +13,11 @@ - - + + -

    "Spring" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    자바 17, 스프링 6.0, 스프링 부트 3.1

    +

    "Spring" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    자바 17, 스프링 6.0, 스프링 부트 3.1

    팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
    2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

    자바 변경 사항

    @@ -79,7 +79,7 @@

    Record(Java 16)

    }

    추가적인 변경사항

    -

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    +

    이외에도 stream의 toList, 인스턴스의 타입을 간편하게 체크하는 Pattern Matching Instanceof, Sealed class 등이 추가되었다.

    스프링, 스프링 부트 변경 사항

    스프링과 스프링 부트에도 많은 변경 사항이 있었다.
    따라서 필요해보이는 몇개 정도만 정리했다.

    @@ -100,7 +100,7 @@

    스프링 부트 최소 요구사

    Gradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6
    이외에도 서드파티들의 최신 릴리즈 버전을 사용함으로, 문제가 발생하는 경우 해당 버전에 맞는 릴리즈 노트를 참고할 수 있을 것 같다.

    참고 자료

    -

    어느 월급쟁이개발자 의 스프링 부트 따라잡기
    +

    어느 월급쟁이개발자 의 스프링 부트 따라잡기
    자바 9-16 주요 특징 복습하기
    Java EE에서 Jakarta EE로의 전환
    Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩
    diff --git a/tags/static.html b/tags/static.html index 1305d1a19..4c92c327b 100644 --- a/tags/static.html +++ b/tags/static.html @@ -13,11 +13,11 @@ - - + + -

    "static" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 3분

    개요

    +

    "static" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 3분

    개요

    정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
    하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

    예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

    diff --git a/tags/teco-chat.html b/tags/teco-chat.html index fad4a0150..acd1c3962 100644 --- a/tags/teco-chat.html +++ b/tags/teco-chat.html @@ -13,39 +13,63 @@ - - + + -

    "TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    개요

    -

    원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
    -레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

    -

    나의 채팅 확인하고 이어하는 기능

    -

    GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
    -예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

    -

    chat1

    -

    좋아요와 댓글 기능

    -

    다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
    -누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
    -또한 댓글 추가 및 삭제 기능도 추가했다.

    -

    키워드 추출

    -

    어떻게 키워드 추출을 할지 고민을 많이 했는데, 일단 GPT를 이용해서 키워드를 추출하기로 했다.
    -해당 부분은 첫 질문에 대한 키워드만 추출하도록 했다.
    -백엔드에선 말랑이 이벤트 이용해서 첫 채팅 요청이 이루어지면, 비동기로 키워드를 추출하는 질문을 추가로 날리도록 구현하였다.
    -CSV 형식으로 GPT에게 답변을 입력해달라고 요청받는데, 이 부분이 문제(프롬프트 엔지니어링 부분이 반환된다.)가 좀 있는 것 같아서 개선이 필요한 것 같다.

    -

    chat2

    -

    다른 크루의 채팅 복사해서 이어하는 기능

    -

    다른 크루들의 채팅을 읽다가 궁금한 점이 있다면 복사해서 바로 질문을 할 수 있는 기능을 추가했다.
    -채팅이 복사된 후 바로 GPT와 대화를 할 수 있는 메인 화면으로 이동한다.

    -

    사용성 고려하기

    -

    chat3

    -

    위 화면은 회원가입 창이다.
    -사실 가장 마음에 드는 부분이고, 회원가입(닉네임만 입력하지만)할 때 익명을 원하는 사람들의 고민을 도와주게 끔 음식, 과일, 과자 등의 요소들을 입력하도록 유도했다! -추가로 GPT의 답변이 오면 자동으로 화면을 스크롤 해주는 것과 같이 사용성을 개선해 보려고 노력했지만 쉽지 않았다.
    -제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

    -

    향후 계획

    -

    실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
    -크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
    -일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

    +

    "TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    4월 21일 금요일

    +

    레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
    +레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
    +단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
    +글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

    +

    나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
    +Chat-GPT 서비스를 크루들에게 제공하고, 해당 크루들이 질문한 내용을 공유할 수 있는 건 어떤지?

    +

    기술이 목적인 사이드 프로젝트를 진행하면 좋을 것 같다는 답변을 들었고, 혼자 아니면 페어할 수 있을 정도의 인원으로 진행하면 좋겠다고 하셨다.
    +프론트랑 간단하게 배포까지 해본 경험이 있어서 혼자해도 크게 어렵지 않을 것 같아서 혼자 하기로 마음을 먹었다.

    +

    이건 못참지

    +

    도메인 구입 성공?

    +

    커피챗이 끝나고 집으로 돌아가는 길에 바로 도메인을 구매하려고 namecheap에서 적당한 도메인이 없을까 검색을 계속했다.
    +마치 어릴 때 했던 게임 닉네임 정하는 것처럼 시간이 오래 걸렸다.
    +dev, io, chat 도메인이 후보였고 집 가는 길에 결정만 하다가 구매하지 못했다.

    +

    말랑의 DM

    +

    집에 가서 밥을 먹고 말랑이랑 DM 하다 프로젝트를 같이 하자는 이야기가 나왔다.
    +우테코 최고 고수 말랑의 요구라 수락하지 않으면 후폭풍을 감당할 수 없었다.

    +

    이런저런 대화를 나누다가 난 빠르게 프로토타입을 만들어 보고 싶어서 프론트를 구현한다고 했고, 말랑은 GPT api를 조사하기로 했다.
    +추가로 도메인에 관한 이야기를 하다가 woowachat이 언급되었고, namecheap에서 chat 도메인을 사용한 woowa.chat으로 구매했다.
    +이후에 teco.chat으로 변경했다!

    +

    도메인 설정 및 배포

    +

    토요일에 구매한 도메인을 CDN, 보안 등 다양한 기능을 제공하는 Cloudflare에 도메인 등록을 했다.
    +나에게 익숙한 Nuxt3를 사용하기로 했고, Cloudflare Pages를 이용하여 배포했다.

    +

    GPT

    +

    무료 크레딧을 사용하니 api limit이 있어 분당 3번밖에 사용할 수 없었다.
    +일단 백엔드를 구축하기 전에는 무료 크레딧을 사용할 생각이다.

    +

    Sonarcloud

    +

    정적 코드 분석 도구로 Sonarcloud를 적용했다.
    +Sonarcloud는 SonarQube의 SaaS 버전이고 사용이 매우 편하다.
    +예전에 Sonarcloud를 사용할 땐 버튼 몇 번 누르면 적용할 수 있었는데, 이번에는 바로 github action을 사용하라는 안내 페이지로 이동했다.
    +Sonarcloud가 자체적으로 github repository에 push 하면 정적 분석을 해주는 기능을 원했고, Administration -> Analysis Method에 Automatic Analysis를 설정하니 되었다.
    +너무 꽁꽁 숨겨져있네

    +

    Tiptap

    +

    코드 하이라이팅 기능을 넣고 싶어서 Tiptap을 사용했다.
    +Tiptap은 Headless WYSIWYG 에디터로 사용자 정의 기능에 특화되어있는 에디터다.
    +아직 Tiptap이 제공하는 모든 기능을 자연스럽게 사용하지는 못하지만 CodeBlockLowlight 플러그인을 사용하여 코드 블록을 예쁘게 출력할 수 있었다.
    +api 반환값 그대로 tiptap의 content에 설정했더니 코드 블록이 설정되지 않아서 백 틱 3개를 <pre><code>로 변환했다.
    +추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
    +변환하는 로직은 GPT의 도움을 많이 받았다.

    +
    const replaceCodeFences = (input: String) => {
    +    const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
    +    return input
    +        .replace(codeFencesRegex, (match, p1, p2) => {
    +        const languageClass = p1 ? ` class="language-${p1}"` : "";
    +        return `<pre><code${languageClass}>${p2}</code></pre>`;
    +        })
    +        .replace(/\n/g, "<br>");
    +};
    +
    +

    Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

    +

    tecochat

    +

    폰트 및 favicon 적용

    +

    타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
    +추가로 favicon도 간단하게 적용해서 만족스러웠다.

    \ No newline at end of file diff --git a/tags/teco-chat/page/2.html b/tags/teco-chat/page/2.html index 6e2757941..4b02637dc 100644 --- a/tags/teco-chat/page/2.html +++ b/tags/teco-chat/page/2.html @@ -13,11 +13,11 @@ - - + + -

    "TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    프론트엔트

    +

    "TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    프론트엔트

    닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
    추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
    자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
    @@ -27,7 +27,7 @@

    백엔드

    말랑이 한 부분이 너무 많아서 내가 못 따라가는 것 같다.
    나중에 백엔드 코드를 이해하는 시간을 가져야겠다.

    Http Request Header

    -

    아직 인증에 대한 부분을 하지 않아서 요청 헤더에 이름을 보내기로 했다.
    +

    아직 인증에 대한 부분을 하지 않아서 요청 헤더에 이름을 보내기로 했다.
    말랑이 한글은 안된다고 말해줘서 Base64로 인코딩하고, 백엔드에서 디코딩 하여 사용하기로 했다.
    아래는 pinia에 있는 name 값을 인코딩 하는 코드다. deprecated 되었다는데, 다른 방법을 사용할 줄 몰라서 일단 이걸 사용했다.

    const encodedName = () => {
    @@ -47,7 +47,7 @@ 

    Elastic Beanstalk nginx 설정

    업로드하는 zip 파일 내부에 .platform/nginx/conf.d/ 경로에 설정 파일을 추가하면 nginx 설정을 할 수 있다.

    Jenkins

    백엔드 코드를 일일히 배포하기 불편해서 Jenkins를 이용하여 Repository에 코드를 push 할 때 자동으로 배포가 되게 설정하기로 했다.
    -작년에 확인했을 땐 2022년 12월 31일까지 EC2 ARM 기반 t4g.small이 무료였는데, 다시 들어가 보니 2023년까지 12월 31일까지 t4g.small을 무료로 사용할 수 있었다.
    +작년에 확인했을 땐 2022년 12월 31일까지 EC2 ARM 기반 t4g.small이 무료였는데, 다시 들어가 보니 2023년까지 12월 31일까지 t4g.small을 무료로 사용할 수 있었다.
    t4g.small은 램이 2G인데, 예전에는 부족하지 않았다고 생각했는데 Java 17을 써서 그런가 빌드 할 때 램이 많이 부족한 것 같아서 Swap 메모리 2기가를 추가로 설정했다.
    추가로 build.gradle에서 아래와 같이 설정한다면 테스트 시 사용하는 램을 늘릴 수 있다. 기본값은 512MB라고 한다.

    test {
    diff --git a/tags/teco-chat/page/3.html b/tags/teco-chat/page/3.html
    index ab7ba183c..c2082f6bd 100644
    --- a/tags/teco-chat/page/3.html
    +++ b/tags/teco-chat/page/3.html
    @@ -13,63 +13,39 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    4월 21일 금요일

    -

    레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
    -레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
    -단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
    -글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

    -

    나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
    -Chat-GPT 서비스를 크루들에게 제공하고, 해당 크루들이 질문한 내용을 공유할 수 있는 건 어떤지?

    -

    기술이 목적인 사이드 프로젝트를 진행하면 좋을 것 같다는 답변을 들었고, 혼자 아니면 페어할 수 있을 정도의 인원으로 진행하면 좋겠다고 하셨다.
    -프론트랑 간단하게 배포까지 해본 경험이 있어서 혼자해도 크게 어렵지 않을 것 같아서 혼자 하기로 마음을 먹었다.

    -

    이건 못참지

    -

    도메인 구입 성공?

    -

    커피챗이 끝나고 집으로 돌아가는 길에 바로 도메인을 구매하려고 namecheap에서 적당한 도메인이 없을까 검색을 계속했다.
    -마치 어릴 때 했던 게임 닉네임 정하는 것처럼 시간이 오래 걸렸다.
    -dev, io, chat 도메인이 후보였고 집 가는 길에 결정만 하다가 구매하지 못했다.

    -

    말랑의 DM

    -

    집에 가서 밥을 먹고 말랑이랑 DM 하다 프로젝트를 같이 하자는 이야기가 나왔다.
    -우테코 최고 고수 말랑의 요구라 수락하지 않으면 후폭풍을 감당할 수 없었다.

    -

    이런저런 대화를 나누다가 난 빠르게 프로토타입을 만들어 보고 싶어서 프론트를 구현한다고 했고, 말랑은 GPT api를 조사하기로 했다.
    -추가로 도메인에 관한 이야기를 하다가 woowachat이 언급되었고, namecheap에서 chat 도메인을 사용한 woowa.chat으로 구매했다.
    -이후에 teco.chat으로 변경했다!

    -

    도메인 설정 및 배포

    -

    토요일에 구매한 도메인을 CDN, 보안 등 다양한 기능을 제공하는 Cloudflare에 도메인 등록을 했다.
    -나에게 익숙한 Nuxt3를 사용하기로 했고, Cloudflare Pages를 이용하여 배포했다.

    -

    GPT

    -

    무료 크레딧을 사용하니 api limit이 있어 분당 3번밖에 사용할 수 없었다.
    -일단 백엔드를 구축하기 전에는 무료 크레딧을 사용할 생각이다.

    -

    Sonarcloud

    -

    정적 코드 분석 도구로 Sonarcloud를 적용했다.
    -Sonarcloud는 SonarQube의 SaaS 버전이고 사용이 매우 편하다.
    -예전에 Sonarcloud를 사용할 땐 버튼 몇 번 누르면 적용할 수 있었는데, 이번에는 바로 github action을 사용하라는 안내 페이지로 이동했다.
    -Sonarcloud가 자체적으로 github repository에 push 하면 정적 분석을 해주는 기능을 원했고, Administration -> Analysis Method에 Automatic Analysis를 설정하니 되었다.
    -너무 꽁꽁 숨겨져있네

    -

    Tiptap

    -

    코드 하이라이팅 기능을 넣고 싶어서 Tiptap을 사용했다.
    -Tiptap은 Headless WYSIWYG 에디터로 사용자 정의 기능에 특화되어있는 에디터다.
    -아직 Tiptap이 제공하는 모든 기능을 자연스럽게 사용하지는 못하지만 CodeBlockLowlight 플러그인을 사용하여 코드 블록을 예쁘게 출력할 수 있었다.
    -api 반환값 그대로 tiptap의 content에 설정했더니 코드 블록이 설정되지 않아서 백 틱 3개를 <pre><code>로 변환했다.
    -추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
    -변환하는 로직은 GPT의 도움을 많이 받았다.

    -
    const replaceCodeFences = (input: String) => {
    -    const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
    -    return input
    -        .replace(codeFencesRegex, (match, p1, p2) => {
    -        const languageClass = p1 ? ` class="language-${p1}"` : "";
    -        return `<pre><code${languageClass}>${p2}</code></pre>`;
    -        })
    -        .replace(/\n/g, "<br>");
    -};
    -
    -

    Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

    -

    tecochat

    -

    폰트 및 favicon 적용

    -

    타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
    -추가로 favicon도 간단하게 적용해서 만족스러웠다.

    +

    "TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    개요

    +

    원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
    +레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

    +

    나의 채팅 확인하고 이어하는 기능

    +

    GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
    +예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

    +

    chat1

    +

    좋아요와 댓글 기능

    +

    다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
    +누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
    +또한 댓글 추가 및 삭제 기능도 추가했다.

    +

    키워드 추출

    +

    어떻게 키워드 추출을 할지 고민을 많이 했는데, 일단 GPT를 이용해서 키워드를 추출하기로 했다.
    +해당 부분은 첫 질문에 대한 키워드만 추출하도록 했다.
    +백엔드에선 말랑이 이벤트 이용해서 첫 채팅 요청이 이루어지면, 비동기로 키워드를 추출하는 질문을 추가로 날리도록 구현하였다.
    +CSV 형식으로 GPT에게 답변을 입력해달라고 요청받는데, 이 부분이 문제(프롬프트 엔지니어링 부분이 반환된다.)가 좀 있는 것 같아서 개선이 필요한 것 같다.

    +

    chat2

    +

    다른 크루의 채팅 복사해서 이어하는 기능

    +

    다른 크루들의 채팅을 읽다가 궁금한 점이 있다면 복사해서 바로 질문을 할 수 있는 기능을 추가했다.
    +채팅이 복사된 후 바로 GPT와 대화를 할 수 있는 메인 화면으로 이동한다.

    +

    사용성 고려하기

    +

    chat3

    +

    위 화면은 회원가입 창이다.
    +사실 가장 마음에 드는 부분이고, 회원가입(닉네임만 입력하지만)할 때 익명을 원하는 사람들의 고민을 도와주게 끔 음식, 과일, 과자 등의 요소들을 입력하도록 유도했다! +추가로 GPT의 답변이 오면 자동으로 화면을 스크롤 해주는 것과 같이 사용성을 개선해 보려고 노력했지만 쉽지 않았다.
    +제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

    +

    향후 계획

    +

    실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
    +크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
    +일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

    \ No newline at end of file diff --git a/tags/test.html b/tags/test.html index e4594ba99..3434faa06 100644 --- a/tags/test.html +++ b/tags/test.html @@ -3,7 +3,7 @@ -"test" 태그로 연결된 2개 게시물개의 게시물이 있습니다. | GG +"Test" 태그로 연결된 2개 게시물개의 게시물이 있습니다. | GG @@ -13,91 +13,50 @@ - - + + -

    "test" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    테스트 격리

    -

    테스트의 순서에 따라 성공 실패 여부가 결정되는 비결정적인(non-determinism) 테스트가 되어서는 안되고, 테스트는 항상 순서에 상관없이 독립적으로 수행되도록 보장되어야 한다. 일반적으로 자원의 공유, 외부 API, 시간 등으로 비결정적인 테스트가 된다. 이를 해결하기 위해 테스트 대역을 사용하거나, 컨텍스트를 재실행하는 @DirtiesContext, 자원을 초기화하기 위해 테스트 이후에 테이블을 롤백 하는 @Transactional등 다양한 방법이 있다.
    -해당 글에서는 스프링에서 데이터베이스 자원의 공유를 방지하기 위해 테스트 격리를 수행하는 부분에 대해 설명한다.

    -

    테스트끼리 서로 의존하면 안 된다.
    -서로 의존하게 된다면 하나의 테스트가 실패할 때, 또 다른 하나의 테스트가 실패할 수 있다.
    -다른 테스트에 의존하지 않고, 독립적으로 실행 가능한 테스트가 좋은 테스트다.

    -

    TestExecutionListener

    -

    스프링에서는 TextExecutionListner를 이용하여 각 테스트 실행 단계에서 이벤트를 수신할 수 있다.
    -이를 이용하면 JUnit의 @BeforeEach를 사용하는 것과 유사하게, 테스트의 생명주기 이전 또는 이후에 필요한 작업을 실행시킬 수 있다.

    -
    public interface TestExecutionListener {
    -    default void beforeTestClass(TestContext testContext) throws Exception {}
    -    default void prepareTestInstance(TestContext testContext) throws Exception {}
    -    default void beforeTestMethod(TestContext testContext) throws Exception {}
    -    default void beforeTestExecution(TestContext testContext) throws Exception {}
    -    default void afterTestExecution(TestContext testContext) throws Exception {}
    -    default void afterTestMethod(TestContext testContext) throws Exception {}
    -    default void afterTestClass(TestContext testContext) throws Exception {}
    -}
    -
    -

    AbstractTestExecutionListener 상속하여 구현

    -

    AbstractTestExecutionListener를 상속받아 테스트 격리 환경을 만들어주는 클래스로, 인터페이스인 TextExecutionListner와 달리 Ordered가 구현되어 있어 해당 클래스를 상속받아 구현한 클래스는 프레임워크가 제공하는 리스너 다음에 실행시키도록 해준다.
    -다음과 같이 데이터베이스에서 각각의 테이블에 해당하는 Truncate 쿼리를 만들어서 조회하고, Test 메서드가 끝날때 마다 해당 쿼리를 실행하여 테이블을 초기화시키도록 설정한다.

    -
    
    -public class DatabaseCleaner extends AbstractTestExecutionListener {
    -
    -    private static final String TRUNCATE_TABLE_QUERY = """
    -            SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ';') 
    -            FROM INFORMATION_SCHEMA.TABLES
    -            WHERE TABLE_SCHEMA = 'PUBLIC'
    -            """;
    -
    -    @Override
    -    public void afterTestMethod(TestContext testContext) {
    -        JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);
    -        List<String> truncateTableQueries = getTruncateTableQueries(jdbcTemplate);
    -        truncateTables(jdbcTemplate, truncateTableQueries);
    -    }
    -
    -    private JdbcTemplate getJdbcTemplate(TestContext testContext) {
    -        return testContext.getApplicationContext().getBean(JdbcTemplate.class);
    -    }
    -
    -    private List<String> getTruncateTableQueries(JdbcTemplate jdbcTemplate) {
    -        return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);
    -    }
    -
    -    private void truncateTables(JdbcTemplate jdbcTemplate, List<String> truncateTableQueries) {
    -        jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");
    -        truncateTableQueries.forEach(jdbcTemplate::execute);
    -        jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");
    -    }
    -}
    -
    -
    -

    Listener 등록

    -

    @TestExecutionListeners를 이용하여 사용자 정의 리스너를 등록할 수 있다.
    -mergeMode의 기본값은 REPLACE_DEFAULTS로 리스너가 이미 존재하는 경우 등록된 리스너로 변경된다.
    -MERGE_WITH_DEFAULTS로 설정한다면 Ordered 기준으로 순서가 결정된다.
    -이후 격리가 필요한 테스트들은 다음의 추상 클래스를 상속하여 사용하면 된다.

    -
    
    -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    -@TestExecutionListeners(
    -        value = DatabaseCleaner.class,
    -        mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
    -)
    -public abstract class AcceptanceTest {
    -
    -    @LocalServerPort
    -    private int port;
    -
    -    @BeforeEach
    -    public void setUp() {
    -        RestAssured.port = port;
    -    }
    -}
    -
    -
    +

    "Test" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    테스트 대역이란?

    +

    모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
    +Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

    +

    테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
    +외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

    +

    테스트 대역의 타입 계층 구조

    + +

    더미(Dummy)

    +

    가장 단순하고, 원시적인 유형의 테스트 대역이다.
    +기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
    +만약 메서드가 무언가 반환을 해야하는 경우 0, null과 같은 값을 반환한다.

    +

    스텁(Stub)

    +

    시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
    +이를 통해 특정 조건에서 메서드가 예상한대로 동작하는지 확인할 수 있다.

    +

    스파이(Spy)

    +

    스텁과 유사하지만 호출 여부를 기록하거나 호출할 때 전달한 인자값을 기록할 수 있다.
    +예) 메일 전송 기능을 가진 객체를 테스트 대역으로 구현했을 때 메일 전송 횟수를 기록한다.

    +

    목, 모의 객체(Mock)

    +

    목은 더미, 스텁, 스파이를 포함한다.
    +호출 시 사전에 정의된 결과를 반환하고, 예상치 못한 호출이 있을 경우 예외를 던질 수 있다.
    +또한 호출에 대한 검증을 할 수 있다.

    +

    가짜(Fake)

    +

    DOC와 동일한 기능을 제공하지만, 더욱 간단한 방법으로 구현된 것이다.
    +예) 실제 데이터베이스와 유사하게 동작하는 가짜 객체를 만들어 테스트할 수 있다.

    +

    의존 구성 요소, DOC를 테스트 더블로 대체할 수 있다.
    +테스트 더블은 DOC와 동일한 API를 제공해야 한다.

    +

    상호작용에 따른 목과 스텁 구분

    +

    단위 테스트 p.149 에서는 테스트 대역을 크게 목과 스텁으로 구분한다.
    +목은 SUT와 관련된 상호작용을 모방하고 검사하는 반면, 스텁은 단순 모방만 한다.

    +
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색
    +

    테스트 대상 시스템
    +테스트를 하려는 대상

    참고 자료

    -

    The Spring TestExecutionListener, Baeldung
    -인수테스트에서 테스트 격리하기, 테코블
    -Eradicating Non-Determinism in Tests, martin fowler
    -@SpringBootTest의 테스트 격리시키기, MangKyu

    +

    소프트웨어 장인 정신 이야기 - 3장 고급 테스트 주도 개발, 로버트 C. 마틴
    +단위 테스트 - 5장 목과 테스트 취약성, 블라디미르 코리코프
    +테스트 주도 개발 시작하기 - 7장 대역, 최범균
    +테스트 더블, Martin Fowler
    +테스트 관련 용어 정리, Johngrib
    +Test Double, Gerard Meszaros

    \ No newline at end of file diff --git a/tags/test/page/2.html b/tags/test/page/2.html index fb434725e..70cbb4906 100644 --- a/tags/test/page/2.html +++ b/tags/test/page/2.html @@ -3,7 +3,7 @@ -"test" 태그로 연결된 2개 게시물개의 게시물이 있습니다. | GG +"Test" 태그로 연결된 2개 게시물개의 게시물이 있습니다. | GG @@ -13,50 +13,91 @@ - - + + -

    "test" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    테스트 대역이란?

    -

    모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
    -Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

    -

    테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
    -외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

    -

    테스트 대역의 타입 계층 구조

    - -

    더미(Dummy)

    -

    가장 단순하고, 원시적인 유형의 테스트 대역이다.
    -기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
    -만약 메서드가 무언가 반환을 해야하는 경우 0, null과 같은 값을 반환한다.

    -

    스텁(Stub)

    -

    시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
    -이를 통해 특정 조건에서 메서드가 예상한대로 동작하는지 확인할 수 있다.

    -

    스파이(Spy)

    -

    스텁과 유사하지만 호출 여부를 기록하거나 호출할 때 전달한 인자값을 기록할 수 있다.
    -예) 메일 전송 기능을 가진 객체를 테스트 대역으로 구현했을 때 메일 전송 횟수를 기록한다.

    -

    목, 모의 객체(Mock)

    -

    목은 더미, 스텁, 스파이를 포함한다.
    -호출 시 사전에 정의된 결과를 반환하고, 예상치 못한 호출이 있을 경우 예외를 던질 수 있다.
    -또한 호출에 대한 검증을 할 수 있다.

    -

    가짜(Fake)

    -

    DOC와 동일한 기능을 제공하지만, 더욱 간단한 방법으로 구현된 것이다.
    -예) 실제 데이터베이스와 유사하게 동작하는 가짜 객체를 만들어 테스트할 수 있다.

    -

    의존 구성 요소, DOC를 테스트 더블로 대체할 수 있다.
    -테스트 더블은 DOC와 동일한 API를 제공해야 한다.

    -

    상호작용에 따른 목과 스텁 구분

    -

    단위 테스트 p.149 에서는 테스트 대역을 크게 목과 스텁으로 구분한다.
    -목은 SUT와 관련된 상호작용을 모방하고 검사하는 반면, 스텁은 단순 모방만 한다.

    -
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색
    -

    테스트 대상 시스템
    -테스트를 하려는 대상

    +

    "Test" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    테스트 격리

    +

    테스트의 순서에 따라 성공 실패 여부가 결정되는 비결정적인(non-determinism) 테스트가 되어서는 안되고, 테스트는 항상 순서에 상관없이 독립적으로 수행되도록 보장되어야 한다. 일반적으로 자원의 공유, 외부 API, 시간 등으로 비결정적인 테스트가 된다. 이를 해결하기 위해 테스트 대역을 사용하거나, 컨텍스트를 재실행하는 @DirtiesContext, 자원을 초기화하기 위해 테스트 이후에 테이블을 롤백 하는 @Transactional등 다양한 방법이 있다.
    +해당 글에서는 스프링에서 데이터베이스 자원의 공유를 방지하기 위해 테스트 격리를 수행하는 부분에 대해 설명한다.

    +

    테스트끼리 서로 의존하면 안 된다.
    +서로 의존하게 된다면 하나의 테스트가 실패할 때, 또 다른 하나의 테스트가 실패할 수 있다.
    +다른 테스트에 의존하지 않고, 독립적으로 실행 가능한 테스트가 좋은 테스트다.

    +

    TestExecutionListener

    +

    스프링에서는 TextExecutionListner를 이용하여 각 테스트 실행 단계에서 이벤트를 수신할 수 있다.
    +이를 이용하면 JUnit의 @BeforeEach를 사용하는 것과 유사하게, 테스트의 생명주기 이전 또는 이후에 필요한 작업을 실행시킬 수 있다.

    +
    public interface TestExecutionListener {
    +    default void beforeTestClass(TestContext testContext) throws Exception {}
    +    default void prepareTestInstance(TestContext testContext) throws Exception {}
    +    default void beforeTestMethod(TestContext testContext) throws Exception {}
    +    default void beforeTestExecution(TestContext testContext) throws Exception {}
    +    default void afterTestExecution(TestContext testContext) throws Exception {}
    +    default void afterTestMethod(TestContext testContext) throws Exception {}
    +    default void afterTestClass(TestContext testContext) throws Exception {}
    +}
    +
    +

    AbstractTestExecutionListener 상속하여 구현

    +

    AbstractTestExecutionListener를 상속받아 테스트 격리 환경을 만들어주는 클래스로, 인터페이스인 TextExecutionListner와 달리 Ordered가 구현되어 있어 해당 클래스를 상속받아 구현한 클래스는 프레임워크가 제공하는 리스너 다음에 실행시키도록 해준다.
    +다음과 같이 데이터베이스에서 각각의 테이블에 해당하는 Truncate 쿼리를 만들어서 조회하고, Test 메서드가 끝날때 마다 해당 쿼리를 실행하여 테이블을 초기화시키도록 설정한다.

    +
    
    +public class DatabaseCleaner extends AbstractTestExecutionListener {
    +
    +    private static final String TRUNCATE_TABLE_QUERY = """
    +            SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ';') 
    +            FROM INFORMATION_SCHEMA.TABLES
    +            WHERE TABLE_SCHEMA = 'PUBLIC'
    +            """;
    +
    +    @Override
    +    public void afterTestMethod(TestContext testContext) {
    +        JdbcTemplate jdbcTemplate = getJdbcTemplate(testContext);
    +        List<String> truncateTableQueries = getTruncateTableQueries(jdbcTemplate);
    +        truncateTables(jdbcTemplate, truncateTableQueries);
    +    }
    +
    +    private JdbcTemplate getJdbcTemplate(TestContext testContext) {
    +        return testContext.getApplicationContext().getBean(JdbcTemplate.class);
    +    }
    +
    +    private List<String> getTruncateTableQueries(JdbcTemplate jdbcTemplate) {
    +        return jdbcTemplate.queryForList(TRUNCATE_TABLE_QUERY, String.class);
    +    }
    +
    +    private void truncateTables(JdbcTemplate jdbcTemplate, List<String> truncateTableQueries) {
    +        jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");
    +        truncateTableQueries.forEach(jdbcTemplate::execute);
    +        jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");
    +    }
    +}
    +
    +
    +

    Listener 등록

    +

    @TestExecutionListeners를 이용하여 사용자 정의 리스너를 등록할 수 있다.
    +mergeMode의 기본값은 REPLACE_DEFAULTS로 리스너가 이미 존재하는 경우 등록된 리스너로 변경된다.
    +MERGE_WITH_DEFAULTS로 설정한다면 Ordered 기준으로 순서가 결정된다.
    +이후 격리가 필요한 테스트들은 다음의 추상 클래스를 상속하여 사용하면 된다.

    +
    
    +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    +@TestExecutionListeners(
    +        value = DatabaseCleaner.class,
    +        mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
    +)
    +public abstract class AcceptanceTest {
    +
    +    @LocalServerPort
    +    private int port;
    +
    +    @BeforeEach
    +    public void setUp() {
    +        RestAssured.port = port;
    +    }
    +}
    +
    +

    참고 자료

    -

    소프트웨어 장인 정신 이야기 - 3장 고급 테스트 주도 개발, 로버트 C. 마틴
    -단위 테스트 - 5장 목과 테스트 취약성, 블라디미르 코리코프
    -테스트 주도 개발 시작하기 - 7장 대역, 최범균
    -테스트 더블, Martin Fowler
    -테스트 관련 용어 정리, Johngrib
    -Test Double, Gerard Meszaros

    +

    The Spring TestExecutionListener, Baeldung
    +인수테스트에서 테스트 격리하기, 테코블
    +Eradicating Non-Determinism in Tests, martin fowler
    +@SpringBootTest의 테스트 격리시키기, MangKyu

    \ No newline at end of file diff --git a/tags/time.html b/tags/time.html index 8067c1b9f..d311532ef 100644 --- a/tags/time.html +++ b/tags/time.html @@ -13,11 +13,11 @@ - - + + -

    "Time" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 2분

    이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    +

    "Time" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 2분

    이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
    ISO-8601을 기반으로 작성
    설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

    날짜와 시간에 관련된 데이터를 다루는 국제 표준

    @@ -30,7 +30,7 @@

    Duration, Period

    간격을 표현하는 클래스

    TemporalAdjusters

    복잡한 날짜 조정이 필요할 때 사용
    -필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

    +필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

    @FunctionalInterface
     public interface TemporalAdjuster {
         Temporal adjustInto(Temporal temporal);
    diff --git a/tags/transaction.html b/tags/transaction.html
    index e08d1317d..4e0344d07 100644
    --- a/tags/transaction.html
    +++ b/tags/transaction.html
    @@ -13,11 +13,11 @@
     
     
     
    -
    -
    +
    +
     
     
    -

    "Transaction" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    트랜잭션(Transaction)

    +

    "Transaction" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 10분

    트랜잭션(Transaction)

    데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
    트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
    논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

    @@ -26,7 +26,7 @@

    트랜잭션의 속성(ACID)

    일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
    격리성(Isolation): 각각의 트랜잭션은 독립적이라 서로에게 영향을 주지 않아야 한다.
    지속성(Durability): 트랜잭션이 성공적으로 완료된다면 영구적으로 결과에 반영되어야 한다.

    -

    트랜잭션 주의사항

    +

    트랜잭션 주의사항

    트랜잭션은 꼭 필요한 최소의 코드에만 적용하는 것이 좋다.(트랜잭션의 범위를 최소화하라)
    구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

    데이터의 일관성과 안전성을 보장하기 위해 배제해야 한다.
    @@ -51,7 +51,7 @@

    READ UNCOMMITTED

    Database->>+Bob: Alice Alice->>Database: COMMIT(Alice)">

    READ COMMITTED

    -

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    +

    트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
    오라클 DBMS에서 기본으로 사용되는 격리 수준이다.
    REPEATABLE READ가 보장되지 않기 때문에 NON-REPEATABLE READ 문제가 발생한다.

    SERIALIZABLE InnoDB에서는 팬텀 리드 현상이 REPEATABLE READ 격리 수준에서 발생하지 않기 때문에 굳이 사용할 필요는 없다.

    격리 수준에 따른 부정합 문제

    격리 수준에 따라 더티 리드, 반복 가능하지 않은 조회, 팬텀 리드 문제가 발생한다.

    -
    격리 수준 / 부정합 문제더티 리드반복 가능하지 않은 조회팬텀 리드
    READ UNCOMMITTEDOOO
    READ COMMITTEDXOO
    REPEATABLE READXXO(InnoDB는 X)
    SERIALIZABLEXXX
    +
    격리 수준 / 부정합 문제더티 리드반복 가능하지 않은 조회팬텀 리드
    READ UNCOMMITTEDOOO
    READ COMMITTEDXOO
    REPEATABLE READXXO(InnoDB는 X)
    SERIALIZABLEXXX

    더티 리드(Dirty read)

    어떤 트랜잭션에서 처리한 작업이 완료되지 않았어도 다른 트랜잭션에서 볼 수 있는 현상
    트랜잭션 격리 수준이 READ UNCOMMITTED일 때 발생한다.
    diff --git a/tags/web-application.html b/tags/web-application.html index 0babb0194..d0a861455 100644 --- a/tags/web-application.html +++ b/tags/web-application.html @@ -13,11 +13,11 @@ - - + + -

    "web application" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    웹 애플리케이션 발전 과정

    +

    "web application" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    웹 애플리케이션 발전 과정

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.
    원래 회고에 작성하려고 했지만, 정리하다 보니 조금 길어져서 따로 분리했다.

    @@ -26,7 +26,7 @@

    WWW(1989)

    정적 페이지를 제공하는 웹 서버를 시작으로 동적 페이지가 필요했기 때문에 CGI가 등장했다.

    CGI(1993)

    -

    CGI는 동적 콘텐츠를 제공하기 위한 규약으로, 해당 인터페이스를 구현한 스크립트를 이용해서 매 요청마다 프로세스를 실행시켜 정보를 반환하도록 한다. 하지만 매 요청마다 프로세스를 실행시키기 때문에 서버에 많은 부하가 발생할 수 있다. 따라서 이러한 단점을 극복하기 위해 나온 것이 Servlet이다.

    +

    CGI는 동적 콘텐츠를 제공하기 위한 규약으로, 해당 인터페이스를 구현한 스크립트를 이용해서 매 요청마다 프로세스를 실행시켜 정보를 반환하도록 한다. 하지만 매 요청마다 프로세스를 실행시키기 때문에 서버에 많은 부하가 발생할 수 있다. 따라서 이러한 단점을 극복하기 위해 나온 것이 Servlet이다.

    Servlet(1996)

    Servlet은 웹 서버에서 실행되는 자바 프로그램으로 HTTP를 이용하여 웹 클라이언트의 요청을 수신하고 응답한다. CGI와 다르게 매 요청마다 프로세스가 아닌 스레드를 생성하여 응답한다.
    하지만 View 영역의 코드를 작성하기 위해 Servlet의 소스 코드를 알아야 하는 등 복잡도가 너무 높았다. 따라서 해당 문제를 해결하기 위해 JSP가 등장했다.

    @@ -49,7 +49,7 @@

    MVC(2000)

    Govind Seshadri

    이때 MVC 패턴이 처음 탄생한 것은 아니고, 서버 측 구현이라고 하는 것을 보니 MVC가 처음 등장한 건 아닌 것 같다.
    -해당 문서를 보면 MVC라는 용어의 등장은 1978년에 등장한 것으로 보인다.

    +해당 문서를 보면 MVC라는 용어의 등장은 1978년에 등장한 것으로 보인다.

    Spring Framework(2003)

    Spring은 복잡했던 J2EE을 대체하기 위해 2003년에 등장했다.
    J2EE는 웹 기반의 엔터프라이즈 애플리케이션을 구축하기 위한 플랫폼으로 위에서 설명한 Servlet, JSP, EJB 등의 기술을 포함하고 있다.
    @@ -60,7 +60,7 @@

    WebFlux 이전 Servlet 3.0(2009),

    Tomcat의 NIO 동작 방식을 보면 Poller가 소켓 커넥션을 들고 있다가 처리가 가능할 때 스레드를 할당하는 식으로 처리를 한다. 하지만 할당 후 Servlet과 통신하는 부분은 블로킹 방식으로 요청이 끝날 때까지 스레드를 점유하고 있었고, 스레드 점유로 인해 요청이 max thread에 도달하면 요청을 처리할 수 없었다.
    그래서 비동기 방식의 Servlet이 Servlet 3.0에 등장했다. 하지만 전통적인 I/O 방식을 사용하는 부분은 블로킹 방식으로 동작했다. Servlet 3.1에서 논블로킹 I/O가 추가되었지만, 많이 사용되지 않았다고 한다.

    Spring WebFlux(2017)

    -

    적은 수의 스레드로 동시성을 처리하고, 적은 리소스로 확장이 가능한 논블로킹 방식의 웹 기술이 필요했고, 기존의 Servlet의 경우 비동기를 지원한다 해도 동기식 API들이 많이 남아있었기 때문에 이러한 Servlet에 영향을 받지 않는 기술이 필요했다. 또한 기존에 Netty와 같이 비동기, 논블로킹 방식 서버로 자리를 잘 잡은 서버를 위해 Spring WebFlux가 등장했다.
    +

    적은 수의 스레드로 동시성을 처리하고, 적은 리소스로 확장이 가능한 논블로킹 방식의 웹 기술이 필요했고, 기존의 Servlet의 경우 비동기를 지원한다 해도 동기식 API들이 많이 남아있었기 때문에 이러한 Servlet에 영향을 받지 않는 기술이 필요했다. 또한 기존에 Netty와 같이 비동기, 논블로킹 방식 서버로 자리를 잘 잡은 서버를 위해 Spring WebFlux가 등장했다.
    추가로 데이터 접근을 위해 사용하는 JDBC의 경우 Blocking API라, Spring Webflux에서는 R2DBC를 사용한다고 한다.

    마치며

    해당 정리 내용의 경우 Async, Non Blocking 관련된 내용을 깊게 공부한 적이 없어서 정확하지 않을 수 있다.
    diff --git a/tags/web-socket.html b/tags/web-socket.html index 326a7d9a1..0ddfb6c40 100644 --- a/tags/web-socket.html +++ b/tags/web-socket.html @@ -13,11 +13,11 @@ - - + + -

    "WebSocket" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    웹소켓

    +

    "WebSocket" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    웹소켓

    단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
    웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

    웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

    diff --git a/tags/woowahan-techcourse.html b/tags/woowahan-techcourse.html index 6a6d9c128..bf1f484e9 100644 --- a/tags/woowahan-techcourse.html +++ b/tags/woowahan-techcourse.html @@ -13,65 +13,89 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 9분

    1단계: https://github.com/woowacourse/jwp-refactoring/pull/465
    -2단계: https://github.com/woowacourse/jwp-refactoring/pull/547
    -3단계: https://github.com/woowacourse/jwp-refactoring/pull/610
    -4단계: https://github.com/woowacourse/jwp-refactoring/pull/721

    -

    리팩터링 미션

    -

    요구사항 작성 → 테스트를 통한 코드 보호 → 리팩터링 → 의존성 리팩터링 → 멀티모듈 순서로 미션을 진행했다.
    -미션에 온전히 집중하고 싶었지만, 프로젝트와 병행하면서 진행했기에 어느정도 타협보고 진행한 부분이 많아서 아쉬웠다.

    -

    1, 2단계

    -

    1단계는 요구사항을 작성하고, 테스트 코드를 작성하여 추후에 리팩터링 할 때 안정감 있게 진행할 수 있도록 준비하는 과정이었다. -요구사항을 작성할 때 제공된 용어 사전을 최대한 활용하면서 기존의 코드를 보면서 요구사항을 정리했다. -테스트는 시간 관계상 API, 서비스 둘 중 하나만 통합 테스트를 진행해야겠다는 생각이 들었다.

    -

    최종적으로 서비스 기준으로 통합 테스트를 작성했는데 약간 후회되는 결정이었던 것 같다.
    -리팩터링 과정에서 API 명세가 바뀌지 않아야 한다는 것을 기준을 잡고 이번 미션을 한다고 가정했을 때 API 기준으로 테스트를 작성하고, 리팩터링을 진행하는 것이 더 안정감 있다고 생각한다.

    -

    2단계는 작성된 테스트 기반으로 리팩터링 하는 미션이었다.
    -서비스에서 도메인을 직접 반환하는 구조였는데, 도메인에 JPA를 적용하면 기존 명세와 달라질 것을 우려해서 DTO로 수정하는 작업을 먼저 진행했다. -DTO 이후에 서비스에 있는 로직을 도메인으로 이동시키고, 최종적으로 JPA를 적용하는 순서로 리팩터링을 진행했다. -이 과정에서 의존성 방향이 양방향인 부분도 생겨났다.

    -

    소프트웨어의 복잡성을 다루는 지혜

    -

    중간에 소프트웨어 복잡성을 다루는 지혜에 관한 제이슨의 강의가 있었다.
    -소프트웨어의 복잡성을 다루는 지혜는 에릭 에반스의 저서 도메인 주도 설계의 부제이다.

    -

    도메인 주도 설계는 유비쿼터스 언어, 전략적 설계, 전술적 설계가 중요하다고 한다.
    -유비쿼터스 언어, 전략적 설계가 전체의 90%에 해당할 정도로 중요하다고 한다. 또한 전술적 설계만 하는 경우를 DDD Lite 라고 한다.

    -

    간단히 도메인 주도 설계에서 나오는 단어를 정리한다면 다음과 같다.

    -
    단어설명
    도메인소프트웨어로 해결하고자 하는 문제 영역
    바운디드 컨텍스트해결 영역, 관심사를 분리하고 격리하여 문제 해결에 집중할 범위
    유비쿼터스 언어프로젝트에 이해관계자들의 공통된 언어로, 서로의 의사소통 비용을 줄이기 위해 사용하는 언어
    전략적 설계도메인 전문가와 개발자가 함께 유비쿼터스 언어를 이용하여 도메인과 관련된 지식을 이해하고 이를 바탕으로 경계를 나눠 바운디드 컨텍스트를 정의하고, 컨텍스트 맵을 생성하는 것을 포함하는 과정
    전술적 설계전략적 설계에서 정의한 바운디드 컨텍스트와 도메인을 이용하여 애그리거트, Entity와 VO, Repository 등을 구현하는 과정
    -

    이 외에도 다양한 내용들이 나왔지만, 지식을 제대로 흡수하지는 못했다.

    -

    3, 4단계

    -

    제이슨의 강의를 듣고, 조영호님의 우아한객체지향 유튜브 영상을 본 다음 3, 4단계를 진행했다.

    -

    3단계는 의존성 리팩터링에 관한 내용이었다. 클래스 간 방향, 패키지 간 방향을 단방향이 되도록 리팩터링을 진행해야 했었다. -함께 생성되고 삭제되는 객체들을 묶고, 결합도를 낮추기 위해 생명주기가 다르다면 id를 이용하여 참조하도록 변경했다.

    -

    의존성을 분리하기 위해 이벤트도 사용해보았다. 이벤트는 현재 기준으로 과거에 벌어진 것을 표현하기 때문에 이벤트명은 과거 시제가 되어야하는 것을 알았다. -처음에는 애플리케이션 이벤트를 사용했지만, 서비스 로직을 최대한 간단하게 하기 위해 도메인 이벤트도 사용해보았다.

    -

    4단계는 멀티모듈로 분리하는 미션이었는데 3단계에서 분리해둔 패키지 그대로 분리하지는 않았다.
    -3단계에서는 함께 생성되고 삭제되는 객체 기준으로 분리했다. 4단계에서는 내가 인식하기 편한 기준으로 분리를 했다. -아직 분리한 기준에 대한 근거가 모호했고, 이에 대한 공부를 조금 더 해야겠다고 생각했다.

    - -

    추가로 테스트 격리를 위한 직접 작성한 @ServiceTest 커스텀 애너테이션이 있었는데, 상위 모듈의 테스트에서 만든 클래스를 하위 모듈에서는 사용할 수 없었다. -따라서 TestFixtures를 사용하여 해결했다.

    -

    마무리

    -

    우아한테크코스의 마지막 미션이니 만큼, 가장 흥미로운 미션이었고 배울점도 많았던 것 같다.
    -바쁜 기간이라 많은 리뷰를 남기지 못했던 리뷰이 호이에게 미안하고, 코멘트 꼼꼼하게 달아주고 미션에 대한 이야기도 오프라인으로 많이 나눈 리뷰어 테오에게 너무 감사하다.

    -

    참고 자료

    -

    도메인 원정대, 우아콘 2021
    -우아한객체지향, 우아한테크세미나
    -TestFixtures, 권남님

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    1단계: https://github.com/woowacourse/java-racingcar/pull/510
    +2단계: https://github.com/woowacourse/java-racingcar/pull/538

    +

    자동차 경주

    +

    자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
    +우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

    +

    첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
    +시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

    +

    시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
    +mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

    +
      +
    • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
    • +
    • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.
    • +
    + +

    미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

    +

    페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
    +리팩터링을 어떻게 했는지? 이런 리뷰에 대해 어떻게 생각하는지 깊게 고민하는 시간을 가질 수 있었다.

    +

    부족했던 부분

    +

    리팩터링이 끝난 후 메서드명, 테스트시 출력하는 메시지에 대한 코멘트가 많이 달렸다.
    +객체가 어떤 책임과 역할을 가지는지 생각하는 시간을 가지고 명확한 메서드명을 작성해야겠다고 생각했다.

    +

    평소에 프로그래밍 이야기가 아닌 다른 주제로 이야기하면 잘 들으려고 하는 편이지만
    +내가 좋아하는 주제, 관심가는 주제인 프로그래밍에 대한 이야기를 할 땐 말이 많아진다.
    +다음 미션부터는 더 많은 시간을 페어의 의견과 이야기를 듣는 곳에 사용해야겠다.

    +

    새로 학습한 부분

    +

    Assertions extracting

    +

    결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
    +이전에는 필요에 따라 stream을 이용하여 검증할 값을 생성했지만, 해당 방법을 이용해서 절차를 줄일 수 있었다.

    +
    @Test
    +void extracting() {
    +    final Cars cars = new Cars(List.of("car1", "car2"));
    +
    +    assertThat(cars.getCars())
    +            .extracting(Car::getName)
    +            .containsExactly("car1", "car2");
    +}
    +
    +
    +

    아래는 리뷰어님과 대화를 나누면서 얻은 답변 + 나의 의견이다.

    +

    제어할 수 없는 부분에 대한 테스트

    +

    테스트 대상이 검증된 것이라면 작성하지 않거나, 제어할 수 있는 부분에 대한 테스트를 더욱 꼼꼼하게 작성한다.
    +이건 개인적인 생각이지만 내가 안정감이 들 수 있을 정도로 출력 범위 내의 결과를 반환하는지 정도 테스트할 수 있지 않을까?

    +

    단순 위임을 하는 메서드에 대한 테스트

    +

    위임이라는 것은 역할과 책임을 넘겨준다는 것이다.
    +호출 횟수를 검증하는 것보다 결과에 대한 테스트하는 것이 좋다.
    +단순히 위임만 하는 테스트의 경우 결과를 검증한다면 테스트가 중복되지 않을까 생각했었다.
    +따라서 중복된 테스트를 줄이기 위해 내부의 메서드를 호출하는지 검증하는 방법도 있다는 것을 알게 되었지만
    +안정적으로 결과를 테스트 하는 것이 더 좋은 방법인 것 같다.

    +

    테스트를 위한 getter 사용

    +

    테스트 용도로 도메인에 새로운 메서드가 생성되는 것은 좋지 못하다.
    +필요의 경우 생성해서 사용할 수 있지만, 기존에 있는 메서드들을 활용해보는 것이 더 좋은 방법이다.
    +이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

    +

    페어에게 배울 부분

    +

    질문이나 생각할 점이 있을 때 매우 깊게 고민하는 것 같았다.
    +생각을 정리한 후 자신의 의견을 명료하게 전달해주었다.
    +그렇기 때문에 지식을 효율적으로 습득한다.
    +난 생각을 잘 정리하지 않은 채로 내버려 둔 얕은 지식이 많은 것 같다. (이런 것도 아는 것이라고 할 수 있을까?)
    +앞으로 조금 더 머릿속에서 정리하고, 문제에 대해 깊게 고민하는 시간을 늘려야겠다.

    +

    개발에 열정을 가진 게 느껴진다.
    +나도 개발을 좋아하지만, 최근에는 의지가 약해졌었다.
    +열정이 가득한 사람을 만나니 나도 열정적인 사람이 되는 것 같다.

    +

    칭찬을 많이 해준다. 단순히 많이 해주는 것이 아니라, 진심을 담긴 칭찬을 해줬다.
    +칭찬은 고래도 춤추게 하던가?
    +그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

    +

    어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
    +이건 바로 배울 수 없지만.
    +나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/10.html b/tags/woowahan-techcourse/page/10.html index 78527eadd..b5dad33b4 100644 --- a/tags/woowahan-techcourse/page/10.html +++ b/tags/woowahan-techcourse/page/10.html @@ -13,46 +13,35 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    1단계: https://github.com/woowacourse/jwp-shopping-cart/pull/244
    -2단계: https://github.com/woowacourse/jwp-shopping-cart/pull/300

    -

    웹 장바구니 미션

    -

    장바구니 미션은 블랙캣이랑 진행했다.
    -요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
    -2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
    -Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
    -이전에 스프링 사용할 때는 아무 생각 없이 코드를 작성하는 경우가 많았는데, 코드를 작성할 때 근거가 생기고 있는 것 같다.

    -

    새로 학습한 부분

    -

    DTO 우발적 중복

    -

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.

    -

    dto1

    -

    클래스명을 제외하고 필드와 검증 로직 그 외 모든 게 같은 DTO를 보며 중복이라고 생각을 했고, 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
    -로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러 가지 종류로 나누어 설명하고 있다.

    -
      -
    • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
    • -
    • 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.
    • -
    -

    추가와 수정은 초기에는 중복으로 보이지만 초기 생성 시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다.
    -따라서 리뷰어 웨지가 아래와 같이 의존 역전을 이용하는 방법도 있다고 알려주셨다.

    -

    dto2

    -

    Interceptor에서 인증한 값 재사용

    -

    사실 조회를 두 번 하기 싫어서 다양한 방법을 생각했었는데 이번 미션에서는 ThreadLocal을 사용했다.
    -일단 Tomcat은 요청마다 다른 스레드를 사용하고, Interceptor에서 조회해서 만든 Credential을 ThreadLocal에 넣어두었다가 ArgumentResolver에서 꺼낸 다음 ThreadLocal을 clear 하면 문제가 없을 거라 판단했다.

    -

    리뷰어인 웨지에게도 어떤 방법을 사용할지 궁금증을 작성했었다.
    -웨지는 email에 index를 걸어두고 dao 재조회를 사용할 것이라고 했다.
    -재사용하지 않고 db에 인덱스를 걸 생각은 하지 못했는데, 제일 직관적이고 좋은 방법이라고 생각했다.

    -

    페어에게 배울 부분

    -

    기록

    -

    블랙캣은 기록을 굉장히 잘 하는 크루였다.
    -노션에 페어를 진행하면서 했던 내용 + 고민했던 부분 + 회고를 꼼꼼하게 기록해서 공유해 주었다.
    -추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

    -

    의견 일치시키기

    -

    페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
    -따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
    -블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

    -

    빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    레벨 인터뷰

    +

    레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
    +따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
    +이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
    +기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

    +

    API 문서 도구 선택

    +

    큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
    +백엔드 팀원이 함께 의사결정을 했고, 미션 기간이 짧은 만큼 팀 차원에서 비교적 학습하기 쉬운 Swagger를 선택했다.
    +추가로 들어가는 시간 대비 하이 리턴이라고 생각했다고 답변했다.

    +

    팀 차원의 학습 비용을 언급해서, 다음과 같은 좋은 피드백을 받았다.

    +
    +

    특히 팀으로 의사결정하는 과정을 공유해 준 점이 좋았고 기술적 의사결정 과정에서 팀의 학습비용을 고려한 점이 좋았음.
    +앞으로도 학습 비용은 주요하게 고려해야 할 사항

    +
    +

    PUT과 PATCH & 토큰과 세션

    +

    PUT과 PATCH 차이를 설명하는 부분에서는 PATCH를 사용할 때 페이로드가 적어진다는 내용을 빼먹고 답변을 했다.
    +토큰과 세션의 경우 기술을 잘 모르는 사람에게 설명해달라는 제약조건이 추가되었다.

    +

    해당 내용을 답변하면서 기술적인 깊이가 많이 부족했다는 생각이 든다.
    +실제로 레벨 2 때 이론적인 학습 시간이 매우 적었고, 집중력도 많이 부족했다.
    +앞으로 어떻게 깊이를 채울지 고민을 할 수 있는 질문들이었다.

    +

    추가로 기술을 잘 모르는 사람에게 설명하는 가정을 두고 학습을 한다면 큰 도움이 될 거라는 피드백을 받았다.

    +

    그 외 개선할 점

    +

    인터뷰할 때 특유의 말버릇을 개선하기
    +생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
    +기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
    +이전에 공부했던거 되돌아 보는 시간 가지기

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/11.html b/tags/woowahan-techcourse/page/11.html index 924fc5d93..a9f27e0ac 100644 --- a/tags/woowahan-techcourse/page/11.html +++ b/tags/woowahan-techcourse/page/11.html @@ -13,49 +13,31 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-racingcar/pull/24
    -2단계: https://github.com/woowacourse/jwp-racingcar/pull/128

    -

    웹 자동차 미션

    -

    사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
    -웹 자동차 미션에서는 비버와 페어가 매칭되었다.
    -레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

    -

    스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
    -첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
    -난이도 높은 미션이 아니었지만 리뷰어인 라빈에게 칭찬을 많이 받아서 기분이 좋았다.
    -라빈 감사합니다!

    -

    부족했던 부분

    -

    컨디션도 좋지 않고 열정도 식은 것 같은 느낌이 들었다.
    -미션이 다소 여유롭다고 느껴져서, 시간에 대한 부분도 잘 관리하지 못한 것 같다.
    -미션에 잘 집중하지 못해서 페어에게 많이 미안했고, 나 자신에게 아쉬웠던 부분이 많았다.

    -

    지난번 회고를 다시 보는데 집중을 잘 못한 경우가 많은 것 같다.
    -도전적이지 않거나 시간이 부족하지 않으면 집중을 잘 못하는 것 같다.
    -머릿속에서 시간적 여유가 있다고 생각할 때가 가장 위험한 순간인 것 같다.

    -

    함께 자라기에서 나온 난이도 높이기가 필요해지는 순간이다.

    -

    새로 학습한 부분

    -

    중요도가 있는 어노테이션부터 클래스 이름에 가깝게 명시하기

    -
    @SuppressWarnings("NonAsciiCharacters")
    -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    -@Transactional
    -@AutoConfigureMockMvc
    -@SpringBootTest
    -public class RacingGameIntegrationTest {
    -
    -

    페어에게 배울 부분

    -

    비버의 성격
    -비버가 성격이 좋아서 편하게 페어를 할 수 있었다.
    -미션을 진행하면서 성급하지 않고 여유로워서 좋았다.

    -

    미션에 집중하는 부분
    -내가 미션에 잘 집중하지 못했는데도 같이 페어를 잘 진행한 것 같아서 좋았다.
    -비버가 미션에 잘 집중해서 그렇지 않았나 생각했다.
    -근육맨 비버라 그런지 체력이 좋아서 그런가?
    -중간에 잘 안 쉬고도 집중해서 미션을 진행하는 걸 보고 대단하다고 생각했다.

    -

    학습에 대한 열정
    -추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
    -비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
    -나도 5월부터 조금 더 화이팅 해야겠다.

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 3분

    23년의 6월이 오고, 레벨 2가 끝났다.
    +빠르게 지나가서 조금 아쉽다.

    +

    학습

    +

    회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
    +항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
    +미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

    +

    고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
    +방학 그리고 레벨 3 때는 조금 더 이론적인 부분을 학습하는데 집중해야겠다.

    +

    점차 학습 범위가 넓어지면서 자연스럽게 모르는 내용이 쌓여간다.
    +필요한 내용은 앞으로 천천히 학습하면 되니까 조급해지지 말아야겠다.

    +

    수면

    +

    레벨 2를 진행하는 동안 수면이 많이 부족했었고, 결과적으로는 그날의 컨디션을 많이 좌우했던 것 같다.
    +앞으로 수면 시간을 늘리고, 좋은 수면 습관을 가지도록 노력해야겠다.

    +

    협업

    +

    레벨 2 마지막에 협업 미션이 있었다.
    +지금까지는 백엔드 크루들과 페어 프로그래밍을 하면서 협업을 경험했다.
    +이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

    +

    레벨 3 때부터 본격적으로 프로젝트가 시작된다.
    +팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

    +

    레벨 2를 마무리하며

    +

    회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. +읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/12.html b/tags/woowahan-techcourse/page/12.html index 1ded3cf94..5242bd974 100644 --- a/tags/woowahan-techcourse/page/12.html +++ b/tags/woowahan-techcourse/page/12.html @@ -13,77 +13,42 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    레벨 1이 끝났다.
    -우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
    -혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
    -하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

    -

    Keep

    -

    나만의 루틴 만들기

    -

    스스로가 외부의 영향을 많이 받는다고 생각한다.
    -최대한 꾸준히 할 수 있는 시간을 만드는 것이 중요하다고 생각한다.

    -

    매일 8시에 도착하여 아침에 해야 할 일을 정리하거나, 우선순위에 따라 처리하고
    -소화능력이 부족하기 때문에 점심은 도시락(그래봤자 계란2개)을 준비하고
    -항상 똑같은 컨디션을 유지하기 위해 항상 6시에 집에 간다.
    -이제 바빠질 테니 일찍 집에 가는 일은 어쩔 수 없이 줄어들겠지만😢

    -

    선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

    -

    크루들과 친하게 지내기

    -

    10명 정도의 크루의 닉네임을 외우고 친하게 지낸다면 성공적이라고 생각했었다.
    -하다 보니 더 많은 크루들의 닉네임을 외운 것 같다.
    -앞으로도 크루들과 친하게 지내고 아무 때나 말을 걸 수 있는 크루가 늘어나길 :)

    -

    글쓰기

    -

    글을 잘 쓰는 편은 아니지만 꾸준히 작성하려고 노력했다.
    -매 미션마다 회고를 작성하니 생각도 정리되고 개선점도 찾을 수 있어서 좋았다.

    -

    우아한테크코스에는 레벨마다 글쓰기를 진행하는데, 운이 좋게 글쓰기 상을 받았다.
    -사실 겉으로 드러내지 않았지만 꼭 받아보고 싶었다.
    -글쓰기 조원, 투표해 준 크루들에게 너무 감사하다.

    -

    코드 리뷰 스터디

    -

    누누, 주노, 다즐, 말랑, 박스터, 오잉, 깃짱와 코드 리뷰 스터디를 진행했다.
    -과연 도움이 될까 생각했지만 결과적으로는 코드 리뷰를 하면서 성장을 많이 한 것 같다.
    -투자한 시간 대비 가성비가 좋은 활동이었다.
    -누누가 스터디장인데 과연 꾸준히 이어나가려나?

    -

    레벨 인터뷰

    -

    인터뷰할 때 많이 떨지 않아서 좋았다.
    -남들 앞에서 이야기를 하거나, 면접을 보면 항상 엄청 떨어서 걱정했는데
    -기술적인 질문을 받았을 때 떨지 않고 잘 대답할 수 있었다.
    -우아한테크코스 생활을 하면서 다른 크루가 질문했을 때, 최대한 이해하기 쉽게 설명하려고 했던 경험이 도움이 된 것 같다.
    -이후 레벨 인터뷰를 진행할 때 다음과 같은 부분을 고려하면 더 좋을 것 같다.

    -
      -
    • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
    • -
    • 두괄식 표현
    • -
    • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
    • -
    • 설명할 수 있을만큼 시간 충분히 가지기
    • -
    • 인터뷰어의 질문 의도를 명확히 이해하지 못했다면 의도 다시 물어보기
    • -
    • 끝맺는 부분 연습하기(자신감 있게)
    • -
    • 기술적인 집착가지기
    • -
    • 기술적인 부분을 꼼꼼히 준비했으면 협업 관련 질문도 준비하기
    • -
    -

    Problem

    -

    페어프로그래밍

    -

    우아한테크코스를 진행하면서 가장 어려운 활동 중 하나라고 생각한다.
    -페어는 매번 바뀌고, 미션의 복잡도도 증가하기 때문인 것 같다.
    -소통 능력, 시간관리가 부족했고, 만족스럽지 않았다.
    -하지만 페어를 진행하고, 회고를 하다 보니 나만의 노하우가 쌓이는 느낌이다.
    -레벨 2에서는 부족했던 부분을 개선하여 함께하고 싶은 페어가 되고 싶다.

    -

    집중하는 시간⏱️ 부족

    -

    레벨 1을 진행하면서 집중하는 시간이 많이 부족했다.
    -이른 아침과 오후에 개인적으로 집중할 수 있는 공간을 예약해서 온전히 나만의 시간을 가져야겠다.

    -

    Try

    -

    허브🌿와의 티타임?

    -

    소프트 스킬을 늘릴 방법을 생각하다가 대화를 나누지 못한 다른 크루들과 깜짝 커피챗을 하면 어떨까 생각했다.
    -예를 들어 잡담방에 저와 커피챗 하실 분 :) 하면서 올릴 수 있을 것 같다.
    -참여하는 사람이 있을지, 안 좋게 보는 게 아닐지 걱정되지만 그래도 재밌을 것 같다.
    -저랑 허브티 한잔 하실래요?

    -

    기술적인 부분

    -

    우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
    -시간의 여유가 될 때 책을 조금씩 읽어야겠다.
    -블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

    -

    레벨 1을 마무리하며

    -

    시간이 빠르게 흘러갔다.
    -타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
    -또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    회고

    +

    지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
    +레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
    +부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
    +내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

    +

    아쉬운 점

    +

    문서화

    +

    개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
    +프로젝트를 진행하면서 내가 한 부분을 조금 더 꼼꼼하게, 이해하기 쉽게 문서화를 했더라면 팀원들에게 더욱 도움이 되었을 텐데 이 부분에 시간을 조금 더 투자하지 못했던 부분에서 아쉬움이 많이 들었다.
    +방학 기간 동안 문서화를 하지 못했던 부분을 개인 블로그 올리면서 조금 더 채워보려고 한다.

    +

    내가 못하는 부분이라면 시간을 들이자

    +

    잘 못하는 부분이라면 시간을 들여서라도 중간은 가도록 해야겠다는 생각이 많이 들었다.
    +말을 하기 전에 정리해서 의견을 내는 것, 발표 준비, 감정 조절 등등 +못하는 부분을 인지하고, 개선하자.

    +

    컴포트 존 벗어나기

    +

    조금 더 도전적으로 목표를 잡았으면 좋았을 것 같다.
    +매번 근거를 가지고 기술을 도입하고, 코드를 작성하려고 노력했다.
    +하지만 지속적으로 개선하려고 하는 부분이 다소 부족했다.

    +

    좋았던 점

    +

    좋았던 점도 문서화

    +

    팀 블로그도 먼저 도입하자고 제안하고, 내가 했던 부분은 문서화를 꽤 많이 해서 팀원들과 공유할 수 있었다.
    +백엔드 크루 4명이서 같이 한 부분에 대해서는 기능 구현한다고 문서화가 조금 미흡해서 보충을 해야겠다.

    +

    내가 디자인한 트립드로우 로고

    + +

    트립드로우 로고를 만들었다.
    +팀원들이 대표 색상(파란색)을 정해줬고, 주말 동안 신나게 로고 디자인을 했던 것 같다.
    +아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

    +

    기술 선택의 이유

    +

    기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
    +100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

    +

    마치며

    +

    플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
    +안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/13.html b/tags/woowahan-techcourse/page/13.html index 0e903d9b6..5314d3b23 100644 --- a/tags/woowahan-techcourse/page/13.html +++ b/tags/woowahan-techcourse/page/13.html @@ -13,83 +13,209 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    1, 2단계: https://github.com/woowacourse/java-chess/pull/441
    -3, 4단계: https://github.com/woowacourse/java-chess/pull/529

    -

    체스

    -

    체스 미션에는 가비와 페어가 매칭되었다!
    -체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
    -하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
    -미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

    -

    가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
    -최종적으로 결정한 부분은 다음과 같다.

    -

    각 기물의 이동 가능여부
    -Rank와 File은 각각 위치값을 가지고 있고, 값의 차이를 이용해서 각 기물의 이동 가능 여부를 계산했다.
    -직선 → Rank와 File 차이 중 하나가 0이어야 한다.
    -대각선 → Rank와 File 차이의 절대값이 같아야 한다. ex) abs(-2) == abs(2)
    -나이트 → 차이의 절대값이 하나는 2 나머지 하나는 1이어야 한다.

    -

    도착 칸의 기물 여부
    -아군 → 이동이 불가능하다.
    -적군 → 이동이 가능하다. 적군을 잡는다.

    -

    중간에 기물 존재 여부
    -이동 경로에 기물이 존재하면 안된다.

    -

    데이터베이스 사용
    -체스 미션은 특별하게 데이터베이스와 연결하는 부분이 있었다.
    -체스 게임의 상태를 다음의 두가지 방법으로 정할 수 있다고 생각했다.

    -
      -
    • 기물 전체를 저장하는 방법
    • -
    • 기보를 저장하고 게임을 불러와 기보대로 이동시키는 방법
    • -
    -

    기물이 이동할 때마다 값을 저장하고 싶었고, 기보를 저장하는 방법을 선택했다.
    -기물 전체를 저장하지 않은 이유는 다음과 같다.

    -
      -
    • 턴과 같은 부가적인 요소를 저장해야 한다.
    • -
    • 이동을 할 때 기물이 잡히는 경우 update 쿼리(이동 기물)와 delete(잡힌 기물) 2개의 쿼리를 날려야 한다.
    • -
    • 현재 구조에서 도메인의 변경이 크게(초기 상태를 구성하는 부분) 일어나야 한다.
    • -
    -

    정리하자면 기물 전체 저장과 기보 저장은 다음과 차이가 있다.
    -보드저장: 초기상태에서 32개의 Insert 쿼리(기물의 위치) + 기물 이동 시 움직임 변경(잡히는 경우 2개의 쿼리)
    -기보저장: 초기상태 애플리케이션에서 구성 + 저장된 기보를 select 쿼리로 조회해서 사용(1회) + insert 쿼리(이동 당 1회)

    -

    추가로 기보저장이 구현도 더욱 간단하다. 👍

    -

    부가적인 부분

    -

    리뷰어인 찰리🍫가 동시에 여러 게임이 진행된다면 어떨지? 에 대한 코멘트를 남겨주셔서 다양한 시도를 해봤다.

    -
      -
    • 누누의 도움으로 ConnectionPool 구현
    • -
    • ThreadLocal 사용해서 쓰레드 별 세션 관리
    • -
    • 실제로 애플리케이션 내에서 체스 게임이 진행되는 Board를 ConcurrentHashMap으로 저장(사실 이 부분은 현재 구조에서 필요없지만 2명이 서로 게임하는 경우를 생각해서 넣어보았다.)
    • -
    -

    두 명이 서로 같은 방에 입장하여 게임을 진행한다면 출력하는 부분이 까다로워질 것 같다고 예상되어(Board에 옵저버 패턴을 사용해야되나?) 해볼 엄두가 나지 않았다.

    -

    부족했던 부분

    -

    꼼꼼하게 코드를 작성하지 못한 부분
    -DB 관련 부분을 꼼꼼하게 코딩을 하지 못했다.
    -도메인 로직에만 집중하다보니 정적 중요한 DB의 코드의 예외처리, 빈 값을 반환 하는 부분을 꼼꼼하게 처리하지 못했다.
    -하지만 찰리의 꼼꼼한 리뷰로 DB부분과 나만의 JdbcTemplate을 깔끔하게 구현할 수 있었다.

    -

    시간에 대한 부담감
    -초반에는 여유롭지만 제출 마감에 가까워질 수록 사람이 급해지는 것 같다.
    -다음 페어프로그래밍할 땐 속도를 조절하고, 마음에 여유를 가져야겠다.

    -

    새로 학습한 부분

    -

    DAO 중복 제거

    -

    프롤로그에 을 작성했다.
    -DAO를 작성하는데 try-catch-resources와 여러 코드가 중복되서 제거하고싶었다.
    -템플릿 콜백 패턴으로 깔끔하게 중복을 제거할 수 있었다.👍

    -

    페어에게 배울 부분

    -

    페어 생각하기
    -가비는 누구보다 페어를 생각하고, 배려해주는 페어였다.
    -중간 중간 당 떨어질까봐 걱정도 해주고, 나의 컨디션도 확인해줬다!

    -

    미션 몰입하기
    -최근에 미션에 잘 몰입하지 못했다.
    -가비는 페어를 진행할 때 미션에 대한 몰입도가 매우 좋았다.
    -집에가서도 체스 이동에 대한 로직을 어떻게 구현할 지 생각한 뒤 꼼꼼해서 정리해서 나에게 보내주었다.
    -덕분에 나도 가비의 생각을 알 수 있어서 미션을 진행하는데 가속도가 붙은 것 같다.
    -또한 미션을 잘 마무리하고 싶은 마음이 전달되서 그런지 나도 덩달아 열심히 미션을 할 수 있었다.😄

    -

    솔직함
    -먼저 회고하자고 말 걸어줘서 정말 고마웠다고 표현해주는 부분
    -모르는게 있으면 솔직하게 말해주는 부분
    -나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
    -솔직함은 페어할 때 중요한 부분인 것 같다.

    -

    마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 13분

    1, 2단계: https://github.com/woowacourse/jwp-dashboard-http/pull/302
    +3, 4단계: https://github.com/woowacourse/jwp-dashboard-http/pull/431

    +

    톰캣 구현

    +

    우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
    +그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

    +

    이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
    +톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

    +

    다이어그램

    +

    Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
    +사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
    +또한 적절하게 인터페이스를 사용하여 의존성 방향을 단방향으로 하려고 노력했다.

    + +

    코드 리뷰

    +

    크루 중 한 명이 나의 리뷰어가 되고, 내가 다른 크루의 리뷰어가 되는 형태로 진행이 되었다.
    +나의 리뷰어는 디노, 리뷰이는 필립이었다.

    +

    디노(매의 눈이 아닌 공룡의 눈?)가 매우 꼼꼼하게 코드 리뷰를 해주어서 조금 더 나은 코드를 작성할 수 있었고, 필립의 코드에서는 꼼꼼하게 예외처리 하는 부분을 배울 수 있었다.
    +한 가지 아쉬운 점은 필립에게 작성한 나의 코멘트들이 미션을 진행하면서 경험 기반으로 작성한 내용이 많아 근거가 조금 부족했고, 정리되지 않은 부분이 많았던 것 같다.
    +다음 미션부터 리뷰할 때 조금 더 시간을 투자해서 더 좋은 내용을 크루들과 공유할 수 있도록 노력해야겠다.

    +

    SessionConfig

    +

    미션을 진행 중 catalina 패키지의 Session 관련 부분을 보면서 중복 로직을 개선해 볼 수 있을 것 같아 컨트리뷰트를 시도했다.
    +세션 쿠키의 이름을 가져오는 Util 클래스의 코드를 수정했는데 기본 값은 JSESSIONID 지만 설정에 따라서 세션 쿠키명을 다르게 사용할 수 있기 때문에 해당 로직이 있는 것으로 생각했다.
    +기존의 코드는 명시된 주석의 내용과 코드의 흐름이 일치하지 않아서 약간 이해하기 어려웠다.

    +

    초기에 요청했던 PR은 기존의 코드보다 전체적으로 비교 연산을 한 번 줄일 수 있었고, context가 null인 경우 바로 기본 값을 반환함으로써 성능 개선의 효과가 있을 거라고 생각했다.
    +메인테이너인 Mark Thomas 형이 해당 로직의 경우 컴파일러가 해당 부분을 최적화 할 수 있을 거라고 기대한다고 했고, 가독성을 개선시켜보라고 조언해주셨다.
    +컴파일러 최적화는 고려해보지 못한 부분인데, 앞으로 학습해야 할 부분이 산더미라고 생각했다.

    +

    남겨준 코멘트에 따라 최종적으로는 중복된 코드를 줄이는 방향으로 코드를 수정했다.
    +결과적으로 기존 로직 대비 비교 연산을 한 번 줄일 수 있었고, 명시된 주석의 내용과 유사한 흐름의 코드를 작성하여 좋은 방향으로 리팩터링을 했다고 생각한다.

    + + +
    public static String getSessionCookieName(Context context) {
    +
    +    String result = getConfiguredSessionCookieName(context);
    +
    +    if (result == null) {
    +        result = DEFAULT_SESSION_COOKIE_NAME;
    +    }
    +
    +    return result;
    +}
    +
    +public static String getSessionUriParamName(Context context) {
    +
    +    String result = getConfiguredSessionCookieName(context);
    +
    +    if (result == null) {
    +        result = DEFAULT_SESSION_PARAMETER_NAME;
    +    }
    +
    +    return result;
    +}
    +
    +private static String getConfiguredSessionCookieName(Context context) {
    +
    +    // Priority is:
    +    // 1. Cookie name defined in context
    +    // 2. Cookie name configured for app
    +    // 3. Default defined by spec
    +    if (context != null) {
    +        String cookieName = context.getSessionCookieName();
    +        if (cookieName != null && cookieName.length() > 0) {
    +            return cookieName;
    +        }
    +
    +        SessionCookieConfig scc =
    +            context.getServletContext().getSessionCookieConfig();
    +        cookieName = scc.getName();
    +        if (cookieName != null && cookieName.length() > 0) {
    +            return cookieName;
    +        }
    +    }
    +
    +    return null;
    +}
    +
    +

    HTTP 수업

    +

    미션 중간에 진행되었던 HTTP 수업에는 HTTP를 적절하게 활용하는 부분에 대해 학습했다.
    +항상 성능 개선을 위해 애플리케이션 단에서 최적화해보려고 노력을 했지만, 더 적은 시간을 투자해서 효율적으로 성능을 개선할 수 있는 방법에 대해 알 수 있었던 수업이었다.
    +HTTP 압축, HTTP 캐싱, 리소스 최적화 기법에 대해 학습했다.

    +

    스프링 부트에서는 다음 옵션을 설정하여 http의 송수신의 압축을 진행할 수 있다.

    +
    server:
    +  compression:
    +    enabled: true
    +
    +

    수업 중 해당 압축 성능이 좋다면 왜 스프링 부트에서는 기본 값으로 설정을 하지 않았는지 궁금해졌다.
    +궁금증을 해소하지 못했는데 말랑이 잡담 채널에 다음과 같은 issue를 찾아주었다.
    +내용을 요약해 보자면 WAS 별로 압축을 하기 위해 설정해야 하는 것이 다르고, 무조건 압축을 하는 것이 최적의 경우가 아닐 수 있기 때문에 기본값으로 설정하지 않는 것 같다.

    +
    +

    If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.

    +
    +

    Phil Webb 형님의 말에 따르면 일반적인 애플리케이션을 개발하는 경우 gzip 압축을 사용하는 것이 좋지만, MSA 환경 + 데이터 센터에서 사용하는 경우 오직 다른 MSA 애플리케이션과 통신하고, 고성능 네트워크가 있기 때문에 CPU 부하를 줄이는 것이 우선시 될 수도 있다는 것이었다.

    +

    이외에도 의도하지 않은 캐싱을 막기 위해 휴리스틱 캐싱을 제거하거나, 개인 정보 유출을 막기 위해 응답 헤더에 private을 설정, ETag도 학습했다.

    +

    ETag HTTP 응답 헤더는 특정 버전의 리소스를 식별하는 식별자다.
    +웹 서버가 내용을 확인하고 변하지 않았으면, 웹 서버로 full 요청을 보내지 않기 때문에, 캐시가 더 효율적이게 된다.
    +MDN

    +

    Thread 수업

    +

    스레드에 대한 수업을 들었지만, 복잡한 내용도 워낙 많았기 때문에 설명하라고 하면 잘 못할 것 같은 느낌이 든다.
    +현재 프로젝트, 미션, 테코톡 준비를 병행해야 해서 세부적인 내용은 시간 날 때 복습하려고 한다.

    +

    스레드를 이해하고, WAS에 스레드 설정 관련한 실습이 있었는데 테오와 같이 1시간 정도 페어로 Thread 실습을 진행해 보았다.
    +학습한 내용은 다음과 같다.

    +

    threads.max: Tomcat의 최대 스레드 개수
    +max-connections: Tomcat이 유지할 수 있는 최대 커넥션 개수
    +accept-count: 최대 연결 수에 도달했을 때 연결 요청에 대해 운영 체제에서 제공하는 대기열의 최대 길이. 해당 Queue에 요청이 쌓이는 것은 Tomcat이 더 이상 요청을 받을 수 없다는 뜻이다. accpet-count queue에도 요청이 가득차면 그 이후에 오는 요청은 거부된다.

    + +

    마치며

    +

    시간은 너무 빠르게 가고 할 일은 많은 것 같다.
    +우선순위를 잘 정하고 학습을 진행해야겠다.
    +현재 데이터 다루는 부분(DB)에 대한 학습이 많이 부족한 것 같다. 해당 부분은 테코톡이 끝나는대로 채워야겠다.

    +

    참고 자료

    +

    RFC 2616
    +ETag, mdn
    +Apache Tomcat 8 Configuration Reference
    +Apache Tomcat Tuning, Terry Cho
    +maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/14.html b/tags/woowahan-techcourse/page/14.html index db69153eb..950106633 100644 --- a/tags/woowahan-techcourse/page/14.html +++ b/tags/woowahan-techcourse/page/14.html @@ -13,59 +13,95 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    1단계: https://github.com/woowacourse/java-blackjack/pull/427
    -2단계: https://github.com/woowacourse/java-blackjack/pull/537

    -

    블랙잭

    -

    블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
    -이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

    -

    블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
    -후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

    -

    미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
    -"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

    -

    곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
    -중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
    -부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

    -

    이 부분에 대해 생각이 많아져서 전 리뷰어인 터틀🐢과도 대화를 나누었다.
    -터틀은 제어할 수 없는 부분보다 제어할 수 있는 부분(궁극적인 목표인 좋은 코드를 작성하는 것)에 집중해보라고 하셨다.

    -

    좋은 코드, 좋은 페어에 대한 부분을 일단 지속적으로 생각해봐야겠다.

    -

    부족했던 부분

    -

    페어 신경쓰기
    -이번 페어할 때 적극적으로 의견을 내보도록 했다. 그렇기에 너무 의견을 강하게 밀어붙인 느낌이 들어서 미안했다.
    -후추가 압박을 느꼈을 수도 있을 것 같다는 생각이 든다.
    -중간 중간 작은 회고를 진행해보는 것이 좋을까?

    -

    체력 관리
    -요즘 잘 못먹는 것 같다.
    -앞으로 살 날이 많은데 잘 챙겨먹고, 힘내야겠다.

    -

    중간 중간 돌아보기
    -이번 미션과 관련된 내용은 아니지만 우테코를 잘 활용 하고 있는지 생각을 해봐야겠다.
    -내가 우테코에 지원한 이유를 항상 잊지 않아야겠다.

    -

    새로 학습한 부분

    -

    상태 패턴
    -객체의 내부 상태에 따라 스스로 행동을 변경하도록 하는 패턴으로 if/else/switch와 같은 조건문을 효과적으로 제거할 수 있다.
    -블랙잭 미션을 진행하면서 상태 패턴에 대한 부분을 처음 적용해보았다.
    -처음 적용하기 전에는 별로라고 생각했는데, 생각보다 괜찮은 것 같다.

    -

    일관성, 가독성, 추상화
    -이번 리뷰어는 검프🍫 였다!
    -검프의 리뷰는 간결함에 관련된 내용이 많았다.
    -일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
    -읽기 좋고, 간결한 방향으로 코드를 작성하는 방법을 배운 것 같다.
    -코드를 바라보는 시점이 하나 늘어난 기분이다!(앞으로 적용하는 것은 나의 몫이지만)

    -

    페어에게 배울 부분

    -

    생각 정리
    -중간 중간 현재 상황에 대해 그림을 그리거나, 글을 적으면서 정리한다.
    -페어와 동일한 부분을 이해하고 있는지 확인한다.
    -진행하는데 매우 도움이 되었던 것 같다.
    -나도 다음 페어때부터 펜이랑 종이를 준비해야겠다.

    -

    가감없이 의견을 말해주는 부분
    -진행 상황에 대한 부분, 진행 속도, 지금 자신이 이해하고 있는 부분을 말해줘서 편했다.
    -회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

    -

    도메인 언어에 신경쓰는 부분
    -클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
    -요구사항 정리도 깔끔하게 잘하는 것 같다.

    -

    후추 최고 👍

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
    +2단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465
    +3단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580

    +

    MVC 구현

    +

    Reflection을 이용하여 Spring MVC와 유사한 기능을 구현하는 미션이었다.
    +미션의 목표는 다음과 같았다.

    +
      +
    • MVC 프레임워크를 구현하면서 내부 동작 원리를 학습한다.
    • +
    • 점진적인 리팩토링을 경험한다.
    • +
    +

    미션의 목표와 더불어 각 클래스들이 역할과 책임을 적절히 가지도록 하고, 패키지의 의존 방향을 고민하면서 미션을 진행하는 것에 중점을 두었다.

    +

    애너테이션 기반 프레임워크 만들기

    +

    기존 코드에 ManualHandlerMapping이라는 서블릿을 직접 등록해서 사용하는 HandlerMapping 클래스가 있었고, 1단계에서는 애너테이션 기반의 AnnotationHandlerMapping을 구현해야 했기 때문에 @Controller, @RequestMapping을 Reflection을 이용하여 스캔하고, 핸들러 매핑을 등록하는 부분까지 진행해야 했다.
    +테오가 @GetMapping이나 @PostMapping 부분도 진행하면 재밌을 것 같다고 해서 같이 진행해 보았다.
    +추가로 미션 요구사항은 아니었지만 클래스 레벨에 적용된 @RequestMapping도 동작하도록 구현해보았다.

    + +

    다음과 같은 Flow로 Handler(실제 요청을 처리하는 메서드) 등록을 진행한다.

    +
      +
    1. @Controller가 적용된 클래스의 정보를 스캔하여 반환한다.
    2. +
    3. @Controller가 적용된 클래스의 @RequestMapping이 적용된 메서드들의 정보를 반환한다.
    4. +
    5. 각 메서드들을 순회하며 HandlerKey(uri + httpMethod 정보)와 HandlerExecution(인스턴스 + 실행하려는 메서드)을 생성하여 Map<HandlerKey, HandlerExecution>에 추가한다.
    6. +
    +

    AnnotationHandlerMapping의 initialize 메서드에서 Handler를 등록한다. 코드는 다음과 같다.

    +
    public void initialize() {
    +    if (!initialized.compareAndSet(false, true)) {
    +        return;
    +    }
    +
    +    final Map<Class<?>, ControllerInstance> controllers = annotationScanner.scanControllers();
    +    final Set<Method> methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());
    +    for (final Method method : methods) {
    +        final ControllerInstance controller = controllers.get(method.getDeclaringClass());
    +        final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);
    +        final List<HandlerKey> handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);
    +        handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));
    +    }
    +
    +    log.info("Initialized AnnotationHandlerMapping!");
    +    handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));
    +}
    +
    +

    Legacy MVC와 @MVC 통합

    +

    2단계는 Legacy MVC와 AnnotationHandlerMapping을 통합하는 부분이었다.
    +기존의 MVC와 애너테이션이 적용된 MVC 두 개를 같이 사용할 수 있어야 헀다.
    +대략적인 흐름은 다음과 같다.

    +
      +
    1. DispatcherServlet.service(request, response) 호출
    2. +
    3. HandlerMappings를 통해 입력받은 request에 해당하는 Handler 조회
    4. +
    5. HandlerAdapters를 통해 Handler를 실행시킬 수 있는 HandlerAdapter 조회
    6. +
    7. HandlerAdapter의.handle 메서드 실행
    8. +
    9. View의 render 호출
    10. +
    + +

    웹 애플리케이션 발전 과정

    +

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    +간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.

    + +

    내용이 길어져서 다음 문서에 정리했다.

    +

    추상적인 개념 학습 방법

    +

    직관적이지 않은 추상적인 개념을 학습할 때는 개념의 구현을 참고하면 학습에 도움이 된다고 한다.

    +
    개념구현
    OOPJava
    WASTomcat, Jetty
    IoCSpring BeanFactory, Servlet Container, Framework
    DISpring BeanFactory
    +

    정리

    +

    지금까지 스프링의 DispatcherServlet의 동작을 이론적으로만 알고 있었는데, 실제로 구현해 보니 조금 더 이해가 잘 가는 것 같다.
    +이번 미션에서 나의 리뷰어는 루카, 리뷰이는 헤나였다.
    +매 단계마다 꼼꼼하게 리뷰해 준 루카에게 너무 감사하고, 헤나에게 이상한 리뷰를 많이 남긴 것 같은데 꼼꼼히 반영해줘서 감사하다.
    +오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/15.html b/tags/woowahan-techcourse/page/15.html index 3569c4856..869b3aece 100644 --- a/tags/woowahan-techcourse/page/15.html +++ b/tags/woowahan-techcourse/page/15.html @@ -13,149 +13,93 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 11분

    1단계: https://github.com/woowacourse/java-ladder/pull/97
    -2단계: https://github.com/woowacourse/java-ladder/pull/234

    -

    사다리 타기

    -

    사다리 타기 미션에서는 우가와 페어가 매칭되었다.
    -이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

    -

    우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

    -

    2단계에서는 2가지 방법으로 구현해봤다.

    -
      -
    1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
    2. -
    3. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법
    4. -
    -

    Position 기준으로 사다리 게임을 진행하는 방법

    -

    사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
    -구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
    -또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

    -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
    +2단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358
    +3단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448
    +4단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515

    +

    Jdbc 구현

    +

    이번 미션은 Jdbc 라이브러리를 구현하고, Transaction 경계 설정과 동기화하는 부분을 구현해 보는 미션이었다.
    +미션 목표는 다음과 같다.

    +
      +
    • JDBC 라이브러리를 구현하면서 중복을 제거하는 연습을 한다.
    • +
    • 데이터베이스에 대한 이해도를 높인다.
    • +
    +

    최대한 Java가 제공하는 기능을 사용하여 리팩터링 하는 방향으로 코드를 작성했다.

    +

    JdbcTemplate

    +

    JdbcTemplate은 Connection을 이용하여 PreparedStatement를 생성하는 부분, 그리고 PreparedStatement가 어떻게 동작하는지에 대한 부분을 분리했다.
    +템플릿 콜백 패턴을 적절하게 적용하여 중복을 비교적 간단하게 제거할 수 있었다.
    +예전에도 미션을 진행하면서 JdbcTemplate을 구현한 적이 있었는데, 이번에는 자원 할당과 해제 부분에 대한 중복도 제거했다.

    +
    public class JdbcTemplate {
     
    -    LadderGame --> LadderGameResult
    +    private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class);
     
    -    Items --> Item
    -    Players --> Player
    +    private final DataSource dataSource;
    +    private final StatementCreator statementCreator;
    +    private final StatementExecutor statementExecutor;
     
    -    LadderGameController --> InputView
    -    LadderGameController --> OutputView
    -">
    -
    public LadderGameResult play() {
    -    final Map<Player, Item> result = new LinkedHashMap<>();
    -    // 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
    -    for (Position position : Position.range(players.count())) {
    -        final Position resultPosition = ladder.play(position);
    -        result.put(players.get(position), items.get(resultPosition));
    +    public JdbcTemplate(final DataSource dataSource) {
    +        this(dataSource, new StatementCreator(), new StatementExecutor());
         }
    -    return new LadderGameResult(result);
    -}
    -
    -

    Player에게 Ladder를 전달하여 게임을 진행하는 방법

    -

    Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
    -이 방법이 사다리 게임을 위해서 객체들이 긴밀하게 협력하고, 조금 더 책임의 분배가 잘 되어있다고 생각이 되었다.

    - -
    public LadderGameResult play() {
    -    // 참가자들에게 사다리를 전달해서 사다리에게 메시지를 보내도록 한다.
    -    final Map<Player, Position> playResult = players.play(ladder);
    +    public <T> Optional<T> queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
    +        final List<T> results = query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
    +        if (results.size() > 1) {
    +            throw new DataAccessException("2개 이상의 결과를 반환할 수 없습니다.");
    +        }
    +        return results.stream().findAny();
    +    }
     
    -    final Map<Player, Item> result = new LinkedHashMap<>();
    -    for (Player player : playResult.keySet()) {
    -        result.put(player, toItem(playResult.get(player)));
    +    public <T> List<T> queryForList(final String sql, final RowMapper<T> rowMapper, final Object... parameters) {
    +        return query(sql, statement -> statementExecutor.execute(statement, rowMapper), parameters);
         }
    -    return new LadderGameResult(result);
     }
     
    -

    부족했던 부분

    -

    유비쿼터스 언어에 시간을 들이기
    -유비쿼터스 언어를 정하는데 시간을 조금 더 들여야겠다고 생각했다.
    -사다리 타기의 실행 결과를 Item으로 짓다니.. 뭔가 만족스럽지 않다.
    -이전 미션과 마찬가지로, 명명하는 부분에서 부족함을 많이 느꼈다.

    -

    페어와 조금 더 친해지기
    -첫날은 페어와 친해지는 시간을 조금 더 가져야겠다고 생각했다.
    -우가랑 회고할 때 내가 시작하자마자 컨벤션 정하자고 해서 많이 당황스러웠다고 한다. 우가 미안.. 🥲

    -

    README를 조금 더 꼼꼼하게
    -이상하게 코딩에 집중하면 README를 업데이트하면서 같이 커밋 하는 걸 항상 까먹는다.
    -다음 미션에는 조금 더 신경 써야겠다.

    -

    좋은 질문을 생각하기
    -첫 PR때 리뷰어에게 질문을 남기지 못했다.
    -리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

    -

    PR 후에도 꼼꼼하게 확인하기
    -분명 알고 있는 부분이지만, 놓친 부분이 많은 것 같았다.
    -PR 하기 전에도 계속 확인을 했지만, 아무래도 IntelliJ에서 보니 코드에 익숙해져서 그런지 변경해야 할 부분이 잘 안보였다.
    -github pr에서는 전체 변경사항을 확인할 수 있으니 PR 후에도 꼭 확인해야겠다.

    -

    적극적으로 나의 의견을 말하기
    -의견을 적극적으로 내는 부분에 대해서 페어의 의견이 괜찮다고 생각하면 수용 후 개선을 하는 방향으로 진행을 했었는데, 조금 더 개선할 수 있는 방향이 있다면 나도 적극적으로 의견을 말해야겠다고 생각이 든다.
    -나도 설득하는 힘을 기르고, 페어도 좋은 방향을 알 수 있고, 결과물도 좋은 방향으로 나오지 않을까? (고민 들어주신 리뷰어 터틀🐢 감사합니다.)

    -

    새로 학습한 부분

    -

    객체의 생성 책임
    -Players가 Position을 생성하고 Player의 생성자에 넣어주었다. 하지만 이 부분에 대해서 생성 책임에 관련된 코멘트가 달렸다. -시간을 가지고 생각해 보니 Position을 가지고 있는 건 Player기 때문에 생성 책임을 Player가 담당하는 것이 좋다고 생각되었다.

    -

    생성 책임에 관한 패턴으로 GRASP의 Creator 패턴이 있는데 다음의 요소를 최대한 만족하는 클래스에 생성 책임을 할당하는 것이 좋다.

    -
      -
    • B가 A 객체를 포함 또는 참조한다.
    • -
    • B가 A 객체를 기록한다.
    • -
    • B가 A를 긴밀하게 사용한다.
    • -
    • B가 A의 초깃값을 가지고 있다.
    • -
    -

    실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

    -

    패키지 분리 기준
    -패키지 분리에 대한 나만의 기준이 아직 명확하지 않아 질문이 들어와도 명확하게 답변을 하지 못했다.
    -마지막 제출 전에 도메인 패키지 내부를 분리해 봤는데, 기준이 명확하지 않았기 때문에 좋지 않은 선택이었던 것 같다. -현재 진행하는 미션의 애플리케이션 크기가 그렇게 크지 않으니, domain 패키지에서 세부 패키지로 분리하지 않아도 될 것 같다.

    -

    사용하는 쪽에서 생각하기 & 예측가능한 코드 작성하기
    -Position에서 다음 위치나 이전 위치를 반환하는 메서드를 허용 범위(019)가 벗어난다면, 의미 없는 값이 들어간 Position을 반환하도록 했다.
    -이건 Position을 사용하는 입장을 고려하지 못한 코딩이었는데, 사용하는 입장에서는 0
    19의 값이 보장되어 있다고 생각할 것이기 때문이다.
    -따라서 hasNext, hasPrevious라는 이전 값, 이후 값이 범위 내에 있는지 확인하는 메서드를 추가하고, 기존의 값을 가져오는 메서드는 범위가 벗어나면 예외를 던지는 방향으로 해결하였다.

    -

    페어에게 배울 부분

    -

    밝은 기운을 가지고 있고 다른 사람들과 친화력이 좋은 것 같았다.
    -이번에 페어 할 때 컨디션 관리를 제대로 못해서 많이 미안했다. 다음에는 최상의 컨디션으로 페어를 준비해 봐야겠다.
    -그리고 우가랑 페어를 하고 나서, 나도 다른 사람들과 더 잘 지내봐야겠다는 생각이 들어 조금 더 용기를 내 잡담 중이다!

    -

    의견을 적극적으로 내줘서 페어프로그래밍 진행이 잘 되었다.
    -또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
    -페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

    -

    항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
    -웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

    +

    트랜잭션 적용

    +

    3, 4단계는 기존의 코드에 트랜잭션을 시작하고 끝나는 부분인 트랜잭션 경계를 설정하고 ThreadLocal을 이용하여 트랜잭션 동기화(Transaction synchronization)를 적용하는 미션이었다.
    +트랜잭션 동기화란 트랜잭션을 시작하기 위한 Connection 객체를 ThreadLocal과 같은 공간에 따로 저장 후, 필요할 때 저장된 Connection을 가져다 사용하는 방식이다.
    +아래와 같은 구조로 미션을 진행했는데, ThreadLocal에 Connection 객체가 아닌, Connection 객체와 Transaction이 진행 중인지 확인할 수 있는 flag를 가지고 있는 클래스를 저장해서 사용하도록 했다.

    + +

    마무리

    +

    Jdbc 미션을 진행하면서 AOP나 Transactional에 대한 학습 테스트도 진행하고, 약간 알찬 미션이었던 것 같다.
    +꼼꼼히 코드를 봐준 리뷰어 호이 그리고 연휴 동안 계속 티키타카 하면서 재밌게 리뷰한 민트에게 감사하다.
    +회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/16.html b/tags/woowahan-techcourse/page/16.html index ef5704944..230c070eb 100644 --- a/tags/woowahan-techcourse/page/16.html +++ b/tags/woowahan-techcourse/page/16.html @@ -13,89 +13,65 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    1단계: https://github.com/woowacourse/java-racingcar/pull/510
    -2단계: https://github.com/woowacourse/java-racingcar/pull/538

    -

    자동차 경주

    -

    자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
    -우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

    -

    첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
    -시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

    -

    시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
    -mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

    -
      -
    • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
    • -
    • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.
    • -
    - -

    미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

    -

    페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
    -리팩터링을 어떻게 했는지? 이런 리뷰에 대해 어떻게 생각하는지 깊게 고민하는 시간을 가질 수 있었다.

    -

    부족했던 부분

    -

    리팩터링이 끝난 후 메서드명, 테스트시 출력하는 메시지에 대한 코멘트가 많이 달렸다.
    -객체가 어떤 책임과 역할을 가지는지 생각하는 시간을 가지고 명확한 메서드명을 작성해야겠다고 생각했다.

    -

    평소에 프로그래밍 이야기가 아닌 다른 주제로 이야기하면 잘 들으려고 하는 편이지만
    -내가 좋아하는 주제, 관심가는 주제인 프로그래밍에 대한 이야기를 할 땐 말이 많아진다.
    -다음 미션부터는 더 많은 시간을 페어의 의견과 이야기를 듣는 곳에 사용해야겠다.

    -

    새로 학습한 부분

    -

    Assertions extracting

    -

    결과 내부에 있는 값을 확인하고 싶을 때 extracting 키워드를 이용해서 내부의 값을 검증할 수 있다.
    -이전에는 필요에 따라 stream을 이용하여 검증할 값을 생성했지만, 해당 방법을 이용해서 절차를 줄일 수 있었다.

    -
    @Test
    -void extracting() {
    -    final Cars cars = new Cars(List.of("car1", "car2"));
    -
    -    assertThat(cars.getCars())
    -            .extracting(Car::getName)
    -            .containsExactly("car1", "car2");
    -}
    -
    -
    -

    아래는 리뷰어님과 대화를 나누면서 얻은 답변 + 나의 의견이다.

    -

    제어할 수 없는 부분에 대한 테스트

    -

    테스트 대상이 검증된 것이라면 작성하지 않거나, 제어할 수 있는 부분에 대한 테스트를 더욱 꼼꼼하게 작성한다.
    -이건 개인적인 생각이지만 내가 안정감이 들 수 있을 정도로 출력 범위 내의 결과를 반환하는지 정도 테스트할 수 있지 않을까?

    -

    단순 위임을 하는 메서드에 대한 테스트

    -

    위임이라는 것은 역할과 책임을 넘겨준다는 것이다.
    -호출 횟수를 검증하는 것보다 결과에 대한 테스트하는 것이 좋다.
    -단순히 위임만 하는 테스트의 경우 결과를 검증한다면 테스트가 중복되지 않을까 생각했었다.
    -따라서 중복된 테스트를 줄이기 위해 내부의 메서드를 호출하는지 검증하는 방법도 있다는 것을 알게 되었지만
    -안정적으로 결과를 테스트 하는 것이 더 좋은 방법인 것 같다.

    -

    테스트를 위한 getter 사용

    -

    테스트 용도로 도메인에 새로운 메서드가 생성되는 것은 좋지 못하다.
    -필요의 경우 생성해서 사용할 수 있지만, 기존에 있는 메서드들을 활용해보는 것이 더 좋은 방법이다.
    -이 부분에 대해서 매우 동의하고, 앞으로도 최대한 테스트를 위한 코드를 도메인에 작성하지 않을 것 같다.

    -

    페어에게 배울 부분

    -

    질문이나 생각할 점이 있을 때 매우 깊게 고민하는 것 같았다.
    -생각을 정리한 후 자신의 의견을 명료하게 전달해주었다.
    -그렇기 때문에 지식을 효율적으로 습득한다.
    -난 생각을 잘 정리하지 않은 채로 내버려 둔 얕은 지식이 많은 것 같다. (이런 것도 아는 것이라고 할 수 있을까?)
    -앞으로 조금 더 머릿속에서 정리하고, 문제에 대해 깊게 고민하는 시간을 늘려야겠다.

    -

    개발에 열정을 가진 게 느껴진다.
    -나도 개발을 좋아하지만, 최근에는 의지가 약해졌었다.
    -열정이 가득한 사람을 만나니 나도 열정적인 사람이 되는 것 같다.

    -

    칭찬을 많이 해준다. 단순히 많이 해주는 것이 아니라, 진심을 담긴 칭찬을 해줬다.
    -칭찬은 고래도 춤추게 하던가?
    -그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

    -

    어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
    -이건 바로 배울 수 없지만.
    -나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 9분

    1단계: https://github.com/woowacourse/jwp-refactoring/pull/465
    +2단계: https://github.com/woowacourse/jwp-refactoring/pull/547
    +3단계: https://github.com/woowacourse/jwp-refactoring/pull/610
    +4단계: https://github.com/woowacourse/jwp-refactoring/pull/721

    +

    리팩터링 미션

    +

    요구사항 작성 → 테스트를 통한 코드 보호 → 리팩터링 → 의존성 리팩터링 → 멀티모듈 순서로 미션을 진행했다.
    +미션에 온전히 집중하고 싶었지만, 프로젝트와 병행하면서 진행했기에 어느정도 타협보고 진행한 부분이 많아서 아쉬웠다.

    +

    1, 2단계

    +

    1단계는 요구사항을 작성하고, 테스트 코드를 작성하여 추후에 리팩터링 할 때 안정감 있게 진행할 수 있도록 준비하는 과정이었다. +요구사항을 작성할 때 제공된 용어 사전을 최대한 활용하면서 기존의 코드를 보면서 요구사항을 정리했다. +테스트는 시간 관계상 API, 서비스 둘 중 하나만 통합 테스트를 진행해야겠다는 생각이 들었다.

    +

    최종적으로 서비스 기준으로 통합 테스트를 작성했는데 약간 후회되는 결정이었던 것 같다.
    +리팩터링 과정에서 API 명세가 바뀌지 않아야 한다는 것을 기준을 잡고 이번 미션을 한다고 가정했을 때 API 기준으로 테스트를 작성하고, 리팩터링을 진행하는 것이 더 안정감 있다고 생각한다.

    +

    2단계는 작성된 테스트 기반으로 리팩터링 하는 미션이었다.
    +서비스에서 도메인을 직접 반환하는 구조였는데, 도메인에 JPA를 적용하면 기존 명세와 달라질 것을 우려해서 DTO로 수정하는 작업을 먼저 진행했다. +DTO 이후에 서비스에 있는 로직을 도메인으로 이동시키고, 최종적으로 JPA를 적용하는 순서로 리팩터링을 진행했다. +이 과정에서 의존성 방향이 양방향인 부분도 생겨났다.

    +

    소프트웨어의 복잡성을 다루는 지혜

    +

    중간에 소프트웨어 복잡성을 다루는 지혜에 관한 제이슨의 강의가 있었다.
    +소프트웨어의 복잡성을 다루는 지혜는 에릭 에반스의 저서 도메인 주도 설계의 부제이다.

    +

    도메인 주도 설계는 유비쿼터스 언어, 전략적 설계, 전술적 설계가 중요하다고 한다.
    +유비쿼터스 언어, 전략적 설계가 전체의 90%에 해당할 정도로 중요하다고 한다. 또한 전술적 설계만 하는 경우를 DDD Lite 라고 한다.

    +

    간단히 도메인 주도 설계에서 나오는 단어를 정리한다면 다음과 같다.

    +
    단어설명
    도메인소프트웨어로 해결하고자 하는 문제 영역
    바운디드 컨텍스트해결 영역, 관심사를 분리하고 격리하여 문제 해결에 집중할 범위
    유비쿼터스 언어프로젝트에 이해관계자들의 공통된 언어로, 서로의 의사소통 비용을 줄이기 위해 사용하는 언어
    전략적 설계도메인 전문가와 개발자가 함께 유비쿼터스 언어를 이용하여 도메인과 관련된 지식을 이해하고 이를 바탕으로 경계를 나눠 바운디드 컨텍스트를 정의하고, 컨텍스트 맵을 생성하는 것을 포함하는 과정
    전술적 설계전략적 설계에서 정의한 바운디드 컨텍스트와 도메인을 이용하여 애그리거트, Entity와 VO, Repository 등을 구현하는 과정
    +

    이 외에도 다양한 내용들이 나왔지만, 지식을 제대로 흡수하지는 못했다.

    +

    3, 4단계

    +

    제이슨의 강의를 듣고, 조영호님의 우아한객체지향 유튜브 영상을 본 다음 3, 4단계를 진행했다.

    +

    3단계는 의존성 리팩터링에 관한 내용이었다. 클래스 간 방향, 패키지 간 방향을 단방향이 되도록 리팩터링을 진행해야 했었다. +함께 생성되고 삭제되는 객체들을 묶고, 결합도를 낮추기 위해 생명주기가 다르다면 id를 이용하여 참조하도록 변경했다.

    +

    의존성을 분리하기 위해 이벤트도 사용해보았다. 이벤트는 현재 기준으로 과거에 벌어진 것을 표현하기 때문에 이벤트명은 과거 시제가 되어야하는 것을 알았다. +처음에는 애플리케이션 이벤트를 사용했지만, 서비스 로직을 최대한 간단하게 하기 위해 도메인 이벤트도 사용해보았다.

    +

    4단계는 멀티모듈로 분리하는 미션이었는데 3단계에서 분리해둔 패키지 그대로 분리하지는 않았다.
    +3단계에서는 함께 생성되고 삭제되는 객체 기준으로 분리했다. 4단계에서는 내가 인식하기 편한 기준으로 분리를 했다. +아직 분리한 기준에 대한 근거가 모호했고, 이에 대한 공부를 조금 더 해야겠다고 생각했다.

    + +

    추가로 테스트 격리를 위한 직접 작성한 @ServiceTest 커스텀 애너테이션이 있었는데, 상위 모듈의 테스트에서 만든 클래스를 하위 모듈에서는 사용할 수 없었다. +따라서 TestFixtures를 사용하여 해결했다.

    +

    마무리

    +

    우아한테크코스의 마지막 미션이니 만큼, 가장 흥미로운 미션이었고 배울점도 많았던 것 같다.
    +바쁜 기간이라 많은 리뷰를 남기지 못했던 리뷰이 호이에게 미안하고, 코멘트 꼼꼼하게 달아주고 미션에 대한 이야기도 오프라인으로 많이 나눈 리뷰어 테오에게 너무 감사하다.

    +

    참고 자료

    +

    도메인 원정대, 우아콘 2021
    +우아한객체지향, 우아한테크세미나
    +TestFixtures, 권남님

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/2.html b/tags/woowahan-techcourse/page/2.html index edac3798c..48138548b 100644 --- a/tags/woowahan-techcourse/page/2.html +++ b/tags/woowahan-techcourse/page/2.html @@ -13,93 +13,149 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/267
    -2단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/358
    -3단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/448
    -4단계: https://github.com/woowacourse/jwp-dashboard-jdbc/pull/515

    -

    Jdbc 구현

    -

    이번 미션은 Jdbc 라이브러리를 구현하고, Transaction 경계 설정과 동기화하는 부분을 구현해 보는 미션이었다.
    -미션 목표는 다음과 같다.

    -
      -
    • JDBC 라이브러리를 구현하면서 중복을 제거하는 연습을 한다.
    • -
    • 데이터베이스에 대한 이해도를 높인다.
    • -
    -

    최대한 Java가 제공하는 기능을 사용하여 리팩터링 하는 방향으로 코드를 작성했다.

    -

    JdbcTemplate

    -

    JdbcTemplate은 Connection을 이용하여 PreparedStatement를 생성하는 부분, 그리고 PreparedStatement가 어떻게 동작하는지에 대한 부분을 분리했다.
    -템플릿 콜백 패턴을 적절하게 적용하여 중복을 비교적 간단하게 제거할 수 있었다.
    -예전에도 미션을 진행하면서 JdbcTemplate을 구현한 적이 있었는데, 이번에는 자원 할당과 해제 부분에 대한 중복도 제거했다.

    -
    public class JdbcTemplate {
    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 11분

    1단계: https://github.com/woowacourse/java-ladder/pull/97
    +2단계: https://github.com/woowacourse/java-ladder/pull/234

    +

    사다리 타기

    +

    사다리 타기 미션에서는 우가와 페어가 매칭되었다.
    +이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

    +

    우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

    +

    2단계에서는 2가지 방법으로 구현해봤다.

    +
      +
    1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
    2. +
    3. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법
    4. +
    +

    Position 기준으로 사다리 게임을 진행하는 방법

    +

    사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
    +구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
    +또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

    + +
    public LadderGameResult play() {
    +    final Map<Player, Item> result = new LinkedHashMap<>();
    +    // 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
    +    for (Position position : Position.range(players.count())) {
    +        final Position resultPosition = ladder.play(position);
    +        result.put(players.get(position), items.get(resultPosition));
         }
    +    return new LadderGameResult(result);
    +}
    +
    +

    Player에게 Ladder를 전달하여 게임을 진행하는 방법

    +

    Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
    +이 방법이 사다리 게임을 위해서 객체들이 긴밀하게 협력하고, 조금 더 책임의 분배가 잘 되어있다고 생각이 되었다.

    + +
    public LadderGameResult play() {
    +    // 참가자들에게 사다리를 전달해서 사다리에게 메시지를 보내도록 한다.
    +    final Map<Player, Position> playResult = players.play(ladder);
    +
    +    final Map<Player, Item> result = new LinkedHashMap<>();
    +    for (Player player : playResult.keySet()) {
    +        result.put(player, toItem(playResult.get(player)));
         }
    +    return new LadderGameResult(result);
     }
     
    -

    트랜잭션 적용

    -

    3, 4단계는 기존의 코드에 트랜잭션을 시작하고 끝나는 부분인 트랜잭션 경계를 설정하고 ThreadLocal을 이용하여 트랜잭션 동기화(Transaction synchronization)를 적용하는 미션이었다.
    -트랜잭션 동기화란 트랜잭션을 시작하기 위한 Connection 객체를 ThreadLocal과 같은 공간에 따로 저장 후, 필요할 때 저장된 Connection을 가져다 사용하는 방식이다.
    -아래와 같은 구조로 미션을 진행했는데, ThreadLocal에 Connection 객체가 아닌, Connection 객체와 Transaction이 진행 중인지 확인할 수 있는 flag를 가지고 있는 클래스를 저장해서 사용하도록 했다.

    - -

    마무리

    -

    Jdbc 미션을 진행하면서 AOP나 Transactional에 대한 학습 테스트도 진행하고, 약간 알찬 미션이었던 것 같다.
    -꼼꼼히 코드를 봐준 리뷰어 호이 그리고 연휴 동안 계속 티키타카 하면서 재밌게 리뷰한 민트에게 감사하다.
    -회고 이만 끝내고 리팩터링 미션 하러가야겠다. 😊

    +

    부족했던 부분

    +

    유비쿼터스 언어에 시간을 들이기
    +유비쿼터스 언어를 정하는데 시간을 조금 더 들여야겠다고 생각했다.
    +사다리 타기의 실행 결과를 Item으로 짓다니.. 뭔가 만족스럽지 않다.
    +이전 미션과 마찬가지로, 명명하는 부분에서 부족함을 많이 느꼈다.

    +

    페어와 조금 더 친해지기
    +첫날은 페어와 친해지는 시간을 조금 더 가져야겠다고 생각했다.
    +우가랑 회고할 때 내가 시작하자마자 컨벤션 정하자고 해서 많이 당황스러웠다고 한다. 우가 미안.. 🥲

    +

    README를 조금 더 꼼꼼하게
    +이상하게 코딩에 집중하면 README를 업데이트하면서 같이 커밋 하는 걸 항상 까먹는다.
    +다음 미션에는 조금 더 신경 써야겠다.

    +

    좋은 질문을 생각하기
    +첫 PR때 리뷰어에게 질문을 남기지 못했다.
    +리뷰어와의 시간이 소중한 시간이라는 것을 까먹지 말고, 나의 성장에 도움이 될 수 있는 질문을 생각해야겠다.

    +

    PR 후에도 꼼꼼하게 확인하기
    +분명 알고 있는 부분이지만, 놓친 부분이 많은 것 같았다.
    +PR 하기 전에도 계속 확인을 했지만, 아무래도 IntelliJ에서 보니 코드에 익숙해져서 그런지 변경해야 할 부분이 잘 안보였다.
    +github pr에서는 전체 변경사항을 확인할 수 있으니 PR 후에도 꼭 확인해야겠다.

    +

    적극적으로 나의 의견을 말하기
    +의견을 적극적으로 내는 부분에 대해서 페어의 의견이 괜찮다고 생각하면 수용 후 개선을 하는 방향으로 진행을 했었는데, 조금 더 개선할 수 있는 방향이 있다면 나도 적극적으로 의견을 말해야겠다고 생각이 든다.
    +나도 설득하는 힘을 기르고, 페어도 좋은 방향을 알 수 있고, 결과물도 좋은 방향으로 나오지 않을까? (고민 들어주신 리뷰어 터틀🐢 감사합니다.)

    +

    새로 학습한 부분

    +

    객체의 생성 책임
    +Players가 Position을 생성하고 Player의 생성자에 넣어주었다. 하지만 이 부분에 대해서 생성 책임에 관련된 코멘트가 달렸다. +시간을 가지고 생각해 보니 Position을 가지고 있는 건 Player기 때문에 생성 책임을 Player가 담당하는 것이 좋다고 생각되었다.

    +

    생성 책임에 관한 패턴으로 GRASP의 Creator 패턴이 있는데 다음의 요소를 최대한 만족하는 클래스에 생성 책임을 할당하는 것이 좋다.

    +
      +
    • B가 A 객체를 포함 또는 참조한다.
    • +
    • B가 A 객체를 기록한다.
    • +
    • B가 A를 긴밀하게 사용한다.
    • +
    • B가 A의 초깃값을 가지고 있다.
    • +
    +

    실제로 객체의 생성 책임에 관해서 깊이 생각하면서 코딩을 하지 않았는데, 이번 미션을 통해 시야가 넓어진 것 같다.

    +

    패키지 분리 기준
    +패키지 분리에 대한 나만의 기준이 아직 명확하지 않아 질문이 들어와도 명확하게 답변을 하지 못했다.
    +마지막 제출 전에 도메인 패키지 내부를 분리해 봤는데, 기준이 명확하지 않았기 때문에 좋지 않은 선택이었던 것 같다. +현재 진행하는 미션의 애플리케이션 크기가 그렇게 크지 않으니, domain 패키지에서 세부 패키지로 분리하지 않아도 될 것 같다.

    +

    사용하는 쪽에서 생각하기 & 예측가능한 코드 작성하기
    +Position에서 다음 위치나 이전 위치를 반환하는 메서드를 허용 범위(019)가 벗어난다면, 의미 없는 값이 들어간 Position을 반환하도록 했다.
    +이건 Position을 사용하는 입장을 고려하지 못한 코딩이었는데, 사용하는 입장에서는 0
    19의 값이 보장되어 있다고 생각할 것이기 때문이다.
    +따라서 hasNext, hasPrevious라는 이전 값, 이후 값이 범위 내에 있는지 확인하는 메서드를 추가하고, 기존의 값을 가져오는 메서드는 범위가 벗어나면 예외를 던지는 방향으로 해결하였다.

    +

    페어에게 배울 부분

    +

    밝은 기운을 가지고 있고 다른 사람들과 친화력이 좋은 것 같았다.
    +이번에 페어 할 때 컨디션 관리를 제대로 못해서 많이 미안했다. 다음에는 최상의 컨디션으로 페어를 준비해 봐야겠다.
    +그리고 우가랑 페어를 하고 나서, 나도 다른 사람들과 더 잘 지내봐야겠다는 생각이 들어 조금 더 용기를 내 잡담 중이다!

    +

    의견을 적극적으로 내줘서 페어프로그래밍 진행이 잘 되었다.
    +또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
    +페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

    +

    항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
    +웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/3.html b/tags/woowahan-techcourse/page/3.html index 94f50385b..ff20f7ab7 100644 --- a/tags/woowahan-techcourse/page/3.html +++ b/tags/woowahan-techcourse/page/3.html @@ -13,95 +13,59 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    1단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/404
    -2단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/465
    -3단계: https://github.com/woowacourse/jwp-dashboard-mvc/pull/580

    -

    MVC 구현

    -

    Reflection을 이용하여 Spring MVC와 유사한 기능을 구현하는 미션이었다.
    -미션의 목표는 다음과 같았다.

    -
      -
    • MVC 프레임워크를 구현하면서 내부 동작 원리를 학습한다.
    • -
    • 점진적인 리팩토링을 경험한다.
    • -
    -

    미션의 목표와 더불어 각 클래스들이 역할과 책임을 적절히 가지도록 하고, 패키지의 의존 방향을 고민하면서 미션을 진행하는 것에 중점을 두었다.

    -

    애너테이션 기반 프레임워크 만들기

    -

    기존 코드에 ManualHandlerMapping이라는 서블릿을 직접 등록해서 사용하는 HandlerMapping 클래스가 있었고, 1단계에서는 애너테이션 기반의 AnnotationHandlerMapping을 구현해야 했기 때문에 @Controller, @RequestMapping을 Reflection을 이용하여 스캔하고, 핸들러 매핑을 등록하는 부분까지 진행해야 했다.
    -테오가 @GetMapping이나 @PostMapping 부분도 진행하면 재밌을 것 같다고 해서 같이 진행해 보았다.
    -추가로 미션 요구사항은 아니었지만 클래스 레벨에 적용된 @RequestMapping도 동작하도록 구현해보았다.

    - -

    다음과 같은 Flow로 Handler(실제 요청을 처리하는 메서드) 등록을 진행한다.

    -
      -
    1. @Controller가 적용된 클래스의 정보를 스캔하여 반환한다.
    2. -
    3. @Controller가 적용된 클래스의 @RequestMapping이 적용된 메서드들의 정보를 반환한다.
    4. -
    5. 각 메서드들을 순회하며 HandlerKey(uri + httpMethod 정보)와 HandlerExecution(인스턴스 + 실행하려는 메서드)을 생성하여 Map<HandlerKey, HandlerExecution>에 추가한다.
    6. -
    -

    AnnotationHandlerMapping의 initialize 메서드에서 Handler를 등록한다. 코드는 다음과 같다.

    -
    public void initialize() {
    -    if (!initialized.compareAndSet(false, true)) {
    -        return;
    -    }
    -
    -    final Map<Class<?>, ControllerInstance> controllers = annotationScanner.scanControllers();
    -    final Set<Method> methods = annotationScanner.scanHttpMappingMethods(controllers.keySet());
    -    for (final Method method : methods) {
    -        final ControllerInstance controller = controllers.get(method.getDeclaringClass());
    -        final HandlerExecution handlerExecution = new HandlerExecution(controller.getInstance(), method);
    -        final List<HandlerKey> handlerKeys = handlerKeyGenerator.generate(controller.getUriPrefix(), method);
    -        handlerKeys.forEach(handlerKey -> handlerExecutions.put(handlerKey, handlerExecution));
    -    }
    -
    -    log.info("Initialized AnnotationHandlerMapping!");
    -    handlerExecutions.keySet().forEach(key -> log.info("key: {}, Handler: {}", key, handlerExecutions.get(key)));
    -}
    -
    -

    Legacy MVC와 @MVC 통합

    -

    2단계는 Legacy MVC와 AnnotationHandlerMapping을 통합하는 부분이었다.
    -기존의 MVC와 애너테이션이 적용된 MVC 두 개를 같이 사용할 수 있어야 헀다.
    -대략적인 흐름은 다음과 같다.

    -
      -
    1. DispatcherServlet.service(request, response) 호출
    2. -
    3. HandlerMappings를 통해 입력받은 request에 해당하는 Handler 조회
    4. -
    5. HandlerAdapters를 통해 Handler를 실행시킬 수 있는 HandlerAdapter 조회
    6. -
    7. HandlerAdapter의.handle 메서드 실행
    8. -
    9. View의 render 호출
    10. -
    - -

    웹 애플리케이션 발전 과정

    -

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    -간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.

    - -

    내용이 길어져서 다음 문서에 정리했다.

    -

    추상적인 개념 학습 방법

    -

    직관적이지 않은 추상적인 개념을 학습할 때는 개념의 구현을 참고하면 학습에 도움이 된다고 한다.

    -
    개념구현
    OOPJava
    WASTomcat, Jetty
    IoCSpring BeanFactory, Servlet Container, Framework
    DISpring BeanFactory
    -

    정리

    -

    지금까지 스프링의 DispatcherServlet의 동작을 이론적으로만 알고 있었는데, 실제로 구현해 보니 조금 더 이해가 잘 가는 것 같다.
    -이번 미션에서 나의 리뷰어는 루카, 리뷰이는 헤나였다.
    -매 단계마다 꼼꼼하게 리뷰해 준 루카에게 너무 감사하고, 헤나에게 이상한 리뷰를 많이 남긴 것 같은데 꼼꼼히 반영해줘서 감사하다.
    -오랫동안 기다려왔던 레벨 4 미션이 하나씩 마무리 될 때 마다 아쉬움이 남는다.

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 6분

    1단계: https://github.com/woowacourse/java-blackjack/pull/427
    +2단계: https://github.com/woowacourse/java-blackjack/pull/537

    +

    블랙잭

    +

    블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
    +이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

    +

    블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
    +후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

    +

    미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
    +"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

    +

    곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
    +중간 중간 회고를 하고, 나의 소프트스킬을 높히는게 답일까?
    +부담감을 느끼지 않고 같이 일하고 싶은 사람이 될 수 있도록 계속 생각해봐야겠다.

    +

    이 부분에 대해 생각이 많아져서 전 리뷰어인 터틀🐢과도 대화를 나누었다.
    +터틀은 제어할 수 없는 부분보다 제어할 수 있는 부분(궁극적인 목표인 좋은 코드를 작성하는 것)에 집중해보라고 하셨다.

    +

    좋은 코드, 좋은 페어에 대한 부분을 일단 지속적으로 생각해봐야겠다.

    +

    부족했던 부분

    +

    페어 신경쓰기
    +이번 페어할 때 적극적으로 의견을 내보도록 했다. 그렇기에 너무 의견을 강하게 밀어붙인 느낌이 들어서 미안했다.
    +후추가 압박을 느꼈을 수도 있을 것 같다는 생각이 든다.
    +중간 중간 작은 회고를 진행해보는 것이 좋을까?

    +

    체력 관리
    +요즘 잘 못먹는 것 같다.
    +앞으로 살 날이 많은데 잘 챙겨먹고, 힘내야겠다.

    +

    중간 중간 돌아보기
    +이번 미션과 관련된 내용은 아니지만 우테코를 잘 활용 하고 있는지 생각을 해봐야겠다.
    +내가 우테코에 지원한 이유를 항상 잊지 않아야겠다.

    +

    새로 학습한 부분

    +

    상태 패턴
    +객체의 내부 상태에 따라 스스로 행동을 변경하도록 하는 패턴으로 if/else/switch와 같은 조건문을 효과적으로 제거할 수 있다.
    +블랙잭 미션을 진행하면서 상태 패턴에 대한 부분을 처음 적용해보았다.
    +처음 적용하기 전에는 별로라고 생각했는데, 생각보다 괜찮은 것 같다.

    +

    일관성, 가독성, 추상화
    +이번 리뷰어는 검프🍫 였다!
    +검프의 리뷰는 간결함에 관련된 내용이 많았다.
    +일관성이 있는 코드, 가독성이 좋은 코드, 추상화가 잘 되어있는 코드
    +읽기 좋고, 간결한 방향으로 코드를 작성하는 방법을 배운 것 같다.
    +코드를 바라보는 시점이 하나 늘어난 기분이다!(앞으로 적용하는 것은 나의 몫이지만)

    +

    페어에게 배울 부분

    +

    생각 정리
    +중간 중간 현재 상황에 대해 그림을 그리거나, 글을 적으면서 정리한다.
    +페어와 동일한 부분을 이해하고 있는지 확인한다.
    +진행하는데 매우 도움이 되었던 것 같다.
    +나도 다음 페어때부터 펜이랑 종이를 준비해야겠다.

    +

    가감없이 의견을 말해주는 부분
    +진행 상황에 대한 부분, 진행 속도, 지금 자신이 이해하고 있는 부분을 말해줘서 편했다.
    +회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

    +

    도메인 언어에 신경쓰는 부분
    +클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
    +요구사항 정리도 깔끔하게 잘하는 것 같다.

    +

    후추 최고 👍

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/4.html b/tags/woowahan-techcourse/page/4.html index 78413c386..f3c98f34e 100644 --- a/tags/woowahan-techcourse/page/4.html +++ b/tags/woowahan-techcourse/page/4.html @@ -13,209 +13,83 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 13분

    1, 2단계: https://github.com/woowacourse/jwp-dashboard-http/pull/302
    -3, 4단계: https://github.com/woowacourse/jwp-dashboard-http/pull/431

    -

    톰캣 구현

    -

    우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
    -그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

    -

    이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
    -톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

    -

    다이어그램

    -

    Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
    -사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
    -또한 적절하게 인터페이스를 사용하여 의존성 방향을 단방향으로 하려고 노력했다.

    - -

    코드 리뷰

    -

    크루 중 한 명이 나의 리뷰어가 되고, 내가 다른 크루의 리뷰어가 되는 형태로 진행이 되었다.
    -나의 리뷰어는 디노, 리뷰이는 필립이었다.

    -

    디노(매의 눈이 아닌 공룡의 눈?)가 매우 꼼꼼하게 코드 리뷰를 해주어서 조금 더 나은 코드를 작성할 수 있었고, 필립의 코드에서는 꼼꼼하게 예외처리 하는 부분을 배울 수 있었다.
    -한 가지 아쉬운 점은 필립에게 작성한 나의 코멘트들이 미션을 진행하면서 경험 기반으로 작성한 내용이 많아 근거가 조금 부족했고, 정리되지 않은 부분이 많았던 것 같다.
    -다음 미션부터 리뷰할 때 조금 더 시간을 투자해서 더 좋은 내용을 크루들과 공유할 수 있도록 노력해야겠다.

    -

    SessionConfig

    -

    미션을 진행 중 catalina 패키지의 Session 관련 부분을 보면서 중복 로직을 개선해 볼 수 있을 것 같아 컨트리뷰트를 시도했다.
    -세션 쿠키의 이름을 가져오는 Util 클래스의 코드를 수정했는데 기본 값은 JSESSIONID 지만 설정에 따라서 세션 쿠키명을 다르게 사용할 수 있기 때문에 해당 로직이 있는 것으로 생각했다.
    -기존의 코드는 명시된 주석의 내용과 코드의 흐름이 일치하지 않아서 약간 이해하기 어려웠다.

    -

    초기에 요청했던 PR은 기존의 코드보다 전체적으로 비교 연산을 한 번 줄일 수 있었고, context가 null인 경우 바로 기본 값을 반환함으로써 성능 개선의 효과가 있을 거라고 생각했다.
    -메인테이너인 Mark Thomas 형이 해당 로직의 경우 컴파일러가 해당 부분을 최적화 할 수 있을 거라고 기대한다고 했고, 가독성을 개선시켜보라고 조언해주셨다.
    -컴파일러 최적화는 고려해보지 못한 부분인데, 앞으로 학습해야 할 부분이 산더미라고 생각했다.

    -

    남겨준 코멘트에 따라 최종적으로는 중복된 코드를 줄이는 방향으로 코드를 수정했다.
    -결과적으로 기존 로직 대비 비교 연산을 한 번 줄일 수 있었고, 명시된 주석의 내용과 유사한 흐름의 코드를 작성하여 좋은 방향으로 리팩터링을 했다고 생각한다.

    - - -
    public static String getSessionCookieName(Context context) {
    -
    -    String result = getConfiguredSessionCookieName(context);
    -
    -    if (result == null) {
    -        result = DEFAULT_SESSION_COOKIE_NAME;
    -    }
    -
    -    return result;
    -}
    -
    -public static String getSessionUriParamName(Context context) {
    -
    -    String result = getConfiguredSessionCookieName(context);
    -
    -    if (result == null) {
    -        result = DEFAULT_SESSION_PARAMETER_NAME;
    -    }
    -
    -    return result;
    -}
    -
    -private static String getConfiguredSessionCookieName(Context context) {
    -
    -    // Priority is:
    -    // 1. Cookie name defined in context
    -    // 2. Cookie name configured for app
    -    // 3. Default defined by spec
    -    if (context != null) {
    -        String cookieName = context.getSessionCookieName();
    -        if (cookieName != null && cookieName.length() > 0) {
    -            return cookieName;
    -        }
    -
    -        SessionCookieConfig scc =
    -            context.getServletContext().getSessionCookieConfig();
    -        cookieName = scc.getName();
    -        if (cookieName != null && cookieName.length() > 0) {
    -            return cookieName;
    -        }
    -    }
    -
    -    return null;
    -}
    -
    -

    HTTP 수업

    -

    미션 중간에 진행되었던 HTTP 수업에는 HTTP를 적절하게 활용하는 부분에 대해 학습했다.
    -항상 성능 개선을 위해 애플리케이션 단에서 최적화해보려고 노력을 했지만, 더 적은 시간을 투자해서 효율적으로 성능을 개선할 수 있는 방법에 대해 알 수 있었던 수업이었다.
    -HTTP 압축, HTTP 캐싱, 리소스 최적화 기법에 대해 학습했다.

    -

    스프링 부트에서는 다음 옵션을 설정하여 http의 송수신의 압축을 진행할 수 있다.

    -
    server:
    -  compression:
    -    enabled: true
    -
    -

    수업 중 해당 압축 성능이 좋다면 왜 스프링 부트에서는 기본 값으로 설정을 하지 않았는지 궁금해졌다.
    -궁금증을 해소하지 못했는데 말랑이 잡담 채널에 다음과 같은 issue를 찾아주었다.
    -내용을 요약해 보자면 WAS 별로 압축을 하기 위해 설정해야 하는 것이 다르고, 무조건 압축을 하는 것이 최적의 경우가 아닐 수 있기 때문에 기본값으로 설정하지 않는 것 같다.

    -
    -

    If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.

    -
    -

    Phil Webb 형님의 말에 따르면 일반적인 애플리케이션을 개발하는 경우 gzip 압축을 사용하는 것이 좋지만, MSA 환경 + 데이터 센터에서 사용하는 경우 오직 다른 MSA 애플리케이션과 통신하고, 고성능 네트워크가 있기 때문에 CPU 부하를 줄이는 것이 우선시 될 수도 있다는 것이었다.

    -

    이외에도 의도하지 않은 캐싱을 막기 위해 휴리스틱 캐싱을 제거하거나, 개인 정보 유출을 막기 위해 응답 헤더에 private을 설정, ETag도 학습했다.

    -

    ETag HTTP 응답 헤더는 특정 버전의 리소스를 식별하는 식별자다.
    -웹 서버가 내용을 확인하고 변하지 않았으면, 웹 서버로 full 요청을 보내지 않기 때문에, 캐시가 더 효율적이게 된다.
    -MDN

    -

    Thread 수업

    -

    스레드에 대한 수업을 들었지만, 복잡한 내용도 워낙 많았기 때문에 설명하라고 하면 잘 못할 것 같은 느낌이 든다.
    -현재 프로젝트, 미션, 테코톡 준비를 병행해야 해서 세부적인 내용은 시간 날 때 복습하려고 한다.

    -

    스레드를 이해하고, WAS에 스레드 설정 관련한 실습이 있었는데 테오와 같이 1시간 정도 페어로 Thread 실습을 진행해 보았다.
    -학습한 내용은 다음과 같다.

    -

    threads.max: Tomcat의 최대 스레드 개수
    -max-connections: Tomcat이 유지할 수 있는 최대 커넥션 개수
    -accept-count: 최대 연결 수에 도달했을 때 연결 요청에 대해 운영 체제에서 제공하는 대기열의 최대 길이. 해당 Queue에 요청이 쌓이는 것은 Tomcat이 더 이상 요청을 받을 수 없다는 뜻이다. accpet-count queue에도 요청이 가득차면 그 이후에 오는 요청은 거부된다.

    - -

    마치며

    -

    시간은 너무 빠르게 가고 할 일은 많은 것 같다.
    -우선순위를 잘 정하고 학습을 진행해야겠다.
    -현재 데이터 다루는 부분(DB)에 대한 학습이 많이 부족한 것 같다. 해당 부분은 테코톡이 끝나는대로 채워야겠다.

    -

    참고 자료

    -

    RFC 2616
    -ETag, mdn
    -Apache Tomcat 8 Configuration Reference
    -Apache Tomcat Tuning, Terry Cho
    -maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    1, 2단계: https://github.com/woowacourse/java-chess/pull/441
    +3, 4단계: https://github.com/woowacourse/java-chess/pull/529

    +

    체스

    +

    체스 미션에는 가비와 페어가 매칭되었다!
    +체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
    +하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
    +미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

    +

    가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
    +최종적으로 결정한 부분은 다음과 같다.

    +

    각 기물의 이동 가능여부
    +Rank와 File은 각각 위치값을 가지고 있고, 값의 차이를 이용해서 각 기물의 이동 가능 여부를 계산했다.
    +직선 → Rank와 File 차이 중 하나가 0이어야 한다.
    +대각선 → Rank와 File 차이의 절대값이 같아야 한다. ex) abs(-2) == abs(2)
    +나이트 → 차이의 절대값이 하나는 2 나머지 하나는 1이어야 한다.

    +

    도착 칸의 기물 여부
    +아군 → 이동이 불가능하다.
    +적군 → 이동이 가능하다. 적군을 잡는다.

    +

    중간에 기물 존재 여부
    +이동 경로에 기물이 존재하면 안된다.

    +

    데이터베이스 사용
    +체스 미션은 특별하게 데이터베이스와 연결하는 부분이 있었다.
    +체스 게임의 상태를 다음의 두가지 방법으로 정할 수 있다고 생각했다.

    +
      +
    • 기물 전체를 저장하는 방법
    • +
    • 기보를 저장하고 게임을 불러와 기보대로 이동시키는 방법
    • +
    +

    기물이 이동할 때마다 값을 저장하고 싶었고, 기보를 저장하는 방법을 선택했다.
    +기물 전체를 저장하지 않은 이유는 다음과 같다.

    +
      +
    • 턴과 같은 부가적인 요소를 저장해야 한다.
    • +
    • 이동을 할 때 기물이 잡히는 경우 update 쿼리(이동 기물)와 delete(잡힌 기물) 2개의 쿼리를 날려야 한다.
    • +
    • 현재 구조에서 도메인의 변경이 크게(초기 상태를 구성하는 부분) 일어나야 한다.
    • +
    +

    정리하자면 기물 전체 저장과 기보 저장은 다음과 차이가 있다.
    +보드저장: 초기상태에서 32개의 Insert 쿼리(기물의 위치) + 기물 이동 시 움직임 변경(잡히는 경우 2개의 쿼리)
    +기보저장: 초기상태 애플리케이션에서 구성 + 저장된 기보를 select 쿼리로 조회해서 사용(1회) + insert 쿼리(이동 당 1회)

    +

    추가로 기보저장이 구현도 더욱 간단하다. 👍

    +

    부가적인 부분

    +

    리뷰어인 찰리🍫가 동시에 여러 게임이 진행된다면 어떨지? 에 대한 코멘트를 남겨주셔서 다양한 시도를 해봤다.

    +
      +
    • 누누의 도움으로 ConnectionPool 구현
    • +
    • ThreadLocal 사용해서 쓰레드 별 세션 관리
    • +
    • 실제로 애플리케이션 내에서 체스 게임이 진행되는 Board를 ConcurrentHashMap으로 저장(사실 이 부분은 현재 구조에서 필요없지만 2명이 서로 게임하는 경우를 생각해서 넣어보았다.)
    • +
    +

    두 명이 서로 같은 방에 입장하여 게임을 진행한다면 출력하는 부분이 까다로워질 것 같다고 예상되어(Board에 옵저버 패턴을 사용해야되나?) 해볼 엄두가 나지 않았다.

    +

    부족했던 부분

    +

    꼼꼼하게 코드를 작성하지 못한 부분
    +DB 관련 부분을 꼼꼼하게 코딩을 하지 못했다.
    +도메인 로직에만 집중하다보니 정적 중요한 DB의 코드의 예외처리, 빈 값을 반환 하는 부분을 꼼꼼하게 처리하지 못했다.
    +하지만 찰리의 꼼꼼한 리뷰로 DB부분과 나만의 JdbcTemplate을 깔끔하게 구현할 수 있었다.

    +

    시간에 대한 부담감
    +초반에는 여유롭지만 제출 마감에 가까워질 수록 사람이 급해지는 것 같다.
    +다음 페어프로그래밍할 땐 속도를 조절하고, 마음에 여유를 가져야겠다.

    +

    새로 학습한 부분

    +

    DAO 중복 제거

    +

    프롤로그에 을 작성했다.
    +DAO를 작성하는데 try-catch-resources와 여러 코드가 중복되서 제거하고싶었다.
    +템플릿 콜백 패턴으로 깔끔하게 중복을 제거할 수 있었다.👍

    +

    페어에게 배울 부분

    +

    페어 생각하기
    +가비는 누구보다 페어를 생각하고, 배려해주는 페어였다.
    +중간 중간 당 떨어질까봐 걱정도 해주고, 나의 컨디션도 확인해줬다!

    +

    미션 몰입하기
    +최근에 미션에 잘 몰입하지 못했다.
    +가비는 페어를 진행할 때 미션에 대한 몰입도가 매우 좋았다.
    +집에가서도 체스 이동에 대한 로직을 어떻게 구현할 지 생각한 뒤 꼼꼼해서 정리해서 나에게 보내주었다.
    +덕분에 나도 가비의 생각을 알 수 있어서 미션을 진행하는데 가속도가 붙은 것 같다.
    +또한 미션을 잘 마무리하고 싶은 마음이 전달되서 그런지 나도 덩달아 열심히 미션을 할 수 있었다.😄

    +

    솔직함
    +먼저 회고하자고 말 걸어줘서 정말 고마웠다고 표현해주는 부분
    +모르는게 있으면 솔직하게 말해주는 부분
    +나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
    +솔직함은 페어할 때 중요한 부분인 것 같다.

    +

    마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/5.html b/tags/woowahan-techcourse/page/5.html index 2e8be6d4f..0f9ed5c80 100644 --- a/tags/woowahan-techcourse/page/5.html +++ b/tags/woowahan-techcourse/page/5.html @@ -13,42 +13,77 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    회고

    -

    지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
    -레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
    -부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
    -내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

    -

    아쉬운 점

    -

    문서화

    -

    개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
    -프로젝트를 진행하면서 내가 한 부분을 조금 더 꼼꼼하게, 이해하기 쉽게 문서화를 했더라면 팀원들에게 더욱 도움이 되었을 텐데 이 부분에 시간을 조금 더 투자하지 못했던 부분에서 아쉬움이 많이 들었다.
    -방학 기간 동안 문서화를 하지 못했던 부분을 개인 블로그 올리면서 조금 더 채워보려고 한다.

    -

    내가 못하는 부분이라면 시간을 들이자

    -

    잘 못하는 부분이라면 시간을 들여서라도 중간은 가도록 해야겠다는 생각이 많이 들었다.
    -말을 하기 전에 정리해서 의견을 내는 것, 발표 준비, 감정 조절 등등 -못하는 부분을 인지하고, 개선하자.

    -

    컴포트 존 벗어나기

    -

    조금 더 도전적으로 목표를 잡았으면 좋았을 것 같다.
    -매번 근거를 가지고 기술을 도입하고, 코드를 작성하려고 노력했다.
    -하지만 지속적으로 개선하려고 하는 부분이 다소 부족했다.

    -

    좋았던 점

    -

    좋았던 점도 문서화

    -

    팀 블로그도 먼저 도입하자고 제안하고, 내가 했던 부분은 문서화를 꽤 많이 해서 팀원들과 공유할 수 있었다.
    -백엔드 크루 4명이서 같이 한 부분에 대해서는 기능 구현한다고 문서화가 조금 미흡해서 보충을 해야겠다.

    -

    내가 디자인한 트립드로우 로고

    - -

    트립드로우 로고를 만들었다.
    -팀원들이 대표 색상(파란색)을 정해줬고, 주말 동안 신나게 로고 디자인을 했던 것 같다.
    -아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

    -

    기술 선택의 이유

    -

    기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
    -100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

    -

    마치며

    -

    플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
    -안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    레벨 1이 끝났다.
    +우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
    +혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
    +하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

    +

    Keep

    +

    나만의 루틴 만들기

    +

    스스로가 외부의 영향을 많이 받는다고 생각한다.
    +최대한 꾸준히 할 수 있는 시간을 만드는 것이 중요하다고 생각한다.

    +

    매일 8시에 도착하여 아침에 해야 할 일을 정리하거나, 우선순위에 따라 처리하고
    +소화능력이 부족하기 때문에 점심은 도시락(그래봤자 계란2개)을 준비하고
    +항상 똑같은 컨디션을 유지하기 위해 항상 6시에 집에 간다.
    +이제 바빠질 테니 일찍 집에 가는 일은 어쩔 수 없이 줄어들겠지만😢

    +

    선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

    +

    크루들과 친하게 지내기

    +

    10명 정도의 크루의 닉네임을 외우고 친하게 지낸다면 성공적이라고 생각했었다.
    +하다 보니 더 많은 크루들의 닉네임을 외운 것 같다.
    +앞으로도 크루들과 친하게 지내고 아무 때나 말을 걸 수 있는 크루가 늘어나길 :)

    +

    글쓰기

    +

    글을 잘 쓰는 편은 아니지만 꾸준히 작성하려고 노력했다.
    +매 미션마다 회고를 작성하니 생각도 정리되고 개선점도 찾을 수 있어서 좋았다.

    +

    우아한테크코스에는 레벨마다 글쓰기를 진행하는데, 운이 좋게 글쓰기 상을 받았다.
    +사실 겉으로 드러내지 않았지만 꼭 받아보고 싶었다.
    +글쓰기 조원, 투표해 준 크루들에게 너무 감사하다.

    +

    코드 리뷰 스터디

    +

    누누, 주노, 다즐, 말랑, 박스터, 오잉, 깃짱와 코드 리뷰 스터디를 진행했다.
    +과연 도움이 될까 생각했지만 결과적으로는 코드 리뷰를 하면서 성장을 많이 한 것 같다.
    +투자한 시간 대비 가성비가 좋은 활동이었다.
    +누누가 스터디장인데 과연 꾸준히 이어나가려나?

    +

    레벨 인터뷰

    +

    인터뷰할 때 많이 떨지 않아서 좋았다.
    +남들 앞에서 이야기를 하거나, 면접을 보면 항상 엄청 떨어서 걱정했는데
    +기술적인 질문을 받았을 때 떨지 않고 잘 대답할 수 있었다.
    +우아한테크코스 생활을 하면서 다른 크루가 질문했을 때, 최대한 이해하기 쉽게 설명하려고 했던 경험이 도움이 된 것 같다.
    +이후 레벨 인터뷰를 진행할 때 다음과 같은 부분을 고려하면 더 좋을 것 같다.

    +
      +
    • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
    • +
    • 두괄식 표현
    • +
    • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
    • +
    • 설명할 수 있을만큼 시간 충분히 가지기
    • +
    • 인터뷰어의 질문 의도를 명확히 이해하지 못했다면 의도 다시 물어보기
    • +
    • 끝맺는 부분 연습하기(자신감 있게)
    • +
    • 기술적인 집착가지기
    • +
    • 기술적인 부분을 꼼꼼히 준비했으면 협업 관련 질문도 준비하기
    • +
    +

    Problem

    +

    페어프로그래밍

    +

    우아한테크코스를 진행하면서 가장 어려운 활동 중 하나라고 생각한다.
    +페어는 매번 바뀌고, 미션의 복잡도도 증가하기 때문인 것 같다.
    +소통 능력, 시간관리가 부족했고, 만족스럽지 않았다.
    +하지만 페어를 진행하고, 회고를 하다 보니 나만의 노하우가 쌓이는 느낌이다.
    +레벨 2에서는 부족했던 부분을 개선하여 함께하고 싶은 페어가 되고 싶다.

    +

    집중하는 시간⏱️ 부족

    +

    레벨 1을 진행하면서 집중하는 시간이 많이 부족했다.
    +이른 아침과 오후에 개인적으로 집중할 수 있는 공간을 예약해서 온전히 나만의 시간을 가져야겠다.

    +

    Try

    +

    허브🌿와의 티타임?

    +

    소프트 스킬을 늘릴 방법을 생각하다가 대화를 나누지 못한 다른 크루들과 깜짝 커피챗을 하면 어떨까 생각했다.
    +예를 들어 잡담방에 저와 커피챗 하실 분 :) 하면서 올릴 수 있을 것 같다.
    +참여하는 사람이 있을지, 안 좋게 보는 게 아닐지 걱정되지만 그래도 재밌을 것 같다.
    +저랑 허브티 한잔 하실래요?

    +

    기술적인 부분

    +

    우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
    +시간의 여유가 될 때 책을 조금씩 읽어야겠다.
    +블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

    +

    레벨 1을 마무리하며

    +

    시간이 빠르게 흘러갔다.
    +타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
    +또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/6.html b/tags/woowahan-techcourse/page/6.html index ce4c40266..362722e4c 100644 --- a/tags/woowahan-techcourse/page/6.html +++ b/tags/woowahan-techcourse/page/6.html @@ -13,31 +13,49 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 3분

    23년의 6월이 오고, 레벨 2가 끝났다.
    -빠르게 지나가서 조금 아쉽다.

    -

    학습

    -

    회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
    -항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
    -미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

    -

    고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
    -방학 그리고 레벨 3 때는 조금 더 이론적인 부분을 학습하는데 집중해야겠다.

    -

    점차 학습 범위가 넓어지면서 자연스럽게 모르는 내용이 쌓여간다.
    -필요한 내용은 앞으로 천천히 학습하면 되니까 조급해지지 말아야겠다.

    -

    수면

    -

    레벨 2를 진행하는 동안 수면이 많이 부족했었고, 결과적으로는 그날의 컨디션을 많이 좌우했던 것 같다.
    -앞으로 수면 시간을 늘리고, 좋은 수면 습관을 가지도록 노력해야겠다.

    -

    협업

    -

    레벨 2 마지막에 협업 미션이 있었다.
    -지금까지는 백엔드 크루들과 페어 프로그래밍을 하면서 협업을 경험했다.
    -이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

    -

    레벨 3 때부터 본격적으로 프로젝트가 시작된다.
    -팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

    -

    레벨 2를 마무리하며

    -

    회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. -읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-racingcar/pull/24
    +2단계: https://github.com/woowacourse/jwp-racingcar/pull/128

    +

    웹 자동차 미션

    +

    사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
    +웹 자동차 미션에서는 비버와 페어가 매칭되었다.
    +레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

    +

    스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
    +첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
    +난이도 높은 미션이 아니었지만 리뷰어인 라빈에게 칭찬을 많이 받아서 기분이 좋았다.
    +라빈 감사합니다!

    +

    부족했던 부분

    +

    컨디션도 좋지 않고 열정도 식은 것 같은 느낌이 들었다.
    +미션이 다소 여유롭다고 느껴져서, 시간에 대한 부분도 잘 관리하지 못한 것 같다.
    +미션에 잘 집중하지 못해서 페어에게 많이 미안했고, 나 자신에게 아쉬웠던 부분이 많았다.

    +

    지난번 회고를 다시 보는데 집중을 잘 못한 경우가 많은 것 같다.
    +도전적이지 않거나 시간이 부족하지 않으면 집중을 잘 못하는 것 같다.
    +머릿속에서 시간적 여유가 있다고 생각할 때가 가장 위험한 순간인 것 같다.

    +

    함께 자라기에서 나온 난이도 높이기가 필요해지는 순간이다.

    +

    새로 학습한 부분

    +

    중요도가 있는 어노테이션부터 클래스 이름에 가깝게 명시하기

    +
    @SuppressWarnings("NonAsciiCharacters")
    +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    +@Transactional
    +@AutoConfigureMockMvc
    +@SpringBootTest
    +public class RacingGameIntegrationTest {
    +
    +

    페어에게 배울 부분

    +

    비버의 성격
    +비버가 성격이 좋아서 편하게 페어를 할 수 있었다.
    +미션을 진행하면서 성급하지 않고 여유로워서 좋았다.

    +

    미션에 집중하는 부분
    +내가 미션에 잘 집중하지 못했는데도 같이 페어를 잘 진행한 것 같아서 좋았다.
    +비버가 미션에 잘 집중해서 그렇지 않았나 생각했다.
    +근육맨 비버라 그런지 체력이 좋아서 그런가?
    +중간에 잘 안 쉬고도 집중해서 미션을 진행하는 걸 보고 대단하다고 생각했다.

    +

    학습에 대한 열정
    +추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
    +비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
    +나도 5월부터 조금 더 화이팅 해야겠다.

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/7.html b/tags/woowahan-techcourse/page/7.html index 68ca46ad8..e24f86fd5 100644 --- a/tags/woowahan-techcourse/page/7.html +++ b/tags/woowahan-techcourse/page/7.html @@ -13,35 +13,46 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 4분

    레벨 인터뷰

    -

    레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
    -따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
    -이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
    -기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

    -

    API 문서 도구 선택

    -

    큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
    -백엔드 팀원이 함께 의사결정을 했고, 미션 기간이 짧은 만큼 팀 차원에서 비교적 학습하기 쉬운 Swagger를 선택했다.
    -추가로 들어가는 시간 대비 하이 리턴이라고 생각했다고 답변했다.

    -

    팀 차원의 학습 비용을 언급해서, 다음과 같은 좋은 피드백을 받았다.

    -
    -

    특히 팀으로 의사결정하는 과정을 공유해 준 점이 좋았고 기술적 의사결정 과정에서 팀의 학습비용을 고려한 점이 좋았음.
    -앞으로도 학습 비용은 주요하게 고려해야 할 사항

    -
    -

    PUT과 PATCH & 토큰과 세션

    -

    PUT과 PATCH 차이를 설명하는 부분에서는 PATCH를 사용할 때 페이로드가 적어진다는 내용을 빼먹고 답변을 했다.
    -토큰과 세션의 경우 기술을 잘 모르는 사람에게 설명해달라는 제약조건이 추가되었다.

    -

    해당 내용을 답변하면서 기술적인 깊이가 많이 부족했다는 생각이 든다.
    -실제로 레벨 2 때 이론적인 학습 시간이 매우 적었고, 집중력도 많이 부족했다.
    -앞으로 어떻게 깊이를 채울지 고민을 할 수 있는 질문들이었다.

    -

    추가로 기술을 잘 모르는 사람에게 설명하는 가정을 두고 학습을 한다면 큰 도움이 될 거라는 피드백을 받았다.

    -

    그 외 개선할 점

    -

    인터뷰할 때 특유의 말버릇을 개선하기
    -생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
    -기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
    -이전에 공부했던거 되돌아 보는 시간 가지기

    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    1단계: https://github.com/woowacourse/jwp-shopping-cart/pull/244
    +2단계: https://github.com/woowacourse/jwp-shopping-cart/pull/300

    +

    웹 장바구니 미션

    +

    장바구니 미션은 블랙캣이랑 진행했다.
    +요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
    +2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
    +Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
    +이전에 스프링 사용할 때는 아무 생각 없이 코드를 작성하는 경우가 많았는데, 코드를 작성할 때 근거가 생기고 있는 것 같다.

    +

    새로 학습한 부분

    +

    DTO 우발적 중복

    +

    장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.

    +

    dto1

    +

    클래스명을 제외하고 필드와 검증 로직 그 외 모든 게 같은 DTO를 보며 중복이라고 생각을 했고, 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
    +로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러 가지 종류로 나누어 설명하고 있다.

    +
      +
    • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
    • +
    • 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.
    • +
    +

    추가와 수정은 초기에는 중복으로 보이지만 초기 생성 시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다.
    +따라서 리뷰어 웨지가 아래와 같이 의존 역전을 이용하는 방법도 있다고 알려주셨다.

    +

    dto2

    +

    Interceptor에서 인증한 값 재사용

    +

    사실 조회를 두 번 하기 싫어서 다양한 방법을 생각했었는데 이번 미션에서는 ThreadLocal을 사용했다.
    +일단 Tomcat은 요청마다 다른 스레드를 사용하고, Interceptor에서 조회해서 만든 Credential을 ThreadLocal에 넣어두었다가 ArgumentResolver에서 꺼낸 다음 ThreadLocal을 clear 하면 문제가 없을 거라 판단했다.

    +

    리뷰어인 웨지에게도 어떤 방법을 사용할지 궁금증을 작성했었다.
    +웨지는 email에 index를 걸어두고 dao 재조회를 사용할 것이라고 했다.
    +재사용하지 않고 db에 인덱스를 걸 생각은 하지 못했는데, 제일 직관적이고 좋은 방법이라고 생각했다.

    +

    페어에게 배울 부분

    +

    기록

    +

    블랙캣은 기록을 굉장히 잘 하는 크루였다.
    +노션에 페어를 진행하면서 했던 내용 + 고민했던 부분 + 회고를 꼼꼼하게 기록해서 공유해 주었다.
    +추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

    +

    의견 일치시키기

    +

    페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
    +따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
    +블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

    +

    빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/8.html b/tags/woowahan-techcourse/page/8.html index 38ef8b2cf..b86f2b0c0 100644 --- a/tags/woowahan-techcourse/page/8.html +++ b/tags/woowahan-techcourse/page/8.html @@ -13,76 +13,85 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    1단계: AWS 배포
    -2단계: https://github.com/woowacourse/jwp-shopping-order/pull/7

    -

    장바구니 주문 미션

    -

    배포 및 협업을 할 수 있는 미션이었다.
    -마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

    -

    배포

    -

    이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
    -각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
    -배포 스크립트를 작성하는 경험을 해볼 수 있었다.
    -배포 스크립트에 시간을 많이 투자하진 않았고, 다음과 같이 간단하게 작성했다.

    -
    echo "Start Deploy Script"
    -REPOSITORY_NAME=/home/ubuntu/jwp-shopping-order
    -PROJECT_NAME=jwp-shopping-order
    -
    -echo "Change Directory"
    -cd $REPOSITORY_NAME
    -
    -echo "Git Pull"
    -git pull origin step2
    -
    -echo "Build"
    -./gradlew bootJar
    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    1단계: https://github.com/woowacourse/jwp-subway-path/pull/16
    +2, 3단계: https://github.com/woowacourse/jwp-subway-path/pull/126

    +

    지하철 미션

    +

    점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
    +지하철 미션은 밀리랑 페어를 진행했다.
    +간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
    +이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
    +API와 테이블 구조를 우리가 정할 수 있는 상황이었고, 도메인 로직이 복잡했기 때문에 도메인을 먼저 구현했다.

    +

    노선의 구간 추가 및 삭제

    +

    노선을 저장하는 방법에 대해서 밀리와 이야기를 나눴다.

    +
      +
    1. 구간을 데이터베이스에서 전부 제거하고 전부 추가하는 방법
    2. +
    3. 변경된 요소만 데이터베이스에 반영하는 방법
    4. +
    +

    페어 시간이 짧아서 더욱 간단한 1번을 선택했고, 시간 내 요구사항을 만족시키기 위해 더 간단하게 구현하는 방법을 선택하는 것도 좋은 트레이드오프였던 것 같다.
    +추후 페어가 끝나고 리뷰어인 서브웨이가 일부분만 반영하는 것으로 개선해 보는 것도 좋을 것 같다고 코멘트를 남겨주셔서 추가 및 제거된 요소만 반영하도록 변경했다.

    +

    부족했던 부분

    +

    미션의 난이도가 올라간 만큼, 페어 할 땐 컨디션 관리도 잘하려고 노력하고 미션 할 때도 집중해서 잘 끝낸 것 같다.
    +우아한테크코스를 진행하면서 알아야 하는 게 많아지면서 가끔 조바심을 가질 때가 있는 것 같은데, 조바심을 경계할 필요가 있을 것 같다.
    +부족한 부분은 인정하고, 앞으로 나아가야겠다.

    +

    새로 학습한 부분

    +

    컴포지트 패턴으로 요금 정책 추상화

    +

    요금 정책은 기본요금 정책, 거리별 요금 정책, 연령별 할인 정책이 있었다.
    +요금을 더하는 부분과, 할인하는 부분이 있어서 이 둘을 분리할까 생각했지만, 이 정도 크기의 애플리케이션에서는 오히려 분리하지 않고 하나로 합치는 게 더 좋다고 생각했다.
    +또한 분리하지 않는다면 정책의 순서가 중요한데, 연령별 할인 정책을 마지막에 두어야 했기 때문에 책임 연쇄 패턴도 고려를 했지만 조금 더 간결해 보이는 컴포지트 패턴을 선택했다.

    +

    도메인에 특정 기술의 의존성을 분리

    +

    처음에 도메인 패키지에 jgrapht 라이브러리를 의존하고 있는 클래스를 두어서 도메인 패키지가 jgrapht와 강결합이 되어버렸다.
    +따라서 도메인 패키지 내에는 경로 검색에 대한 인터페이스를 두고, 세부 구현은 도메인 패키지 외부로 분리했다.
    +최대한 간결하게 구현한다고 생각을 해도, 이런 부분은 인터페이스를 두어 결합을 피하는 것이 좋을 것 같다.

    +

    컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
    +이때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

    +

    인수 테스트 작성

    +

    인수 테스트는 사용자 스토리 시나리오 기반 테스트다.
    +브라운이 해주신 강의 + 유튜브에 있는 브라운의 강의를 보고 지하철 미션에 인수 테스트를 적용해 보았다.
    +메서드, 변수명을 전부 한글로 작성했는데 전체적인 흐름을 알기 편하고 읽기도 좋았다.
    +그리고 인수 테스트에 필요한 Steps를 만드는 과정이 너무 재밌었다.

    +

    결과는 아래와 같다.

    +
    @Nested
    +public class 노선을_전체_조회할_때 {
     
    -echo "Copy, Start Server"
    -mv ./build/libs/$PROJECT_NAME.jar .
    +    @Test
    +    void 상행종점역_부터_하행종점역으로_정렬된_결과를_반환한다() {
    +        // given
    +        노선_생성_요청("2호선", "초록", 0);
    +        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("2호선", "잠실", "잠실새내", 5);
    +        구간_생성_요청("2호선", "잠실새내", "종합운동장", 오른쪽, 5);
     
    -PID=$(pgrep -f $PROJECT_NAME)
    +        노선_생성_요청("9호선", "고동", 0);
    +        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("9호선", "봉은사", "종합운동장", 3);
    +        구간_생성_요청("9호선", "종합운동장", "삼전", 오른쪽, 7);
     
    -if [ -n $PID ]; then
    -        kill -9 $PID
    -	sleep 5
    -fi
    +        // when
    +        final var 조회_결과 = 노선_전체_조회_요청();
     
    -nohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &
    -
    -

    협업

    -

    일단 우스랑 우코가 먼저 잠실로 와줘서 너무 감사했다.
    -백엔드가 아닌 다른 크루들과 해보는 첫 협업이라 약간 두근거렸다.
    -예상외로 대화가 잘 되어서, 빠르게 명세를 정할 수 있었다.

    -

    부족했던 부분

    -

    여러가지 방법에 대한 장단점을 고려해보기

    -

    백엔드와 테이블 명세나 쿠폰 구현에 대해서 이야기할 때 장단에 대해 많이 고려하지 못한 것 같다.
    -조금 더 시간을 많이 들여서 장단점을 고려했다면 더 좋은 결과물이 나오지 않았을까?
    -앞으로 선택의 순간에서 조금 더 시간을 들여보는 것도 좋을 것 같다.

    -

    새로 배운 부분

    -

    expose headers

    -

    웹 페이지에서 Location 헤더를 받을 수 없는 문제가 있었다.
    -기본적으로 허용 목록에 존재하는 응답헤더만 반환한다는 것을 모르고 있었다.
    -이를 expose headers 설정을 통해 해결할 수 있었다.
    -nginx 설정에 다음과 같이 추가해 주었다.

    -
    add_header 'Access-Control-Expose-Headers' 'Location'
    +        // then
    +        요청_결과의_상태를_검증한다(조회_결과, 정상_요청);
    +        노선_전체_조회_결과를_확인한다(
    +                조회_결과,
    +                노선_정보("2호선", "초록", 0, "잠실", "잠실새내", "종합운동장"),
    +                노선_정보("9호선", "고동", 0, "봉은사", "종합운동장", "삼전")
    +        );
    +    }
    +}
     
    -

    읽기 전용 트랜잭션

    -

    단순 조회 요청에 대한 성능을 향상시켜준다는 것이라고 간단히만 알고 있었다.
    -이번에 코멘트가 달려서 조금 더 자세히 공부해 보기로 했다.
    -Transactional(readOnly = true)를 사용하는 경우 다음과 같이 동작한다.

    -

    setReadOnly(true) 설정이 된 Connection으로 연결을 시도를 한다. 이 설정을 하는 경우 DB마다 다르게 동작한다.

    -
      -
    • h2의 Connection 구현체는 readOnly 설정을 무시하는 방향으로 구현되어 Transactional 적용되지 않는다.
    • -
    • MySQL 8.0(InnoDB 사용 시)의 경우 읽기 전용으로 알려진 트랜잭션의 경우 트랜잭션 ID를 설정하지 않기 때문에 조회 속도가 더 빨라진다.
    • -
    -

    ORM 프레임워크를 사용한다면 prepareTransactionalConnection를 호출한다고 한다.
    -추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

    -

    DAO에 @Transactional 적용

    -

    DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
    -Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
    -DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

    +

    페어에게 배울 부분

    +

    의견 조율하기

    +

    밀리가 필요한 부분에서 의견을 적극적으로 내줘서 진행이 수월했다.
    +의사소통이 매우 잘 돼서 좋았고 덕분에 시간 내에 요구사항을 만족해 미션을 제출할 수 있었던 것 같다.

    +

    꼼꼼하게 코딩하기

    +

    밀리는 코딩을 엄청 꼼꼼하게 하는 것 같다.
    +변수명, 메서드명을 중요하게 생각했고, 좋은 변수명을 잘 짓는 것 같다.
    +또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

    +

    편한 분위기

    +

    전체적으로 페어 할 때 편하게 진행했던 것 같다.
    +일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
    +나는 과연 다른 사람들에게 편한 사람일까?

    \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/9.html b/tags/woowahan-techcourse/page/9.html index 1badea588..4a593b49e 100644 --- a/tags/woowahan-techcourse/page/9.html +++ b/tags/woowahan-techcourse/page/9.html @@ -13,85 +13,76 @@ - - + + -

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 8분

    1단계: https://github.com/woowacourse/jwp-subway-path/pull/16
    -2, 3단계: https://github.com/woowacourse/jwp-subway-path/pull/126

    -

    지하철 미션

    -

    점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
    -지하철 미션은 밀리랑 페어를 진행했다.
    -간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
    -이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
    -API와 테이블 구조를 우리가 정할 수 있는 상황이었고, 도메인 로직이 복잡했기 때문에 도메인을 먼저 구현했다.

    -

    노선의 구간 추가 및 삭제

    -

    노선을 저장하는 방법에 대해서 밀리와 이야기를 나눴다.

    -
      -
    1. 구간을 데이터베이스에서 전부 제거하고 전부 추가하는 방법
    2. -
    3. 변경된 요소만 데이터베이스에 반영하는 방법
    4. -
    -

    페어 시간이 짧아서 더욱 간단한 1번을 선택했고, 시간 내 요구사항을 만족시키기 위해 더 간단하게 구현하는 방법을 선택하는 것도 좋은 트레이드오프였던 것 같다.
    -추후 페어가 끝나고 리뷰어인 서브웨이가 일부분만 반영하는 것으로 개선해 보는 것도 좋을 것 같다고 코멘트를 남겨주셔서 추가 및 제거된 요소만 반영하도록 변경했다.

    -

    부족했던 부분

    -

    미션의 난이도가 올라간 만큼, 페어 할 땐 컨디션 관리도 잘하려고 노력하고 미션 할 때도 집중해서 잘 끝낸 것 같다.
    -우아한테크코스를 진행하면서 알아야 하는 게 많아지면서 가끔 조바심을 가질 때가 있는 것 같은데, 조바심을 경계할 필요가 있을 것 같다.
    -부족한 부분은 인정하고, 앞으로 나아가야겠다.

    -

    새로 학습한 부분

    -

    컴포지트 패턴으로 요금 정책 추상화

    -

    요금 정책은 기본요금 정책, 거리별 요금 정책, 연령별 할인 정책이 있었다.
    -요금을 더하는 부분과, 할인하는 부분이 있어서 이 둘을 분리할까 생각했지만, 이 정도 크기의 애플리케이션에서는 오히려 분리하지 않고 하나로 합치는 게 더 좋다고 생각했다.
    -또한 분리하지 않는다면 정책의 순서가 중요한데, 연령별 할인 정책을 마지막에 두어야 했기 때문에 책임 연쇄 패턴도 고려를 했지만 조금 더 간결해 보이는 컴포지트 패턴을 선택했다.

    -

    도메인에 특정 기술의 의존성을 분리

    -

    처음에 도메인 패키지에 jgrapht 라이브러리를 의존하고 있는 클래스를 두어서 도메인 패키지가 jgrapht와 강결합이 되어버렸다.
    -따라서 도메인 패키지 내에는 경로 검색에 대한 인터페이스를 두고, 세부 구현은 도메인 패키지 외부로 분리했다.
    -최대한 간결하게 구현한다고 생각을 해도, 이런 부분은 인터페이스를 두어 결합을 피하는 것이 좋을 것 같다.

    -

    컴포지트 패턴은 인터페이스를 구현한 개별 객체가 존재하고, 그 개별 객체들을 포함하는 하나의 구현체가 따로 존재하는 패턴이다.
    -이때 사용자는 개별 객체와 합성 객체(개별 객체들을 포함하고 있는)를 똑같이 사용할 수 있다.

    -

    인수 테스트 작성

    -

    인수 테스트는 사용자 스토리 시나리오 기반 테스트다.
    -브라운이 해주신 강의 + 유튜브에 있는 브라운의 강의를 보고 지하철 미션에 인수 테스트를 적용해 보았다.
    -메서드, 변수명을 전부 한글로 작성했는데 전체적인 흐름을 알기 편하고 읽기도 좋았다.
    -그리고 인수 테스트에 필요한 Steps를 만드는 과정이 너무 재밌었다.

    -

    결과는 아래와 같다.

    -
    @Nested
    -public class 노선을_전체_조회할_때 {
    +

    "Woowahan Techcourse" 태그로 연결된 16개 게시물개의 게시물이 있습니다.

    모든 태그 보기

    · 약 5분

    1단계: AWS 배포
    +2단계: https://github.com/woowacourse/jwp-shopping-order/pull/7

    +

    장바구니 주문 미션

    +

    배포 및 협업을 할 수 있는 미션이었다.
    +마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

    +

    배포

    +

    이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
    +각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
    +배포 스크립트를 작성하는 경험을 해볼 수 있었다.
    +배포 스크립트에 시간을 많이 투자하진 않았고, 다음과 같이 간단하게 작성했다.

    +
    echo "Start Deploy Script"
    +REPOSITORY_NAME=/home/ubuntu/jwp-shopping-order
    +PROJECT_NAME=jwp-shopping-order
    +
    +echo "Change Directory"
    +cd $REPOSITORY_NAME
    +
    +echo "Git Pull"
    +git pull origin step2
     
    -    @Test
    -    void 상행종점역_부터_하행종점역으로_정렬된_결과를_반환한다() {
    -        // given
    -        노선_생성_요청("2호선", "초록", 0);
    -        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("2호선", "잠실", "잠실새내", 5);
    -        구간_생성_요청("2호선", "잠실새내", "종합운동장", 오른쪽, 5);
    +echo "Build"
    +./gradlew bootJar
     
    -        노선_생성_요청("9호선", "고동", 0);
    -        노선에_구간이_존재하지_않을_때_초기_구간_생성_요청("9호선", "봉은사", "종합운동장", 3);
    -        구간_생성_요청("9호선", "종합운동장", "삼전", 오른쪽, 7);
    +echo "Copy, Start Server"
    +mv ./build/libs/$PROJECT_NAME.jar .
     
    -        // when
    -        final var 조회_결과 = 노선_전체_조회_요청();
    +PID=$(pgrep -f $PROJECT_NAME)
     
    -        // then
    -        요청_결과의_상태를_검증한다(조회_결과, 정상_요청);
    -        노선_전체_조회_결과를_확인한다(
    -                조회_결과,
    -                노선_정보("2호선", "초록", 0, "잠실", "잠실새내", "종합운동장"),
    -                노선_정보("9호선", "고동", 0, "봉은사", "종합운동장", "삼전")
    -        );
    -    }
    -}
    +if [ -n $PID ]; then
    +        kill -9 $PID
    +	sleep 5
    +fi
    +
    +nohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &
    +
    +

    협업

    +

    일단 우스랑 우코가 먼저 잠실로 와줘서 너무 감사했다.
    +백엔드가 아닌 다른 크루들과 해보는 첫 협업이라 약간 두근거렸다.
    +예상외로 대화가 잘 되어서, 빠르게 명세를 정할 수 있었다.

    +

    부족했던 부분

    +

    여러가지 방법에 대한 장단점을 고려해보기

    +

    백엔드와 테이블 명세나 쿠폰 구현에 대해서 이야기할 때 장단에 대해 많이 고려하지 못한 것 같다.
    +조금 더 시간을 많이 들여서 장단점을 고려했다면 더 좋은 결과물이 나오지 않았을까?
    +앞으로 선택의 순간에서 조금 더 시간을 들여보는 것도 좋을 것 같다.

    +

    새로 배운 부분

    +

    expose headers

    +

    웹 페이지에서 Location 헤더를 받을 수 없는 문제가 있었다.
    +기본적으로 허용 목록에 존재하는 응답헤더만 반환한다는 것을 모르고 있었다.
    +이를 expose headers 설정을 통해 해결할 수 있었다.
    +nginx 설정에 다음과 같이 추가해 주었다.

    +
    add_header 'Access-Control-Expose-Headers' 'Location'
     
    -

    페어에게 배울 부분

    -

    의견 조율하기

    -

    밀리가 필요한 부분에서 의견을 적극적으로 내줘서 진행이 수월했다.
    -의사소통이 매우 잘 돼서 좋았고 덕분에 시간 내에 요구사항을 만족해 미션을 제출할 수 있었던 것 같다.

    -

    꼼꼼하게 코딩하기

    -

    밀리는 코딩을 엄청 꼼꼼하게 하는 것 같다.
    -변수명, 메서드명을 중요하게 생각했고, 좋은 변수명을 잘 짓는 것 같다.
    -또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

    -

    편한 분위기

    -

    전체적으로 페어 할 때 편하게 진행했던 것 같다.
    -일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
    -나는 과연 다른 사람들에게 편한 사람일까?

    +

    읽기 전용 트랜잭션

    +

    단순 조회 요청에 대한 성능을 향상시켜준다는 것이라고 간단히만 알고 있었다.
    +이번에 코멘트가 달려서 조금 더 자세히 공부해 보기로 했다.
    +Transactional(readOnly = true)를 사용하는 경우 다음과 같이 동작한다.

    +

    setReadOnly(true) 설정이 된 Connection으로 연결을 시도를 한다. 이 설정을 하는 경우 DB마다 다르게 동작한다.

    +
      +
    • h2의 Connection 구현체는 readOnly 설정을 무시하는 방향으로 구현되어 Transactional 적용되지 않는다.
    • +
    • MySQL 8.0(InnoDB 사용 시)의 경우 읽기 전용으로 알려진 트랜잭션의 경우 트랜잭션 ID를 설정하지 않기 때문에 조회 속도가 더 빨라진다.
    • +
    +

    ORM 프레임워크를 사용한다면 prepareTransactionalConnection를 호출한다고 한다.
    +추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

    +

    DAO에 @Transactional 적용

    +

    DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
    +Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
    +DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

    \ No newline at end of file diff --git a/tecochat-retrospective-1.html b/tecochat-retrospective-1.html index e86478fca..3b991ba8e 100644 --- a/tecochat-retrospective-1.html +++ b/tecochat-retrospective-1.html @@ -13,11 +13,11 @@ - - + + -

    [테코챗] 1. 프로토타입 만들기

    · 약 6분

    4월 21일 금요일

    +

    [테코챗] 1. 프로토타입 만들기

    · 약 6분

    4월 21일 금요일

    레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
    레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
    단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
    @@ -27,7 +27,7 @@

    기술이 목적인 사이드 프로젝트를 진행하면 좋을 것 같다는 답변을 들었고, 혼자 아니면 페어할 수 있을 정도의 인원으로 진행하면 좋겠다고 하셨다.
    프론트랑 간단하게 배포까지 해본 경험이 있어서 혼자해도 크게 어렵지 않을 것 같아서 혼자 하기로 마음을 먹었다.

    이건 못참지

    -

    도메인 구입 성공?

    +

    도메인 구입 성공?

    커피챗이 끝나고 집으로 돌아가는 길에 바로 도메인을 구매하려고 namecheap에서 적당한 도메인이 없을까 검색을 계속했다.
    마치 어릴 때 했던 게임 닉네임 정하는 것처럼 시간이 오래 걸렸다.
    dev, io, chat 도메인이 후보였고 집 가는 길에 결정만 하다가 구매하지 못했다.

    @@ -47,7 +47,7 @@

    Sonarcloud

    정적 코드 분석 도구로 Sonarcloud를 적용했다.
    Sonarcloud는 SonarQube의 SaaS 버전이고 사용이 매우 편하다.
    예전에 Sonarcloud를 사용할 땐 버튼 몇 번 누르면 적용할 수 있었는데, 이번에는 바로 github action을 사용하라는 안내 페이지로 이동했다.
    -Sonarcloud가 자체적으로 github repository에 push 하면 정적 분석을 해주는 기능을 원했고, Administration -> Analysis Method에 Automatic Analysis를 설정하니 되었다.
    +Sonarcloud가 자체적으로 github repository에 push 하면 정적 분석을 해주는 기능을 원했고, Administration -> Analysis Method에 Automatic Analysis를 설정하니 되었다.
    너무 꽁꽁 숨겨져있네

    Tiptap

    코드 하이라이팅 기능을 넣고 싶어서 Tiptap을 사용했다.
    @@ -70,6 +70,6 @@

    Tiptap

    tecochat

    폰트 및 favicon 적용

    타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
    -추가로 favicon도 간단하게 적용해서 만족스러웠다.

    +추가로 favicon도 간단하게 적용해서 만족스러웠다.

    \ No newline at end of file diff --git a/tecochat-retrospective-2.html b/tecochat-retrospective-2.html index 180579dc5..dad7c6768 100644 --- a/tecochat-retrospective-2.html +++ b/tecochat-retrospective-2.html @@ -13,11 +13,11 @@ - - + + -

    [테코챗] 2. 배포

    · 약 5분

    프론트엔트

    +

    [테코챗] 2. 배포

    · 약 5분

    프론트엔트

    닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
    추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
    자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
    @@ -61,6 +61,6 @@

    Jenkins Blue Ocean

    참고 자료

    Elastic Beanstalk, AWS
    EC2 AWS Graviton, AWS
    -Default Memory Settings, AWS

    +Default Memory Settings, AWS

    \ No newline at end of file diff --git a/tecochat-retrospective-3.html b/tecochat-retrospective-3.html index 825cbadb2..fdf320e46 100644 --- a/tecochat-retrospective-3.html +++ b/tecochat-retrospective-3.html @@ -13,11 +13,11 @@ - - + + -

    [테코챗] 3. 기능 구현

    · 약 5분

    개요

    +

    [테코챗] 3. 기능 구현

    · 약 5분

    개요

    원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
    레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

    나의 채팅 확인하고 이어하는 기능

    @@ -29,7 +29,7 @@

    좋아요와 댓글 기능

    누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
    또한 댓글 추가 및 삭제 기능도 추가했다.

    키워드 추출

    -

    어떻게 키워드 추출을 할지 고민을 많이 했는데, 일단 GPT를 이용해서 키워드를 추출하기로 했다.
    +

    어떻게 키워드 추출을 할지 고민을 많이 했는데, 일단 GPT를 이용해서 키워드를 추출하기로 했다.
    해당 부분은 첫 질문에 대한 키워드만 추출하도록 했다.
    백엔드에선 말랑이 이벤트 이용해서 첫 채팅 요청이 이루어지면, 비동기로 키워드를 추출하는 질문을 추가로 날리도록 구현하였다.
    CSV 형식으로 GPT에게 답변을 입력해달라고 요청받는데, 이 부분이 문제(프롬프트 엔지니어링 부분이 반환된다.)가 좀 있는 것 같아서 개선이 필요한 것 같다.

    @@ -45,7 +45,7 @@

    사용성 고려하기

    제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

    향후 계획

    실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
    -크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
    -일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

    +크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
    +일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

    \ No newline at end of file diff --git a/test-double.html b/test-double.html index 74c74dce9..f2ae438f8 100644 --- a/test-double.html +++ b/test-double.html @@ -13,11 +13,11 @@ - - + + -

    테스트 대역

    · 약 5분

    테스트 대역이란?

    +

    테스트 대역

    · 약 5분

    테스트 대역이란?

    모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
    Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

    테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
    @@ -31,7 +31,7 @@

    더미(Dummy)

    기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
    만약 메서드가 무언가 반환을 해야하는 경우 0, null과 같은 값을 반환한다.

    스텁(Stub)

    -

    시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
    +

    시나리오마다 다른 값(미리 준비 된 결과)을 반환한다.
    이를 통해 특정 조건에서 메서드가 예상한대로 동작하는지 확인할 수 있다.

    스파이(Spy)

    스텁과 유사하지만 호출 여부를 기록하거나 호출할 때 전달한 인자값을 기록할 수 있다.
    @@ -48,7 +48,7 @@

    가짜(Fake)

    상호작용에 따른 목과 스텁 구분

    단위 테스트 p.149 에서는 테스트 대역을 크게 목과 스텁으로 구분한다.
    목은 SUT와 관련된 상호작용을 모방하고 검사하는 반면, 스텁은 단순 모방만 한다.

    -
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색
    +
    TestDoubleMockStub
    포함 유형목, 스파이스텁, 더미, 페이크
    용도외부로 나가는 상호작용을 모방하고 검사하는 데 사용내부로 들어오는 상호작용을 모방하는 데 사용
    설명SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당
    예시이메일 발송데이터 검색

    테스트 대상 시스템
    테스트를 하려는 대상

    참고 자료

    @@ -57,6 +57,6 @@

    참고 자료

    테스트 주도 개발 시작하기 - 7장 대역, 최범균
    테스트 더블, Martin Fowler
    테스트 관련 용어 정리, Johngrib
    -Test Double, Gerard Meszaros

    +Test Double, Gerard Meszaros

    \ No newline at end of file diff --git a/the-essence-of-object-orientation.html b/the-essence-of-object-orientation.html index 989bfcfad..6bcc4a621 100644 --- a/the-essence-of-object-orientation.html +++ b/the-essence-of-object-orientation.html @@ -13,11 +13,11 @@ - - + + -

    [책] 객체지향의 사실과 오해

    · 약 6분

    책 정보

    +

    [책] 객체지향의 사실과 오해

    · 약 6분

    책 정보

    객체지향의 사실과 오해
    조영호

    @@ -38,7 +38,7 @@

    책임의 자율성을
    • 요청하는 객체가 몰라도 되는 부분이 캡슐화됨으로 인터페이스와 구현의 분리
    -

    책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않는다.

    +

    책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않는다.

    • 변경의 파급효과를 객체 내부로 캡슐화 → 메시지를 보내는 객체와의 결합도 저하
    @@ -68,7 +68,7 @@

    밑줄 친 문장들

    시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법

    자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.

    객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.

    -

    객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다. +

    객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다. p.35

    @@ -87,6 +87,6 @@

    밑줄 친 문장들

    ’어떤 행위(What)’를 수행할 것인지 결정한 후 ‘누가(who)’ 그 행위를 수행할 것인지 결정해야 한다. 여기서 ‘어떤 행위’가 바로 메시지다. p.158

    -
    +
    \ No newline at end of file diff --git a/tomcat-retrospective.html b/tomcat-retrospective.html index 7f52e5253..bc7d80d07 100644 --- a/tomcat-retrospective.html +++ b/tomcat-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    톰캣 구현 미션 회고

    · 약 13분

    1, 2단계: https://github.com/woowacourse/jwp-dashboard-http/pull/302
    +

    톰캣 구현 미션 회고

    · 약 13분

    1, 2단계: https://github.com/woowacourse/jwp-dashboard-http/pull/302
    3, 4단계: https://github.com/woowacourse/jwp-dashboard-http/pull/431

    톰캣 구현

    우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
    @@ -25,7 +25,7 @@

    톰캣 구현

    이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
    톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

    다이어그램

    -

    Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
    +

    Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
    사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
    또한 적절하게 인터페이스를 사용하여 의존성 방향을 단방향으로 하려고 노력했다.

    참고 자료 ETag, mdn
    Apache Tomcat 8 Configuration Reference
    Apache Tomcat Tuning, Terry Cho
    -maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

    +maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

    \ No newline at end of file diff --git a/transaction-and-isolation.html b/transaction-and-isolation.html index eb8d6350c..20fd1cf3a 100644 --- a/transaction-and-isolation.html +++ b/transaction-and-isolation.html @@ -13,11 +13,11 @@ - - + + -

    트랜잭션과 격리수준

    · 약 10분

    트랜잭션(Transaction)

    +

    트랜잭션과 격리수준

    · 약 10분

    트랜잭션(Transaction)

    데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
    트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
    논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

    @@ -28,7 +28,7 @@

    트랜잭션의 속성(ACID)

    지속성(Durability): 트랜잭션이 성공적으로 완료된다면 영구적으로 결과에 반영되어야 한다.

    트랜잭션 주의사항

    트랜잭션은 꼭 필요한 최소의 코드에만 적용하는 것이 좋다.(트랜잭션의 범위를 최소화하라)
    -구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

    +구현해야 하는 업무에 따라 트랜잭션을 묶거나 트랜잭션에서 제외하고, 네트워크 작업이 있는 경우 반드시 트랜잭션에서 배제해야 한다.

    데이터의 일관성과 안전성을 보장하기 위해 배제해야 한다.
    네트워크 작업을 트랜잭션 내부에 포함한다면 다음과 같은 문제가 발생할 수 있다.

    • 네트워크 작업이 중간에 실패할 가능성(안전성 X)
    • @@ -145,6 +145,6 @@

      팬텀 리드(Phantom read, Phant Database->>+Bob: 2">

      참고 자료

      Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
      -Isolation Level, MySQL

    +Isolation Level, MySQL

    \ No newline at end of file diff --git a/web-application-evolution.html b/web-application-evolution.html index 7d44d05df..5c5a164fe 100644 --- a/web-application-evolution.html +++ b/web-application-evolution.html @@ -13,11 +13,11 @@ - - + + -

    웹 애플리케이션 발전 과정

    · 약 8분

    웹 애플리케이션 발전 과정

    +

    웹 애플리케이션 발전 과정

    · 약 8분

    웹 애플리케이션 발전 과정

    웹 애플리케이션의 발전 과정 대한 구구의 강의가 있었다.
    간단하게 정리하자면 다음과 같은 흐름으로 웹 애플리케이션이 발전했다.
    원래 회고에 작성하려고 했지만, 정리하다 보니 조금 길어져서 따로 분리했다.

    @@ -28,7 +28,7 @@

    WWW(1989)

    CGI(1993)

    CGI는 동적 콘텐츠를 제공하기 위한 규약으로, 해당 인터페이스를 구현한 스크립트를 이용해서 매 요청마다 프로세스를 실행시켜 정보를 반환하도록 한다. 하지만 매 요청마다 프로세스를 실행시키기 때문에 서버에 많은 부하가 발생할 수 있다. 따라서 이러한 단점을 극복하기 위해 나온 것이 Servlet이다.

    Servlet(1996)

    -

    Servlet은 웹 서버에서 실행되는 자바 프로그램으로 HTTP를 이용하여 웹 클라이언트의 요청을 수신하고 응답한다. CGI와 다르게 매 요청마다 프로세스가 아닌 스레드를 생성하여 응답한다.
    +

    Servlet은 웹 서버에서 실행되는 자바 프로그램으로 HTTP를 이용하여 웹 클라이언트의 요청을 수신하고 응답한다. CGI와 다르게 매 요청마다 프로세스가 아닌 스레드를 생성하여 응답한다.
    하지만 View 영역의 코드를 작성하기 위해 Servlet의 소스 코드를 알아야 하는 등 복잡도가 너무 높았다. 따라서 해당 문제를 해결하기 위해 JSP가 등장했다.

    JSP(1999)

    JSP는 HTML에 자바 코드를 작성하여 동적 웹 페이지를 생성하는 기술로, 유사한 기술로는 ASP, PHP가 있다.
    @@ -51,8 +51,8 @@

    MVC(2000)

    이때 MVC 패턴이 처음 탄생한 것은 아니고, 서버 측 구현이라고 하는 것을 보니 MVC가 처음 등장한 건 아닌 것 같다.
    해당 문서를 보면 MVC라는 용어의 등장은 1978년에 등장한 것으로 보인다.

    Spring Framework(2003)

    -

    Spring은 복잡했던 J2EE을 대체하기 위해 2003년에 등장했다.
    -J2EE는 웹 기반의 엔터프라이즈 애플리케이션을 구축하기 위한 플랫폼으로 위에서 설명한 Servlet, JSP, EJB 등의 기술을 포함하고 있다.
    +

    Spring은 복잡했던 J2EE을 대체하기 위해 2003년에 등장했다.
    +J2EE는 웹 기반의 엔터프라이즈 애플리케이션을 구축하기 위한 플랫폼으로 위에서 설명한 Servlet, JSP, EJB 등의 기술을 포함하고 있다.
    하지만 이중 EJB라는 기술이 J2EE의 핵심 기술이었는데, 해당 기술이 매우 복잡했기 때문에 사용에 문제가 많았다고 한다.
    2002년에 Rod Johnson이 EJB를 사용하지 않고 J2EE 애플리케이션을 구축하는 방법에 대해 저술한 Expert One-to-One J2EE Development라는 책을 발행했고, 출간 후 Juergen Hoeller, Yann Caroff가 Rod Johnson에게 오픈소스 제안을 하여 스프링이 탄생했다고 한다.

    스프링은 엔터프라이즈 서비스 기능을 POJO에 제공하며, 이 덕분에 스프링을 사용하여 비즈니스 로직에 집중할 수 있다.

    @@ -60,7 +60,7 @@

    WebFlux 이전 Servlet 3.0(2009),

    Tomcat의 NIO 동작 방식을 보면 Poller가 소켓 커넥션을 들고 있다가 처리가 가능할 때 스레드를 할당하는 식으로 처리를 한다. 하지만 할당 후 Servlet과 통신하는 부분은 블로킹 방식으로 요청이 끝날 때까지 스레드를 점유하고 있었고, 스레드 점유로 인해 요청이 max thread에 도달하면 요청을 처리할 수 없었다.
    그래서 비동기 방식의 Servlet이 Servlet 3.0에 등장했다. 하지만 전통적인 I/O 방식을 사용하는 부분은 블로킹 방식으로 동작했다. Servlet 3.1에서 논블로킹 I/O가 추가되었지만, 많이 사용되지 않았다고 한다.

    Spring WebFlux(2017)

    -

    적은 수의 스레드로 동시성을 처리하고, 적은 리소스로 확장이 가능한 논블로킹 방식의 웹 기술이 필요했고, 기존의 Servlet의 경우 비동기를 지원한다 해도 동기식 API들이 많이 남아있었기 때문에 이러한 Servlet에 영향을 받지 않는 기술이 필요했다. 또한 기존에 Netty와 같이 비동기, 논블로킹 방식 서버로 자리를 잘 잡은 서버를 위해 Spring WebFlux가 등장했다.
    +

    적은 수의 스레드로 동시성을 처리하고, 적은 리소스로 확장이 가능한 논블로킹 방식의 웹 기술이 필요했고, 기존의 Servlet의 경우 비동기를 지원한다 해도 동기식 API들이 많이 남아있었기 때문에 이러한 Servlet에 영향을 받지 않는 기술이 필요했다. 또한 기존에 Netty와 같이 비동기, 논블로킹 방식 서버로 자리를 잘 잡은 서버를 위해 Spring WebFlux가 등장했다.
    추가로 데이터 접근을 위해 사용하는 JDBC의 경우 Blocking API라, Spring Webflux에서는 R2DBC를 사용한다고 한다.

    마치며

    해당 정리 내용의 경우 Async, Non Blocking 관련된 내용을 깊게 공부한 적이 없어서 정확하지 않을 수 있다.
    @@ -76,6 +76,6 @@

    참고 자료

    Asynchronous processing support in Servlet 3.0, Dr. Xinyu Liu WebFlux Overview, Spring Spring WebFlux와 Armeria를 이용하여 Microservice에 필요한 Reactive + RPC 동시에 잡기, Naver D2
    -Spring WebFlux란 무엇일까

    +Spring WebFlux란 무엇일까

    \ No newline at end of file diff --git a/web-racing-car-retrospective.html b/web-racing-car-retrospective.html index 8045ac9b5..ae29aa427 100644 --- a/web-racing-car-retrospective.html +++ b/web-racing-car-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    웹 자동차 미션 회고

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-racingcar/pull/24
    +

    웹 자동차 미션 회고

    · 약 4분

    1단계: https://github.com/woowacourse/jwp-racingcar/pull/24
    2단계: https://github.com/woowacourse/jwp-racingcar/pull/128

    웹 자동차 미션

    사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
    @@ -27,8 +27,8 @@

    웹 자동차 미션

    첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
    난이도 높은 미션이 아니었지만 리뷰어인 라빈에게 칭찬을 많이 받아서 기분이 좋았다.
    라빈 감사합니다!

    -

    부족했던 부분

    -

    컨디션도 좋지 않고 열정도 식은 것 같은 느낌이 들었다.
    +

    부족했던 부분

    +

    컨디션도 좋지 않고 열정도 식은 것 같은 느낌이 들었다.
    미션이 다소 여유롭다고 느껴져서, 시간에 대한 부분도 잘 관리하지 못한 것 같다.
    미션에 잘 집중하지 못해서 페어에게 많이 미안했고, 나 자신에게 아쉬웠던 부분이 많았다.

    지난번 회고를 다시 보는데 집중을 잘 못한 경우가 많은 것 같다.
    @@ -54,8 +54,8 @@

    페어에게 배울 부분

    근육맨 비버라 그런지 체력이 좋아서 그런가?
    중간에 잘 안 쉬고도 집중해서 미션을 진행하는 걸 보고 대단하다고 생각했다.

    학습에 대한 열정
    -추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
    +추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
    비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
    -나도 5월부터 조금 더 화이팅 해야겠다.

    +나도 5월부터 조금 더 화이팅 해야겠다.

    \ No newline at end of file diff --git a/websocket.html b/websocket.html index 721865915..cdaadf1d0 100644 --- a/websocket.html +++ b/websocket.html @@ -13,11 +13,11 @@ - - + + -

    웹소켓

    · 약 5분

    웹소켓

    +

    웹소켓

    · 약 5분

    웹소켓

    단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
    웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

    웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

    @@ -27,7 +27,7 @@

    웹소켓 등장 배경

    Polling: 주기적으로 서버에 요청을 보내 수신할 정보가 있는지 확인하는 방법

    • 서버에서 보낼 내용이 없어도 클라이언트는 알 수 없다.
    • 계속해서 요청을 보내 확인을 해야하기 때문에 서버에 불필요한 부하를 주어야 한다.
    • -

    Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

      +

    Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

    • 폴링 방식보다 서버에 적은 부하를 줄 수 있지만, 요청의 주기가 짧으면 폴링과 차이가 없어진다.

    Streaming: 클라이언트가 request를 보내면 커넥션을 맺고, 이 커넥션을 유지하면서 서버가 계속 데이터를 보내는 방법

    • 클라이언트가 서버에 요청을 하고 싶다면 새로운 커넥션을 맺어야 한다.
    • @@ -61,7 +61,7 @@

      1. Upgrade 요청

      Origin: http://localhost:8080

    2. Switching Protocols

    -

    서버는 101 Switching Protocols 응답을 반환한다.
    +

    서버는 101 Switching Protocols 응답을 반환한다.
    Sec-WebSocket-Accept은 Sec-WebSocket-Key 뒤에 258EAFA5-E914-47DA-95CA-C5AB0DC85B11를 붙이고 SHA1로 해싱 후 Base64로 인코딩하여 반환한다.
    이는 서버 웹소켓 프로토콜의 지원 여부를 클라이언트에게 명확히 알리기 위해 존재한다.

    HTTP/1.1 101 Switching Protocols 
    @@ -77,6 +77,6 @@ 

    참고 자료

    https://datatracker.ietf.org/doc/html/rfc6455
    https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
    https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
    -https://docs.spring.io/spring-framework/reference/web/websocket.html

    +https://docs.spring.io/spring-framework/reference/web/websocket.html

    \ No newline at end of file diff --git a/woowacourse-level1-retrospective.html b/woowacourse-level1-retrospective.html index 5e254db4f..2159a3b3e 100644 --- a/woowacourse-level1-retrospective.html +++ b/woowacourse-level1-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    우아한테크코스 레벨 1 회고

    · 약 8분

    레벨 1이 끝났다.
    +

    우아한테크코스 레벨 1 회고

    · 약 8분

    레벨 1이 끝났다.
    우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
    혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
    하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

    @@ -29,7 +29,7 @@

    Keep

    소화능력이 부족하기 때문에 점심은 도시락(그래봤자 계란2개)을 준비하고
    항상 똑같은 컨디션을 유지하기 위해 항상 6시에 집에 간다.
    이제 바빠질 테니 일찍 집에 가는 일은 어쩔 수 없이 줄어들겠지만😢

    -

    선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

    +

    선택도 비용이다. 앞으로 의사결정이 필요 없는 부분을 최대한 많이 만들어야겠다.

    크루들과 친하게 지내기

    10명 정도의 크루의 닉네임을 외우고 친하게 지낸다면 성공적이라고 생각했었다.
    하다 보니 더 많은 크루들의 닉네임을 외운 것 같다.
    @@ -52,9 +52,9 @@

    Keep

    우아한테크코스 생활을 하면서 다른 크루가 질문했을 때, 최대한 이해하기 쉽게 설명하려고 했던 경험이 도움이 된 것 같다.
    이후 레벨 인터뷰를 진행할 때 다음과 같은 부분을 고려하면 더 좋을 것 같다.

      -
    • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
    • +
    • 대답하면서 질문을 계속 생각하며 잊어버리지 말기
    • 두괄식 표현
    • -
    • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
    • +
    • 설명하다가 잘못 설명한 것 같으면 다 끊고 다시 이야기해도 될지 물어보기
    • 설명할 수 있을만큼 시간 충분히 가지기
    • 인터뷰어의 질문 의도를 명확히 이해하지 못했다면 의도 다시 물어보기
    • 끝맺는 부분 연습하기(자신감 있게)
    • @@ -78,12 +78,12 @@

      Try

      참여하는 사람이 있을지, 안 좋게 보는 게 아닐지 걱정되지만 그래도 재밌을 것 같다.
      저랑 허브티 한잔 하실래요?

      기술적인 부분

      -

      우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
      +

      우아한테크코스 생활을 하면서 소프트 스킬에 조금 더 무게를 두다 보니 이론적인 부분이 부족할 수 있다고 생각했다.
      시간의 여유가 될 때 책을 조금씩 읽어야겠다.
      블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

      레벨 1을 마무리하며

      시간이 빠르게 흘러갔다.
      타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
      -또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

    +또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

    \ No newline at end of file diff --git a/woowacourse-level2-retrospective.html b/woowacourse-level2-retrospective.html index 16caa9c8d..8b19b0db1 100644 --- a/woowacourse-level2-retrospective.html +++ b/woowacourse-level2-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    우아한테크코스 레벨 2 회고

    · 약 3분

    23년의 6월이 오고, 레벨 2가 끝났다.
    +

    우아한테크코스 레벨 2 회고

    · 약 3분

    23년의 6월이 오고, 레벨 2가 끝났다.
    빠르게 지나가서 조금 아쉽다.

    학습

    회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
    @@ -38,6 +38,6 @@

    협업

    팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

    레벨 2를 마무리하며

    회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. -읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

    +읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

    \ No newline at end of file diff --git a/woowacourse-level3-retrospective.html b/woowacourse-level3-retrospective.html index c5366e8e7..6527919d9 100644 --- a/woowacourse-level3-retrospective.html +++ b/woowacourse-level3-retrospective.html @@ -13,11 +13,11 @@ - - + + -

    우아한테크코스 레벨 3 회고

    · 약 4분

    회고

    +

    우아한테크코스 레벨 3 회고

    · 약 4분

    회고

    지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
    레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
    부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
    @@ -49,6 +49,6 @@

    좋았던 점

    100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

    마치며

    플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
    -안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

    +안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

    \ No newline at end of file