류윤주 류윤주 2024-02-22
240222 류윤주 커밋
@7a706f02573f4a56b773d7bfa8a72cd419ed38e0
 
client/resources/css/common.css (added)
+++ client/resources/css/common.css
@@ -0,0 +1,468 @@
+@charset "utf-8";
+
+/* 마진 */
+.ml0 {
+    margin-left: 0px;
+}
+
+.ml5 {
+    margin-left: 5px;
+}
+
+.ml10 {
+    margin-left: 10px;
+}
+
+.ml20 {
+    margin-left: 20px;
+}
+
+.ml30 {
+    margin-left: 30px;
+}
+
+.ml40 {
+    margin-left: 40px;
+}
+
+.ml50 {
+    margin-left: 50px;
+}
+
+.ml60 {
+    margin-left: 60px;
+}
+
+.ml70 {
+    margin-left: 70px;
+}
+
+.ml80 {
+    margin-left: 80px;
+}
+
+.ml90 {
+    margin-left: 90px;
+}
+
+.ml100 {
+    margin-left: 100px;
+}
+
+.mr0 {
+    margin-right: 0px;
+}
+
+.mr5 {
+    margin-right: 5px;
+}
+
+.mr10 {
+    margin-right: 10px;
+}
+
+.mr20 {
+    margin-right: 20px;
+}
+
+.mr30 {
+    margin-right: 30px;
+}
+
+.mr40 {
+    margin-right: 40px;
+}
+
+.mr50 {
+    margin-right: 50px;
+}
+
+.mr60 {
+    margin-right: 60px;
+}
+
+.mr70 {
+    margin-right: 70px;
+}
+
+.mr80 {
+    margin-right: 80px;
+}
+
+.mr90 {
+    margin-right: 90px;
+}
+
+.mr100 {
+    margin-right: 100px;
+}
+
+.mt0 {
+    margin-top: 0px;
+}
+
+.mt5 {
+    margin-top: 5px;
+}
+
+.mt10 {
+    margin-top: 10px;
+}
+
+.mt20 {
+    margin-top: 20px;
+}
+
+.mt30 {
+    margin-top: 30px;
+}
+
+.mt40 {
+    margin-top: 40px;
+}
+
+.mt50 {
+    margin-top: 50px;
+}
+
+.mt60 {
+    margin-top: 60px;
+}
+
+.mt70 {
+    margin-top: 70px;
+}
+
+.mt80 {
+    margin-top: 80px;
+}
+
+.mt90 {
+    margin-top: 90px;
+}
+
+.mt100 {
+    margin-top: 100px;
+}
+
+.mb0 {
+    margin-bottom: 0px;
+}
+
+.mb5 {
+    margin-bottom: 5px;
+}
+
+.mb10 {
+    margin-bottom: 10px;
+}
+
+.mb20 {
+    margin-bottom: 20px;
+}
+
+.mb30 {
+    margin-bottom: 30px;
+}
+
+.mb40 {
+    margin-bottom: 40px;
+}
+
+.mb50 {
+    margin-bottom: 50px;
+}
+
+.mb60 {
+    margin-bottom: 60px;
+}
+
+.mb70 {
+    margin-bottom: 70px;
+}
+
+.mb80 {
+    margin-bottom: 80px;
+}
+
+.mb90 {
+    margin-bottom: 90px;
+}
+
+.mb100 {
+    margin-bottom: 100px;
+}
+
+/* 패딩 */
+.pd0 {
+    padding: 0;
+}
+
+.pd5 {
+    padding: 5px;
+}
+
+.pd10 {
+    padding: 10px;
+}
+
+.pd15 {
+    padding: 15px;
+}
+
+
+.pd20 {
+    padding: 20px;
+}
+
+.pd30 {
+    padding: 30px;
+}
+
+.pd40 {
+    padding: 40px;
+}
+
+.pd50 {
+    padding: 50px;
+}
+
+.pd60 {
+    padding: 60px;
+}
+
+.pd70 {
+    padding: 70px;
+}
+
+.pd80 {
+    padding: 80px;
+}
+
+.pd90 {
+    padding: 90px;
+}
+
+.pd100 {
+    padding: 100px;
+}
+
+.pt0 {
+    padding-top: 0;
+}
+
+.pt5 {
+    padding-top: 5px;
+}
+
+.pt10 {
+    padding-top: 10px;
+}
+
+.pt20 {
+    padding-top: 20px;
+}
+
+.pt30 {
+    padding-top: 30px;
+}
+
+.pt40 {
+    padding-top: 40px;
+}
+
+.pt50 {
+    padding-top: 50px;
+}
+
+.pt60 {
+    padding-top: 60px;
+}
+
+.pt70 {
+    padding-top: 70px;
+}
+
+.pt80 {
+    padding-top: 80px;
+}
+
+.pt90 {
+    padding-top: 90px;
+}
+
+.pt100 {
+    padding-top: 100px;
+}
+
+.pb0 {
+    padding-bottom: 0;
+}
+
+.pb5 {
+    padding-bottom: 5px;
+}
+
+.pb10 {
+    padding-bottom: 10px;
+}
+
+.pb20 {
+    padding-bottom: 20px;
+}
+
+.pb30 {
+    padding-bottom: 30px;
+}
+
+.pb40 {
+    padding-bottom: 40px;
+}
+
+.pb50 {
+    padding-bottom: 50px;
+}
+
+.pb60 {
+    padding-bottom: 60px;
+}
+
+.pb70 {
+    padding-bottom: 70px;
+}
+
+.pb80 {
+    padding-bottom: 80px;
+}
+
+.pb90 {
+    padding-bottom: 90px;
+}
+
+.pb100 {
+    padding-bottom: 100px;
+}
+
+.pl0 {
+    padding-left: 0;
+}
+
+.pl5 {
+    padding-left: 5px;
+}
+
+.pl10 {
+    padding-left: 10px;
+}
+
+.pl15 {
+    padding-left: 15px;
+}
+
+.pl20 {
+    padding-left: 20px;
+}
+
+.pl30 {
+    padding-left: 30px;
+}
+
+.pl40 {
+    padding-left: 40px;
+}
+
+.pl50 {
+    padding-left: 50px;
+}
+
+.pl60 {
+    padding-left: 60px;
+}
+
+.pl70 {
+    padding-left: 70px;
+}
+
+.pl80 {
+    padding-left: 80px;
+}
+
+.pl90 {
+    padding-left: 90px;
+}
+
+.pl100 {
+    padding-left: 100px;
+}
+
+.pr0 {
+    padding-right: 0;
+}
+
+.pr5 {
+    padding-right: 5px;
+}
+
+.pr10 {
+    padding-right: 10px;
+}
+
+.pr15 {
+    padding-right: 15px;
+}
+
+.pr20 {
+    padding-right: 20px;
+}
+
+.pr30 {
+    padding-right: 30px;
+}
+
+.pr40 {
+    padding-right: 40px;
+}
+
+.pr50 {
+    padding-right: 50px;
+}
+
+.pr60 {
+    padding-right: 60px;
+}
+
+.pr70 {
+    padding-right: 70px;
+}
+
+.pr80 {
+    padding-right: 80px;
+}
+
+.rb90 {
+    padding-right: 90px;
+}
+
+.pr100 {
+    padding-right: 100px;
+}
+
+
+/* text 정렬 */
+.text-lf {
+    text-align: left;
+}
+
+.text-ct {
+    text-align: center;
+}
+
+.text-rg {
+    text-align: right;
+}
+
+
+/* 기타 공용 */
+.cursor {
+    cursor: pointer;
+}(No newline at end of file)
 
client/resources/css/component.css (added)
+++ client/resources/css/component.css
@@ -0,0 +1,275 @@
+@charset "utf-8";
+
+/* btn */
+.small-btn {
+    width: 120px;
+    padding: 5px 10px;
+    border-radius: 5px;
+    font-size: 1.3rem;
+}
+.comment-btn{
+    padding: 10px;
+    font-size: 1.3rem;
+    border-radius: 0 5px 5px 0;
+}
+.large-btn {
+    width: 100%;
+    padding: 5px 15px;
+    border-radius: 5px;
+}
+
+.icon-btn {
+    padding: 5px;
+    border-radius: 50%;
+}
+
+.close-btn{
+    font-size: 1.6rem;
+    font-weight: 900;
+}
+.btn,
+.logout-btn{
+    position: relative;
+    font-size: 1.4rem;
+}
+.logout-btn::before {
+    content: "";
+    width: 1px;
+    height: 10px;
+    position: absolute;
+    top: 50%;
+    left: 0;
+    transform: translateY(-50%);
+    background-color: #aaa;
+}
+
+.close-btn {
+    color: #d6def6;
+}
+
+.blue-btn,
+.blue-border-btn:hover {
+    background-color: var(--blue);
+    color: var(--white);
+    transition: all 0.3s ease-in-out;
+}
+
+.red-btn,
+.red-border-btn:hover {
+    background-color: var(--red);
+    color: var(--white);
+    transition: all 0.3s ease-in-out;
+}
+
+.green-btn,
+.green-border-btn:hover {
+    background-color: var(--green);
+    color: var(--white);
+    transition: all 0.3s ease-in-out;
+}
+
+.orange-btn,
+.orange-border-btn:hover {
+    background-color: var(--orange);
+    color: var(--white);
+    transition: all 0.3s ease-in-out;
+}
+
+.darkg-btn,
+.darkg-border-btn:hover {
+    background-color: var(--dark);
+    color: var(--white);
+    transition: all 0.3s ease-in-out;
+}
+
+.gray-btn,
+.gray-border-btn:hover {
+    background-color: #eee;
+    color: #333;
+    transition: all 0.3s ease-in-out;
+}
+
+
+.blue-border-btn {
+    border: 1px solid var(--blue);
+    color: var(--blue);
+    background-color: var(--white);
+}
+
+.red-border-btn {
+    border: 1px solid var(--red);
+    color: var(--red);
+    background-color: var(--white);
+}
+
+.green-border-btn {
+    border: 1px solid var(--green);
+    color: var(--green);
+    background-color: var(--white);
+}
+
+.orange-border-btn {
+    border: 1px solid var(--orange);
+    ;
+    color: var(--orange);
+    background-color: var(--white);
+}
+
+.darkg-border-btn {
+    border: 1px solid #434343;
+    color: #434343;
+    background-color: var(--white);
+}
+
+.gray-border-btn {
+    border: 1px solid #aaa;
+    color: #aaa;
+    background-color: var(--white);
+}
+
+.white-border-btn {
+    border: 1px solid var(--white);
+    color: var(--white);
+    background-color: transparent;
+}
+
+.tp-btn {
+    background-color: transparent;
+    width: 15px;
+    height: 15px;
+    margin-left: 10px;
+}
+
+button:disabled {
+    background-color: #eee;
+    color: #333;
+}
+
+/* 모달 */
+.modal-wrapper {
+    background-color: rgba(0, 0, 0, 0.5);
+    position: fixed;
+    width: 100%;
+    height: 100%;
+    top: 0;
+    left: 0;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    z-index: 11000;
+}
+
+.modal-container {
+    background: #fff;
+    min-width: 500px;
+    width: 30%;
+    height:80%;
+    border-radius: 5px;
+    display: grid;
+    grid-template-rows: auto 1fr auto;
+    padding: 20px;
+    box-sizing: border-box;
+    max-height: 95%;
+    min-height: 500px;
+}
+
+.modal-title {
+    width: 100%;
+    border-bottom: 1px solid #d4cccc;
+    padding: 10px 0;
+}
+
+.modal-subtitle {
+    font-size: 1.3rem;
+    font-weight: 600;
+}
+
+.modal-content-monthly {
+    width: 100%;
+    padding: 20px 0;
+    overflow-y: auto;
+}
+
+.large-modal {
+    width: 90%;
+}
+
+.small-modal {
+    min-width: 200px;
+    min-height: 200px;
+    max-width: 450px;
+    height: auto;
+    max-height: 50%;
+}
+
+.list-modal {
+    width: 80%;
+    height: 80%;
+}
+
+.alert-write {
+    font-size: 1.6rem;
+    line-height: 180%;
+}
+
+
+.modal-content-monthly::-webkit-scrollbar {
+    width: 10px;
+}
+
+.modal-content-monthly::-webkit-scrollbar-thumb {
+    background-color: #6b6b6b;
+    border-radius: 10px;
+    background-clip: padding-box;
+    border: 2px solid transparent;
+}
+
+.modal-content-monthly::-webkit-scrollbar-track {
+    background-color: #eee;
+    border-radius: 10px;
+    box-shadow: inset 0px 0px 5px white;
+}
+
+.modal-end {
+    width: 100%;
+    padding: 15px 0;
+    border-top: 1px solid #eee;
+}
+
+.alert-modal .modal-end button,
+.small-modal .modal-end button {
+    margin-left: 0;
+}
+
+.full-input,
+.full-select {
+    width: 100%;
+}
+
+
+/* auto list */
+.input-group{
+    position: relative;
+}
+.auto-list{
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    transform: translateY(100%);
+    width: 100%;
+    max-height: 200px;
+    overflow-y: auto;
+    border-radius: 0 0 5px 5px;
+    /* background-color: var(--white);
+    padding: 10px;
+    border: 1px solid #eee; */
+}
+
+.auto-list li{
+    font-size: 1.3rem;
+    margin-bottom: 5px;
+}
+
+.auto-list li:last-child{
+    margin-bottom: 0;
+}(No newline at end of file)
 
client/resources/css/font.css (added)
+++ client/resources/css/font.css
@@ -0,0 +1,27 @@
+@font-face {
+    font-family: 'Pretendard';
+    src: url('../font/PretendardVariable.woff2') format('woff');
+    font-weight: 400;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: "GmarketSansM";
+    src: url("/client/resources/font/GmarketSansMedium.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: "GmarketSansL";
+    src: url("/client/resources/font/GmarketSansLight.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: "GmarketSansB";
+    src: url("/client/resources/font/GmarketSansBold.woff") format("woff");
+    font-weight: bold;
+    font-style: normal;
+}(No newline at end of file)
 
client/resources/css/grid.css (added)
+++ client/resources/css/grid.css
@@ -0,0 +1,333 @@
+@charset "utf-8";
+
+.container {
+    width: 100%;
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+}
+
+@media (min-width: 576px) {
+    .container {
+        max-width: 540px;
+    }
+}
+
+@media (min-width: 768px) {
+    .container {
+        max-width: 720px;
+    }
+}
+
+@media (min-width: 992px) {
+    .container {
+        max-width: 960px;
+    }
+}
+
+@media (min-width: 1200px) {
+    .container {
+        max-width: 1140px;
+    }
+}
+
+
+.flex {
+    display: flex;
+    flex-wrap: wrap;
+}
+
+.flex-column {
+    display: flex;
+    flex-direction: column;
+}
+
+.no-gutters {
+    margin-right: 0;
+    margin-left: 0;
+}
+
+
+.no-gutters>.col,
+.no-gutters>[class*="col-"] {
+    padding-right: 0;
+    padding-left: 0;
+}
+
+.col-1,
+.col-2,
+.col-3,
+.col-4,
+.col-5,
+.col-6,
+.col-7,
+.col-8,
+.col-9,
+.col-10,
+.col-11,
+.col-12,
+.col,
+.col-auto,
+.col-sm-1,
+.col-sm-2,
+.col-sm-3,
+.col-sm-4,
+.col-sm-5,
+.col-sm-6,
+.col-sm-7,
+.col-sm-8,
+.col-sm-9,
+.col-sm-10,
+.col-sm-11,
+.col-sm-12,
+.col-sm,
+.col-sm-auto,
+.col-md-1,
+.col-md-2,
+.col-md-3,
+.col-md-4,
+.col-md-5,
+.col-md-6,
+.col-md-7,
+.col-md-8,
+.col-md-9,
+.col-md-10,
+.col-md-11,
+.col-md-12,
+.col-md,
+.col-md-auto,
+.col-lg-1,
+.col-lg-2,
+.col-lg-3,
+.col-lg-4,
+.col-lg-5,
+.col-lg-6,
+.col-lg-7,
+.col-lg-8,
+.col-lg-9,
+.col-lg-10,
+.col-lg-11,
+.col-lg-12,
+.col-lg,
+.col-lg-auto,
+.col-xl-1,
+.col-xl-2,
+.col-xl-3,
+.col-xl-4,
+.col-xl-5,
+.col-xl-6,
+.col-xl-7,
+.col-xl-8,
+.col-xl-9,
+.col-xl-10,
+.col-xl-11,
+.col-xl-12,
+.col-xl,
+.col-xl-auto {
+    position: relative;
+    width: 100%;
+    min-height: 1px;
+    padding-right: 10px;
+    padding-left: 10px;
+}
+
+
+.col {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+}
+
+.col-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+}
+
+.col-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+}
+
+.col-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+}
+
+.col-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+}
+
+.col-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+}
+
+.col-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+}
+
+.col-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+}
+
+.col-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+}
+
+.col-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+}
+
+.col-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+}
+
+.col-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+}
+
+.col-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+}
+
+.col-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+}
+
+
+
+.justify-start {
+    justify-content: flex-start;
+}
+
+.justify-center {
+    justify-content: center;
+}
+
+.justify-end {
+    justify-content: flex-end;
+}
+
+.justify-between {
+    justify-content: space-between;
+}
+
+.justify-around {
+    justify-content: space-around;
+}
+
+.align-start {
+    align-items: flex-start;
+}
+
+
+.align-center {
+    align-items: center;
+}
+
+.align-end {
+    align-items: flex-end;
+}
+
+.flex-auto {
+    flex: 0 0 auto;
+}
+
+.flex1 {
+    flex: 1;
+}
+
+.flex2 {
+    flex: 2;
+}
+
+.flex3 {
+    flex: 3;
+}
+
+.flex4 {
+    flex: 4;
+}
+
+.flex5 {
+    flex: 5;
+}
+
+.flex6 {
+    flex: 6;
+}
+
+.flex7 {
+    flex: 7;
+}
+
+.flex8 {
+    flex: 8;
+}
+
+
+.gap1 {
+    gap: 1%;
+}
+
+.gap2 {
+    gap: 2%;
+}
+
+.gap3 {
+    gap: 3%;
+}
+
+.gap4 {
+    gap: 4%;
+}
+
+.gap5 {
+    gap: 5%;
+}
+
+.gap6 {
+    gap: 6%;
+}
+
+.gap7 {
+    gap: 7%;
+}
+
+.gap8 {
+    gap: 8%;
+}
+
+.gap9 {
+    gap: 9%;
+}
+
+.gap10 {
+    gap: 10%;
+}(No newline at end of file)
 
client/resources/css/layout.css (added)
+++ client/resources/css/layout.css
@@ -0,0 +1,52 @@
+.mobile-layout {
+    display: grid;
+    grid-template-rows: auto 1fr auto;
+    grid-template-areas:
+        "header"
+        "main"
+        "nav "
+}
+
+
+header {
+    padding: 15px;
+    grid-area: header;
+    background-color: var(--blue);
+}
+
+.current-name{
+    color: var(--white);
+    font-size: 1.6rem;
+    font-weight: 600;
+}
+
+.main-menu {
+    background-color: var(--blue);
+    grid-area: nav;
+}
+
+.main-menu ul,
+.main-menu li {
+    list-style: none;
+}
+
+
+.main-menu ul li a {
+    color: #ddd;
+    text-decoration: none;
+    font-size: 1.2rem;
+    padding: 10px;
+}
+
+.main-menu ul li.active a {
+    color: var(--white);
+    border-radius: 5px;
+    font-weight: bold;
+}
+
+
+#pages {
+    padding: 15px 10px;
+    grid-area: main;
+    overflow-y: auto;
+}(No newline at end of file)
 
client/resources/css/reset.css (added)
+++ client/resources/css/reset.css
@@ -0,0 +1,223 @@
+@charset "utf-8";
+
+:root {
+    --blue: #005aab;
+    --skyblue: #f2f8ff;
+    --indigo: #6610f2;
+    --purple: #6f42c1;
+    --pink: #e83e8c;
+    --red: #dc3545;
+    --orange: #fd7e14;
+    --yellow: #ffc107;
+    --green: #28a745;
+    --teal: #20c997;
+    --cyan: #17a2b8;
+    --white: #fff;
+    --gray: #6c757d;
+    --gray-dark: #343a40;
+    --primary: #007bff;
+    --primary-lignt: #b7daff;
+    --secondary: #6c757d;
+    --success: #28a745;
+    --info: #17a2b8;
+    --main: #388d6e;
+    --warning: #ffc107;
+    --danger: #dc3545;
+    --light: #f8f9fa;
+    --dark: #343a40;
+    --light: #eeeeee;
+}
+
+/* box-sizing 규칙을 명시합니다. */
+*,
+*::before,
+*::after {
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+}
+
+/* 폰트 크기의 팽창을 방지합니다. */
+html {
+    -moz-text-size-adjust: none;
+    -webkit-text-size-adjust: none;
+    text-size-adjust: none;
+    font-size: 10px;
+}
+
+/* 기본 여백을 제거하여 작성된 CSS를 더 잘 제어할 수 있습니다. */
+body,
+h1,
+h2,
+h3,
+h4,
+p,
+figure,
+blockquote,
+dl,
+dd {
+    margin-block-end: 0;
+}
+
+/* list를 role값으로 갖는 ul, ol 요소의 기본 목록 스타일을 제거합니다. */
+ul,
+ol,
+li {
+    list-style: none;
+}
+
+/* 핵심 body의 기본값을 설정합니다. */
+body,
+#root,
+#App {
+    width: 100%;
+    height: 100vh;
+    font-family: 'Pretendard';
+    /* background-color: #f9f9f9; */
+}
+
+/* 제목 요소와 상호작용하는 요소에 대해 line-height를 더 짧게 설정합니다. */
+h1,
+h2,
+h3,
+h4,
+button,
+input,
+label {
+    line-height: 1.1;
+}
+
+/* 제목에 대한 text-wrap을 balance로 설정합니다. */
+h1,
+h2,
+h3,
+h4 {
+    text-wrap: balance;
+}
+
+/* 클래스가 없는 기본 a 태그 요소는 기본 스타일을 가져옵니다. */
+a:not([class]) {
+    text-decoration-skip-ink: auto;
+    color: currentColor;
+}
+
+/* 이미지 관련 작업을 더 쉽게 합니다. */
+img,
+picture {
+    max-width: 100%;
+    display: block;
+}
+
+svg {
+    vertical-align: bottom;
+}
+
+/* input 및 button 항목들이 글꼴을 상속하도록 합니다. */
+input,
+button,
+textarea,
+select {
+    font: inherit;
+}
+
+button {
+    background: inherit;
+    border: none;
+    box-shadow: none;
+    border-radius: 0;
+    padding: 0;
+    overflow: visible;
+    cursor: pointer
+}
+
+/* 행 속성이 없는 textarea가 너무 작지 않도록 합니다. */
+textarea:not([rows]) {
+    min-height: 10em;
+}
+
+/* 고정된 모든 항목에는 여분의 스크롤 여백이 있어야 합니다. */
+:target {
+    scroll-margin-block: 5ex;
+}
+
+table {
+    min-width: 100%;
+    border-collapse: collapse;
+    table-layout: fixed;
+}
+
+table th,
+table td {
+    font-size: 1.3rem;
+}
+
+select,
+input{
+    padding: 10px;
+    border: 1px solid #ddd;
+    border-radius: 5px;
+    font-size: 1.3rem;
+}
+
+input:focus{
+    outline: none;
+}
+
+input[type="file"] {
+    width: 100%;
+    border: 0;
+}
+
+summary {
+    position: relative;
+}
+
+summary::marker {
+    content: none;
+}
+
+summary::after {
+    background: url(../img/comment_arrow.png) no-repeat 0px 0px;  
+    content: '';
+    width: 11px;
+    height: 11px;
+    font-size: 1.6rem;
+    font-weight: bold;
+    color: #eee;
+    position: absolute;
+    top: calc(50%);
+    right: 0;
+    transform: translateY(-50%);
+}
+
+
+[open] summary::after {
+    top: 50%;
+    transform: translateY(-50%) rotate(180deg);
+    color: var(--blue);
+}
+
+textarea{
+    width: 100%;
+    border: 0;
+    border-radius: 5px;
+    min-height: 250px;
+    outline: 0;
+    font-size: 1.3rem;
+}
+
+/* 스크롤바 디자인 */
+::-webkit-scrollbar {
+    width: 8px;
+    height: 8px;
+}
+
+::-webkit-scrollbar-thumb {
+    background-color: #ededed;
+    border-radius: 10px;
+}
+
+::-webkit-scrollbar-track {
+    background-color: #fff;
+    border-radius: 10px;
+}(No newline at end of file)
 
client/resources/css/style.css (added)
+++ client/resources/css/style.css
@@ -0,0 +1,97 @@
+
+/* 로그인 */
+.login-page {
+    background-color: var(--light);
+}
+
+/* 홈화면 */
+.item {
+    padding: 10px;
+    background-color: var(--white);
+    border-radius: 10px;
+    border: 1px solid #eee;
+}
+
+.img-zone {
+    width: 100%;
+    height: 120px;
+    border: 1px solid #eee;
+    border-radius: 10px;
+}
+
+.img-zone img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+    border-radius: 10px;
+}
+
+.tag {
+    display: inline-block;
+    padding: 5px;
+    background-color: #eee;
+    border: 1px solid #ddd;
+    border-radius: 5px;
+}
+
+.item-title {
+    color: var(--blue);
+    font-size: 1.3rem;
+}
+
+.item-table th,
+.item-table td {
+    padding: 5px 0;
+}
+
+.comment-zone {
+    padding: 5px 0;
+    border-top: 1px solid #ddd;
+}
+
+.comment-zone>details>summary>span {
+    font-size: 1.2rem;
+}
+
+/* 등록 */
+
+.input-group>label {
+    display: block;
+}
+
+.text-area {
+    width: 100%;
+    background-color: var(--white);
+    border-radius: 5px;
+    border: 1px solid #ddd;
+    padding: 5px;
+}
+
+.file-zone {
+    width: 100%;
+    border-top: 1px solid #ddd;
+}
+
+.comment-bottom,
+.btn-wrap {
+    padding-top: 10px;
+    border-top: 1px solid #eee;
+}
+
+.comment-input {
+    border: 1px solid #eee;
+    border-radius: 5px;
+}
+
+.comment-input input {
+    border: none;
+}
+
+/* 조회 */
+.search-zone{
+    padding: 10px;
+    background-color: var(--skyblue);
+    border: 1px solid var(--primary-lignt);
+    border-radius: 5px;
+}
+
 
client/resources/font/GmarketSansBold.woff (Binary) (added)
+++ client/resources/font/GmarketSansBold.woff
Binary file is not shown
 
client/resources/font/GmarketSansLight.woff (Binary) (added)
+++ client/resources/font/GmarketSansLight.woff
Binary file is not shown
 
client/resources/font/GmarketSansMedium.woff (Binary) (added)
+++ client/resources/font/GmarketSansMedium.woff
Binary file is not shown
 
client/resources/font/PretendardVariable.woff2 (Binary) (added)
+++ client/resources/font/PretendardVariable.woff2
Binary file is not shown
 
client/resources/img/ajin_logo.png (Binary) (added)
+++ client/resources/img/ajin_logo.png
Binary file is not shown
 
client/resources/img/comment_arrow.png (Binary) (added)
+++ client/resources/img/comment_arrow.png
Binary file is not shown
 
client/views/component/autosearch/AutoSearch.jsx (added)
+++ client/views/component/autosearch/AutoSearch.jsx
@@ -0,0 +1,60 @@
+import React, { useState } from "react";
+
+function AutoSearch(props) {
+  const [inputValue, setInputValue] = useState("");
+  const [accountResults, setAccountResults] = useState([]);
+  const accounts = props.accounts;
+  const list = document.querySelector(".auto-list");
+
+  const handleInputChange = (e) => {
+    const value = e.target.value;
+    setInputValue(value);
+
+    const filtered = accounts.filter((account) =>
+      account.toLowerCase().startsWith(value.toLowerCase())
+    );
+    setAccountResults(filtered);
+
+    if (value === "") {
+        list.style.display = "none"
+      list.style.padding = "0";
+      list.style.backgroundColor = "transparent";
+      list.style.border = "0";
+
+    }else{
+        list.style.display = "block"
+        list.style.padding = "10px";
+        list.style.backgroundColor = "#ffffff";
+        list.style.border = "1px solid #eee";
+    }
+  };
+
+  const handleItemClick = (account) => {
+    setInputValue(account);
+    setAccountResults([]);
+  };
+
+  return (
+    <>
+      <label htmlFor="" className="item-title mb5">
+        {props.titleName}
+      </label>
+      <input
+        type="text"
+        value={inputValue}
+        onChange={handleInputChange}
+        placeholder="거래처를 입력하세요"
+        className="full-input"
+      />
+      <ul className="auto-list">
+        {accountResults.map((account, index) => (
+          <li key={index} onClick={() => handleItemClick(account)}>
+            {account}
+          </li>
+        ))}
+      </ul>
+    </>
+  );
+}
+
+export default AutoSearch;
client/views/index.html
--- client/views/index.html
+++ client/views/index.html
@@ -6,6 +6,13 @@
         <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
         <meta name="description" content="Node React Web">
         <link rel="icon" href="" />
+        <link rel="stylesheet" href="/client/resources/css/font.css" />
+        <link rel="stylesheet" href="/client/resources/css/reset.css" />
+        <link rel="stylesheet" href="/client/resources/css/layout.css" />
+        <link rel="stylesheet" href="/client/resources/css/grid.css" />
+        <link rel="stylesheet" href="/client/resources/css/common.css" />
+        <link rel="stylesheet" href="/client/resources/css/component.css" />
+        <link rel="stylesheet" href="/client/resources/css/style.css" />
         <title>Node React Web</title>
     </head>
 
client/views/index.jsx
--- client/views/index.jsx
+++ client/views/index.jsx
@@ -4,14 +4,17 @@
  * @dscription : React를 활용한 Client단 구현의 시작점(Index) Component 입니다.
  */
 
- import React from 'react';
- import ReactDOM from 'react-dom/client';
- 
- //Application Root component
- import App from './pages/App.jsx';
- 
- const root = ReactDOM.createRoot(document.getElementById('root'));
- root.render(<App/>);
- 
- 
- 
(No newline at end of file)
+import React from "react";
+import ReactDOM from "react-dom/client";
+import { BrowserRouter } from "react-router-dom";
+//Application Root component
+import App from "./pages/App.jsx";
+
+const root = ReactDOM.createRoot(document.getElementById("root"));
+root.render(
+  <BrowserRouter>
+    <React.StrictMode>
+      <App />
+    </React.StrictMode>
+  </BrowserRouter>
+);
client/views/layout/Header.jsx
--- client/views/layout/Header.jsx
+++ client/views/layout/Header.jsx
@@ -1,25 +1,44 @@
-import React from 'react';
+import React from "react";
+import { useNavigate } from "react-router-dom";
+import Icon from "@mdi/react";
+import { mdiTrashCanOutline, mdiPencilOutline, mdiChevronLeft } from "@mdi/js";
 
-function Header () {
-
-    const [headerData, setHeaderData] = React.useState(0);
-    console.log('Header headerData : ', headerData);
-
-    function headerDataChange () {
-        for (let i = 0; i < 10; i++) {
-            setHeaderData(headerData + 1);
+function Header(props) {
+  const navigate = useNavigate();
+  const rollBackBtn = () => {
+    navigate(-1); // 바로 이전 페이지로 이동
+  };
+  return (
+    <header>
+      <div
+        className={
+          "flex align-center no-gutters "+
+          (props.pathName !== "영업 일지"
+            ? "justify-center"
+            : "justify-between")
         }
-        console.log('function headerDataChange headerData : ', headerData);
-    }
-
-    
-
-    return (
-        <div>
-            헤더입니다.
-            <button onClick={headerDataChange}>+1</button>
-        </div>
-    )
+      >
+        {props.pathName === "영업 일지" ? (
+          <div className="col-2">
+            <button onClick={rollBackBtn}>
+              <Icon path={mdiChevronLeft} size={1.5} color={"#fff"} />
+            </button>
+          </div>
+        ) : null}
+        <p className="current-name col-8 text-ct">{props.pathName}</p>
+        {props.pathName === "영업 일지" ? (
+          <div className="col-2">
+            <button className="mr5 btn">
+              <Icon path={mdiTrashCanOutline} size={1.2} color={"#fff"} />
+            </button>
+            <button>
+              <Icon path={mdiPencilOutline} size={1.2} color={"#fff"} />
+            </button>
+          </div>
+        ) : null}
+      </div>
+    </header>
+  );
 }
 
-export default Header;
(No newline at end of file)
+export default Header;
client/views/layout/Menu.jsx
--- client/views/layout/Menu.jsx
+++ client/views/layout/Menu.jsx
@@ -1,17 +1,63 @@
-import React from 'react';
-import { BrowserRouter, Link } from 'react-router-dom';
+import React, { useState } from "react";
+import { Link  } from "react-router-dom";
+import Icon from "@mdi/react";
+import {
+  mdiHomeOutline,
+  mdiMagnify,
+  mdiPlusCircleOutline,
+  mdiInformationOutline,
+} from "@mdi/js";
 
-function Menu () {
-    return (
-        <>
-            <div>
-                <BrowserRouter>
-                    <Link to="/">Home</Link>
-                </BrowserRouter>
-            </div>
-        </>
-        
-    )
+function Menu() {
+  const menuList = [
+    {
+      path: "/",
+      pathName: "HOME",
+      icon: <Icon path={mdiHomeOutline} size={1.6} rem />,
+    },
+    {
+      path: "/search",
+      pathName: "Search",
+      icon: <Icon path={mdiMagnify} size={1.6} rem />,
+    },
+    {
+      path: "/homeInsert",
+      pathName: "Add",
+      icon: <Icon path={mdiPlusCircleOutline} size={1.6} rem />,
+    },
+    {
+      path: "/custinfo",
+      pathName: "Cust Info",
+      icon: <Icon path={mdiInformationOutline} size={1.6} rem />,
+    },
+  ];
+
+  const [activeIndex, setActiveIndex] = useState(null);
+
+  const handleClick = (index) => {
+    setActiveIndex(index);
+  };
+
+
+  return (
+    <nav className="main-menu">
+        <ul className="flex justify-between aling-center">
+          {menuList.map((menu, index) => (
+            <li
+              className={`${activeIndex === index ? "active" : ""}`}
+              onClick={() => handleClick(index)}
+            >
+              <Link
+              to={menu.path}
+                className="flex-column justify-center align-center">
+                <p>{menu.icon}</p>
+                <p>{menu.pathName}</p>
+              </Link>
+            </li>
+          ))}
+        </ul>
+    </nav>
+  );
 }
 
-export default Menu;
(No newline at end of file)
+export default Menu;
client/views/pages/App.jsx
--- client/views/pages/App.jsx
+++ client/views/pages/App.jsx
@@ -3,27 +3,46 @@
  * @since : 2022.09.20
  * @dscription : React를 활용한 Client단 구현 대상인 Application의 시작점(Index) Component 입니다.
  */
- import React from 'react';
+import React, { useEffect, useState } from "react";
+import { useLocation } from "react-router-dom";
+import AppRoute from "./AppRoute.jsx";
+import Header from "../layout/Header.jsx";
+import Menu from "../layout/Menu.jsx";
 
- //Application의 Route 정보를 관리하는 Component
- import AppRoute from './AppRoute.jsx';
- 
- //Test Layout
- import Header from '../layout/Header.jsx';
- import Menu from '../layout/Menu.jsx';
- import Footer from '../layout/Footer.jsx';
- 
- function App() {
-     return (
-         <div id="App">
-             <Header></Header>
-             <Menu></Menu>
-             <div id="pages">
-                 <AppRoute/>
-             </div>
-             <Footer></Footer>
-         </div>
-     )
- }
- 
- export default App;
(No newline at end of file)
+function App() {
+  const [currentPathName, setCurrentPathName] = useState("");
+  const location = useLocation();
+
+  useEffect(() => {
+    const body = document.querySelector("body");
+
+    if (location.pathname === "/") {
+      body.style.backgroundColor = "#f9f9f9";
+      setCurrentPathName("홈");
+    } else if (location.pathname === "/search") {
+      body.style.backgroundColor = "#ffffff";
+      setCurrentPathName("조회");
+    } else if (location.pathname === "/homeInsert") {
+      body.style.backgroundColor = "#ffffff";
+      setCurrentPathName("업체 등록");
+    } else if (location.pathname === "/homeSelectOne") {
+      body.style.backgroundColor = "#ffffff";
+      setCurrentPathName("영업 일지");
+    } else if (location.pathname === "/custinfo") {
+      body.style.backgroundColor = "#ffffff";
+      setCurrentPathName("업체 정보 조회");
+    }
+  }, [location.pathname]);
+
+  return (
+    <div id="App" className="mobile-layout">
+      <Header pathName={currentPathName}></Header>
+      <Menu></Menu>
+      <div id="pages">
+        <AppRoute />
+      </div>
+    </div>
+  );
+}
+
+export default App;
client/views/pages/AppRoute.jsx
--- client/views/pages/AppRoute.jsx
+++ client/views/pages/AppRoute.jsx
@@ -3,20 +3,28 @@
  * @since : 2022.09.20
  * @dscription : Application의 Route 정보를 관리하는 Component 입니다.
  */
- import React from 'react';
- //react router 라이브러리 import
- import { BrowserRouter, Routes, Route } from 'react-router-dom';
- 
- import Main from './main/Main.jsx';
- 
- function AppRoute () {
-     return (
-         <BrowserRouter>
-             <Routes>
-                 <Route path="/" element={<Main/>}></Route>
-             </Routes>
-         </BrowserRouter>
-     )
- }
- 
- export default AppRoute;
(No newline at end of file)
+import React from "react";
+//react router 라이브러리 import
+import { Routes, Route } from "react-router-dom";
+
+import HomeSelectList from "./main/HomeSelectList.jsx";
+import HomeInsert from "./main/HomeInsert.jsx";
+import HomeSelectOne from "./main/HomeSelectOne.jsx";
+import CustInfoSelectList from "./custInfo/CustInfoSelectList.jsx";
+import Search from "./search/Search.jsx";
+import Login from "./login/Login.jsx";
+
+function AppRoute() {
+  return (
+    <Routes>
+      <Route path="/" element={<HomeSelectList />}></Route>
+      <Route path="/search" element={<Search />}></Route>
+      <Route path="/homeSelectOne" element={<HomeSelectOne />}></Route>
+      <Route path="/login" element={<Login />}></Route>
+      <Route path="/homeInsert" element={<HomeInsert />}></Route>
+      <Route path="/custinfo" element={<CustInfoSelectList />}></Route>
+    </Routes>
+  );
+}
+
+export default AppRoute;
 
client/views/pages/custInfo/CustInfoSelectList.jsx (added)
+++ client/views/pages/custInfo/CustInfoSelectList.jsx
@@ -0,0 +1,21 @@
+import React from "react";
+import AutoSearch from "./../../component/autosearch/AutoSearch.jsx";
+
+function CustInfoSelectList() {
+  const accounts = ["Apple", "Banana", "Orange", "Grape", "Strawberry"];
+
+  return (
+    <div className="custinfo-page">
+      <div className="search-zone">
+        <div className="input-group mb10">
+          <AutoSearch titleName={"거래처"} accounts={accounts} />
+        </div>
+        <div className="btn-wrap flex justify-end">
+          <button className="blue-btn small-btn">조회</button>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+export default CustInfoSelectList;
 
client/views/pages/login/Login.jsx (added)
+++ client/views/pages/login/Login.jsx
@@ -0,0 +1,41 @@
+import React from "react";
+
+function Login() {
+  return (
+    <div className="login-page flex-column justify-center">
+      <div className="login-wrap">
+        <div className="logo">
+          <img src="../../../resources/img/ajin_logo.png" alt="" />
+        </div>
+        <div className="login-title">
+          <p>LOGIN</p>
+        </div>
+        <div className="input-group">
+          <label htmlFor="businessNumber"></label>
+          <input
+            type="text"
+            id="businessNumber"
+            placeholder="사번을 입력해주세요"
+          />
+        </div>
+        <div className="input-group">
+          <label htmlFor="number"></label>
+          <input
+            type="text"
+            id="number"
+            placeholder="전화번호를 입력해주세요"
+          />
+        </div>
+        <div className="input-group">
+          <label htmlFor="crtificationNumber"></label>
+          <input type="text" id="crtificationNumber" placeholder="인증번호" />
+        </div>
+        <div className="btn-wrap">
+          <button className="blue-btn">인증</button>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+export default Login;
 
client/views/pages/main/HomeInsert.jsx (added)
+++ client/views/pages/main/HomeInsert.jsx
@@ -0,0 +1,57 @@
+import React from "react";
+
+function HomeInsert() {
+  return (
+    <div className="add-page page">
+      <div className="input-group mb20">
+        <label htmlFor="" className="item-title mb5">
+          방문일자
+        </label>
+        <input type="date" name="" id="" className="full-input" />
+      </div>
+      <div className="input-group mb20">
+        <label htmlFor="" className="item-title mb5">
+          거래처
+        </label>
+        <input
+          type="text"
+          name=""
+          id=""
+          className="full-input"
+          list="depList"
+        />
+        <datalist id="depList">
+          <option value="거래처1"></option>
+          <option value="거래처2"></option>
+          <option value="거래처3"></option>
+          <option value="거래처4"></option>
+        </datalist>
+      </div>
+      <div className="input-group mb20">
+        <label htmlFor="" className="item-title mb5">
+          거래처 담당자
+        </label>
+        <input type="text" name="" id="" className="full-input" />
+      </div>
+      <div className="input-group mb20">
+        <label htmlFor="" className="item-title mb5">
+          특이사항
+        </label>
+        <div className="text-area">
+          <textarea name="" id="" cols="30" rows="10"></textarea>
+          <div className="file-zone">
+            <input type="file" name="" id="" />
+          </div>
+        </div>
+      </div>
+      <div className="input-group mb20">
+        <label htmlFor="" className="item-title mb5">
+          태그
+        </label>
+        <input type="text" name="" id="" className="full-input" />
+      </div>
+    </div>
+  );
+}
+
+export default HomeInsert;
 
client/views/pages/main/HomeSelectList.jsx (added)
+++ client/views/pages/main/HomeSelectList.jsx
@@ -0,0 +1,51 @@
+import React from "react";
+import Icon from '@mdi/react';
+import { mdiCalendarMonth,mdiHandshakeOutline,mdiFileCheckOutline,mdiAccountOutline,mdiChatOutline} from '@mdi/js';
+import TestImg from "../../../resources/img/ajin_logo.png"
+
+function HomeSelectList() {
+  return (
+    <div className="main-page">
+      <ul>
+        <li className="item">
+          <div className="img-zone mb10">
+            <img src={TestImg} alt="" />
+          </div>
+          <div className="tag-zone mb10">
+            <span className="tag">태그입니다.</span>
+          </div>
+          <div className="text-zone mb10">
+            <table className="item-table">
+              <tr>
+                <th className="item-title col-4 text-lf"><Icon path={mdiCalendarMonth} size={1} /> 방문일자</th>
+                <td>2024.02.08</td>
+              </tr>
+              <tr>
+                <th className="item-title col-4 text-lf"><Icon path={mdiHandshakeOutline} size={1} /> 거래처</th>
+                <td>태광산업</td>
+              </tr>
+              <tr>
+                <th className="item-title col-4 text-lf"><Icon path={mdiFileCheckOutline} size={1} /> 특이사항</th>
+                <td>
+                  1. 제지 종이 신규로 받고 있음<br />
+                  2. EKAEKDWK XXX로 변경
+                </td>
+              </tr>
+              <tr>
+                <th className="item-title col-4 text-lf"><Icon path={mdiAccountOutline} size={1} /> 담당자</th>
+                <td>곽길도 과장</td>
+              </tr>
+            </table>
+          </div>
+          <div className="comment-zone">
+              <details>
+                <summary><Icon path={mdiChatOutline} size={1} horizontal/><span className="ml5">2</span></summary>
+              </details>
+          </div>
+        </li>
+      </ul>
+    </div>
+  );
+}
+
+export default HomeSelectList;
 
client/views/pages/main/HomeSelectOne.jsx (added)
+++ client/views/pages/main/HomeSelectOne.jsx
@@ -0,0 +1,76 @@
+import React from "react";
+import Icon from "@mdi/react";
+import {
+  mdiCalendarMonth,
+  mdiHandshakeOutline,
+  mdiFileCheckOutline,
+  mdiAccountOutline,
+  mdiChatOutline,
+} from "@mdi/js";
+import TestImg from "../../../resources/img/ajin_logo.png";
+
+function HomeSelectOne() {
+  return (
+    <div className="detail-page page">
+      <div className="img-zone mb10">
+        <img src={TestImg} alt="" />
+      </div>
+      <div className="text-zone mb10">
+        <table className="item-table">
+          <tr>
+            <th className="item-title col-4 text-lf">
+              <Icon path={mdiCalendarMonth} size={1} /> 방문일자
+            </th>
+            <td>2024.02.08</td>
+          </tr>
+          <tr>
+            <th className="item-title col-4 text-lf">
+              <Icon path={mdiHandshakeOutline} size={1} /> 거래처
+            </th>
+            <td>태광산업</td>
+          </tr>
+          <tr>
+            <th className="item-title col-4 text-lf">
+              <Icon path={mdiFileCheckOutline} size={1} /> 특이사항
+            </th>
+            <td>
+              1. 제지 종이 신규로 받고 있음
+              <br />
+              2. EKAEKDWK XXX로 변경
+            </td>
+          </tr>
+          <tr>
+            <th className="item-title col-4 text-lf">
+              <Icon path={mdiAccountOutline} size={1} /> 담당자
+            </th>
+            <td>곽길도 과장</td>
+          </tr>
+        </table>
+      </div>
+      <div className="tag-zone mb10">
+        <span className="tag">태그입니다.</span>
+      </div>
+      <div className="comment-zone">
+        <div className="comment-top pb10">
+          <Icon path={mdiChatOutline} size={1} horizontal />
+          <span className="ml5">2</span>
+        </div>
+        {/* 여기 댓글 트리 */}
+        <div className="comment-bottom">
+          <div className="comment-input  flex align-center">
+            <input
+              type="text"
+              name=""
+              id=""
+              placeholder="댓글을 입력해주세요."
+              className="col-10"
+            />
+            <button className="comment-btn darkg-btn col-2">등록</button>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+export default HomeSelectOne;
 
client/views/pages/main/Main.jsx (deleted)
--- client/views/pages/main/Main.jsx
@@ -1,16 +0,0 @@
-import React from 'react';
-
-import TestCompoent from '../../component/test/TestCompoent.jsx';
-
-function Main () {
-    return (
-        <>
-            <div>
-                메인 페이지 입니다.
-                <TestCompoent/>
-            </div>
-        </>
-    )
-}
-
-export default Main;(No newline at end of file)
 
client/views/pages/search/Search.jsx (added)
+++ client/views/pages/search/Search.jsx
@@ -0,0 +1,55 @@
+import React from "react";
+
+function Search() {
+  return (
+    <div className="search-page">
+      <div className="search-zone">
+        <div className="input-group mb10">
+          <label htmlFor="" className="item-title mb5">
+            거래처
+          </label>
+          <input
+            type="text"
+            name=""
+            id=""
+            list="account"
+            className="full-input"
+          />
+          <datalist id="account">
+            <option value="거래처1"></option>
+            <option value="거래처2"></option>
+            <option value="거래처3"></option>
+            <option value="거래처4"></option>
+          </datalist>
+        </div>
+        <div className="input-group mb10">
+          <label htmlFor="" className="item-title mb5">
+            기간
+          </label>
+          <div className="flex justify-between align-center">
+            <input type="date" name="" id="" list="account" className="col-5" />
+            <span className="col-2 text-ct">~</span>
+            <input type="date" name="" id="" list="account" className="col-5" />
+          </div>
+        </div>
+        <div className="input-group mb10">
+          <label htmlFor="" className="item-title mb5">
+            태그
+          </label>
+          <input type="text" name="" id="" className="full-input" />
+        </div>
+        <div className="input-group mb10">
+          <label htmlFor="" className="item-title mb5">
+            내용
+          </label>
+          <input type="text" name="" id="" className="full-input" />
+        </div>
+        <div className="btn-wrap flex justify-end">
+          <button className="blue-btn small-btn">조회</button>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+export default Search;
 
client/views/pages/test/TestInsert.jsx (deleted)
--- client/views/pages/test/TestInsert.jsx
@@ -1,20 +0,0 @@
-import React from 'react';
-
-/**
- * @author : 최정우
- * @since : 2022.09.24
- * @dscription : 테스트용 등록 페이지 입니다.
- */
-function TestInsert () {
-    return (
-        <>
-            <div style={{width:'100%', height:'100vh', backgroundColor:'#6799FF', textAlign:'center'}}>
-                <div style={{margin:'0 auto'}}>
-                    <p>Test용 목록 조회 페이지 입니다</p>
-                </div>
-            </div>
-        </>
-    )
-}
-export default TestInsert;
-
 
client/views/pages/test/TestSelectList.jsx (deleted)
--- client/views/pages/test/TestSelectList.jsx
@@ -1,20 +0,0 @@
-import React from 'react';
-
-/**
- * @author : 최정우
- * @since : 2022.09.24
- * @dscription : 테스트용 목록 조회 페이지 입니다.
- */
-function TestSelectList () {
-    return (
-        <>
-            <div style={{width:'100%', height:'100vh', backgroundColor:'#6799FF', textAlign:'center'}}>
-                <div style={{margin:'0 auto'}}>
-                    <p>Test용 목록 조회 페이지 입니다</p>
-                </div>
-            </div>
-        </>
-    )
-}
-export default TestSelectList;
-
 
client/views/pages/test/TestSelectOne.jsx (deleted)
--- client/views/pages/test/TestSelectOne.jsx
@@ -1,20 +0,0 @@
-import React from 'react';
-
-/**
- * @author : 최정우
- * @since : 2022.09.24
- * @dscription : 테스트용 상세 조회 페이지 입니다.
- */
-function TestSelectOne () {
-    return (
-        <>
-            <div style={{width:'100%', height:'100vh', backgroundColor:'#6799FF', textAlign:'center'}}>
-                <div style={{margin:'0 auto'}}>
-                    <p>Test용 상세 조회 페이지 입니다</p>
-                </div>
-            </div>
-        </>
-    )
-}
-export default TestSelectOne;
-
 
client/views/pages/test/TestUpdate.jsx (deleted)
--- client/views/pages/test/TestUpdate.jsx
@@ -1,20 +0,0 @@
-import React from 'react';
-
-/**
- * @author : 최정우
- * @since : 2022.09.24
- * @dscription : 테스트용 수정 페이지 입니다.
- */
-function TestUpdate () {
-    return (
-        <>
-            <div style={{width:'100%', height:'100vh', backgroundColor:'#6799FF', textAlign:'center'}}>
-                <div style={{margin:'0 auto'}}>
-                    <p>Test용 목록 조회 페이지 입니다</p>
-                </div>
-            </div>
-        </>
-    )
-}
-export default TestUpdate;
-
node_modules/.package-lock.json
--- node_modules/.package-lock.json
+++ node_modules/.package-lock.json
@@ -1,6 +1,6 @@
 {
-  "name": "node_react_web_server_framework_v1.0",
-  "lockfileVersion": 2,
+  "name": "agin_business_log",
+  "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "node_modules/@ampproject/remapping": {
@@ -582,6 +582,19 @@
       "dependencies": {
         "@jridgewell/resolve-uri": "^3.0.3",
         "@jridgewell/sourcemap-codec": "^1.4.10"
+      }
+    },
+    "node_modules/@mdi/js": {
+      "version": "7.4.47",
+      "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz",
+      "integrity": "sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ=="
+    },
+    "node_modules/@mdi/react": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/@mdi/react/-/react-1.6.1.tgz",
+      "integrity": "sha512-4qZeDcluDFGFTWkHs86VOlHkm6gnKaMql13/gpIcUQ8kzxHgpj31NuCkD8abECVfbULJ3shc7Yt4HJ6Wu6SN4w==",
+      "dependencies": {
+        "prop-types": "^15.7.2"
       }
     },
     "node_modules/@nicolo-ribaudo/chokidar-2": {
@@ -2247,6 +2260,14 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/object-inspect": {
       "version": "1.12.2",
       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
@@ -2607,6 +2628,21 @@
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
       "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
     },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/prop-types/node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
     "node_modules/proxy-addr": {
       "version": "2.0.7",
       "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
package-lock.json
--- package-lock.json
+++ package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "node_react_web_server_framework_v1.0",
+  "name": "agin_business_log",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
@@ -8,14 +8,17 @@
         "@babel/cli": "7.18.10",
         "@babel/core": "7.19.1",
         "@babel/preset-react": "7.18.6",
+        "@mdi/js": "^7.4.47",
+        "@mdi/react": "^1.6.1",
         "babel-loader": "^8.2.5",
         "css-loader": "^6.7.1",
         "express": "4.18.1",
         "file-loader": "^6.2.0",
         "fs": "0.0.1-security",
         "history": "5.3.0",
-        "mysql": "^2.18.1",
-        "oracledb": "^5.5.0",
+        "lodash": "^4.17.21",
+        "mysql": "2.18.1",
+        "oracledb": "5.5.0",
         "pg": "8.8.0",
         "react": "18.2.0",
         "react-dom": "18.2.0",
@@ -609,6 +612,19 @@
       "dependencies": {
         "@jridgewell/resolve-uri": "^3.0.3",
         "@jridgewell/sourcemap-codec": "^1.4.10"
+      }
+    },
+    "node_modules/@mdi/js": {
+      "version": "7.4.47",
+      "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz",
+      "integrity": "sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ=="
+    },
+    "node_modules/@mdi/react": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/@mdi/react/-/react-1.6.1.tgz",
+      "integrity": "sha512-4qZeDcluDFGFTWkHs86VOlHkm6gnKaMql13/gpIcUQ8kzxHgpj31NuCkD8abECVfbULJ3shc7Yt4HJ6Wu6SN4w==",
+      "dependencies": {
+        "prop-types": "^15.7.2"
       }
     },
     "node_modules/@nicolo-ribaudo/chokidar-2": {
@@ -2287,6 +2303,14 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/object-inspect": {
       "version": "1.12.2",
       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
@@ -2646,6 +2670,21 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
       "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+    },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/prop-types/node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
     },
     "node_modules/proxy-addr": {
       "version": "2.0.7",
@@ -3992,6 +4031,19 @@
         "@jridgewell/sourcemap-codec": "^1.4.10"
       }
     },
+    "@mdi/js": {
+      "version": "7.4.47",
+      "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz",
+      "integrity": "sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ=="
+    },
+    "@mdi/react": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/@mdi/react/-/react-1.6.1.tgz",
+      "integrity": "sha512-4qZeDcluDFGFTWkHs86VOlHkm6gnKaMql13/gpIcUQ8kzxHgpj31NuCkD8abECVfbULJ3shc7Yt4HJ6Wu6SN4w==",
+      "requires": {
+        "prop-types": "^15.7.2"
+      }
+    },
     "@nicolo-ribaudo/chokidar-2": {
       "version": "2.1.8-no-fsevents.3",
       "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
@@ -5261,6 +5313,11 @@
       "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
       "optional": true
     },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+    },
     "object-inspect": {
       "version": "1.12.2",
       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
@@ -5505,6 +5562,23 @@
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
       "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
     },
+    "prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "requires": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      },
+      "dependencies": {
+        "react-is": {
+          "version": "16.13.1",
+          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+          "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+        }
+      }
+    },
     "proxy-addr": {
       "version": "2.0.7",
       "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
package.json
--- package.json
+++ package.json
@@ -3,12 +3,15 @@
     "@babel/cli": "7.18.10",
     "@babel/core": "7.19.1",
     "@babel/preset-react": "7.18.6",
+    "@mdi/js": "^7.4.47",
+    "@mdi/react": "^1.6.1",
     "babel-loader": "^8.2.5",
     "css-loader": "^6.7.1",
     "express": "4.18.1",
     "file-loader": "^6.2.0",
     "fs": "0.0.1-security",
     "history": "5.3.0",
+    "lodash": "^4.17.21",
     "mysql": "2.18.1",
     "oracledb": "5.5.0",
     "pg": "8.8.0",
server/modules/web/Server.js
--- server/modules/web/Server.js
+++ server/modules/web/Server.js
@@ -3,11 +3,11 @@
  * @since : 2022.09.20
  * @dscription : Express 라이브러리 활용 HTTP Web Server 모듈입니다.
  */
-const { BASE_DIR, PORT } = require('../../../Global');
-const JsxToJsBuild = require('./build/JsxToJsBuild');//JSX파일을 JS파일로 Build 해주는 모듈
-const Logger = require('../log/Logger');//Logger(필수)
+const { BASE_DIR, PORT } = require("../../../Global");
+const JsxToJsBuild = require("./build/JsxToJsBuild"); //JSX파일을 JS파일로 Build 해주는 모듈
+const Logger = require("../log/Logger"); //Logger(필수)
 
-const express = require('express');
+const express = require("express");
 const webServer = express();
 
 /**
@@ -16,8 +16,8 @@
  * @dscription : HTTP Server start
  */
 webServer.listen(PORT, function () {
-    Logger.logging(`★★★ Node.js를 활용한 Web Server 구동(Port:${PORT}) ★★★`);
-})
+  Logger.logging(`★★★ Node.js를 활용한 Web Server 구동(Port:${PORT}) ★★★`);
+});
 
 /**
  * @author : 최정우
@@ -25,9 +25,11 @@
  * @dscription : Intercepter 역할을 하는 미들웨어 기능
  */
 webServer.use(function (request, response, next) {
-    let ip = request.headers['x-forwarded-for'] || request.socket.remoteAddress;
-    Logger.logging(`[HTTP] ${request.url} (Method: ${request.method}, IP: ${ip})`);
-    next();
+  let ip = request.headers["x-forwarded-for"] || request.socket.remoteAddress;
+  Logger.logging(
+    `[HTTP] ${request.url} (Method: ${request.method}, IP: ${ip})`
+  );
+  next();
 });
 
 /**
@@ -35,16 +37,16 @@
  * @since : 2022.09.20
  * @dscription : ROOT URL -> index.html
  */
-webServer.get('/', function (request, response) {
-    response.sendFile(`${BASE_DIR}/client/views/index.html`);
-})
+webServer.get("/", function (request, response) {
+  response.sendFile(`${BASE_DIR}/client/views/index.html`);
+});
 
 /**
  * @author : 최정우
  * @since : 2022.09.20
  * @dscription : Router's (Controller)
  */
-webServer.use("/test", require('../../service/test/router/TestRouter'));
+webServer.use("/test", require("../../service/test/router/TestRouter"));
 
 /**
  * webpack 환경에서는 필요 없음
@@ -71,23 +73,25 @@
 })
 */
 
-/**
- * @author : 최정우
- * @since : 2022.09.20
- * @dscription : 화면요청 URL 처리
- */
-webServer.get('*.page', function (request, response, next) {
-    //기능구현예정
-})
+
 
 /**
  * @author : 최정우
  * @since : 2022.09.20
  * @dscription : ROOT URL, Router's, 화면요청 URL 등.. 이 외 나머지 정적 자원에 대한 처리 기능
  */
-webServer.get('*.*', function (request, response, next) {
-    response.sendFile(`${BASE_DIR}${request.params['0']}.${request.params['1']}`);
-})
+webServer.get("*.*", function (request, response, next) {
+  response.sendFile(`${BASE_DIR}${request.params["0"]}.${request.params["1"]}`);
+});
+
+/**
+ * @author : 류윤주
+ * @since : 2022.11.06
+ * @dscription : React Router처리
+ */
+webServer.get("*", function (request, response, next) {
+  response.sendFile(`${BASE_DIR}/client/views/index.html`);
+});
 
 /**
  * @author : 최정우
@@ -95,9 +99,11 @@
  * @dscription : Global Error Handler (*맨 마지막에 적용해야됨)
  */
 webServer.use(function (error, request, response, next) {
-    const errorCode = !error.statusCode ? 500 : error.statusCode;
-    response.status(errorCode).send('에러가 발생하였습니다. 관리자에게 문의바랍니다.');
-    let message = `[Error:${errorCode}] ${request.url}\n ${error.stack}\n`;
-    Logger.logging(message);
-    //next();
-})
(No newline at end of file)
+  const errorCode = !error.statusCode ? 500 : error.statusCode;
+  response
+    .status(errorCode)
+    .send("에러가 발생하였습니다. 관리자에게 문의바랍니다.");
+  let message = `[Error:${errorCode}] ${request.url}\n ${error.stack}\n`;
+  Logger.logging(message);
+  //next();
+});
Add a comment
List