Fix: contributon branch 반영

This commit is contained in:
yongfire38
2024-05-27 17:23:53 +09:00
parent da5caa40fc
commit 6f4f8c9c4d
64 changed files with 1527 additions and 11848 deletions

View File

@@ -0,0 +1,35 @@
name: 개발가이드 수정 요청 Requesting changes to the development guide
description: 개발가이드 수정 요청하는 템플릿입니다. Template for requesting changes to the dev guide.
title: "[Guide]: "
labels: ["guide"]
assignees:
- overpassion
body:
- type: markdown
attributes:
value: |
시간을 내어 개발가이드 수정 요청을 작성해 주셔서 감사합니다. Thank you for taking the time to fill out a DevGuide correction request. (공유하고 싶은 기술문서나 노하우는 github wiki에 남겨 주세요. If you have any documentation or know-how you'd like to share, please leave it on our github wiki.)
- type: input
id: url
attributes:
label: 개발가이드 URL Dev Guide URL
description: 수정해야할 개발가이드 URL을 적어 주세요. Please write down the dev guide URL that needs to be modified.
placeholder: Example) https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte4.1:fdl:aop:aspectj
validations:
required: true
- type: textarea
id: where-to-amend
attributes:
label: 수정 대상 내용 What to fix
description: 수정해야할 대상 내용을 기입해 주세요. Fill in what you need to fix.
placeholder: 수정해야할 대상은 다음과 같습니다. Here's what you'll need to modify
validations:
required: true
- type: textarea
id: amendment
attributes:
label: 수정 문구 Corrective Wording
description: 어떻게 수정되어야 하는지 적어주세요. Please write down how it should be fixed.
placeholder: 다음과 같이 수정되어야 합니다. It should be modified as follows
validations:
required: true

74
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,74 @@
name: 버그 리포트 Bug report
description: 오류 내용을 이슈로 등록하는 템플릿입니다. Template to register an error as an issue.
title: "[Bug]: "
labels: ["bug", "triage"]
assignees:
- overpassion
body:
- type: markdown
attributes:
value: |
시간을 내어 버그 리포트를 작성해 주셔서 감사합니다. Thank you for taking the time to fill out a bug report.
- type: input
id: contact
attributes:
label: 연락처 Contact
description: 추가 정보 필요 시, 연락할 수 있는 이메일을 적어 주세요. Please include an email where we can reach you if we need more information. (Optional)
placeholder: 예) email@example.com
validations:
required: false
- type: textarea
id: what-happened
attributes:
label: 오류 내용 Error Description
description: 오류 내용을 기입해 주세요. Please provide a description of the error.
placeholder: Tell us what you see!
value: "오류를 발견했어요. I found an error."
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: 오류 재현 방법 How to reproduce the error
description: 오류 발생을 재현하려면, 어떻게 해야하나요? How can we reproduce the error you reported?
placeholder: 오류 재현 방법 How to reproduce the error
value: "(다음은 예시이며, 내용을 덮어 써 주세요. The following is an example, please overwrite the content.)\n\n
1. 다음 메뉴를 선택한다. Select the following menu '...'\n
2. 다음 버튼을 클릭한다. Click the Next button. '....'\n
3. 다음 문구까지 스크롤 다운한다. Scroll down to the following phrase '....'\n
4. 오류를 확인한다. Check for errors."
validations:
required: false
- type: textarea
id: environment
attributes:
label: 환경정보 Environmental Information
description: 오류가 발생한 환경정보를 작성해 주세요. Please describe the environment in which the error occurred.
placeholder: 오류 환경정보 Error Environment Information
value: " - OS정보 Operating System: \n
- 표준프레임워크 버전 eGovFrame Version: \n
- JDK(JRE) 정보: \n
- WAS 정보: \n
- DB 정보: \n
- 기타 환경 정보 Other environmental information:"
validations:
required: false
- type: dropdown
id: browsers
attributes:
label: 어느 브라우저를 사용했나요? Which browser did you use?
multiple: true
options:
- Chrome
- Firefox
- Microsoft Edge
- Opera
- Safari
- Internet Explorer
- Others
- type: textarea
id: logs
attributes:
label: 에러 로그 Error Logs
description: 관련 에러 로그를 복사하여 붙여넣어 주세요. Please copy and paste the relevant error logs.
render: shell

View File

@@ -0,0 +1,51 @@
name: 기능 요구 및 의견 Feature Request
description: 기능 요구나 기타 의견을 이슈로 등록하는 템플릿입니다. Suggest an idea for improving eGovFrame.
title: "[기능요구(Feature)]: "
labels: ["feature"]
assignees:
- overpassion
body:
- type: markdown
attributes:
value: |
시간을 내어 의견을 작성해 주셔서 감사합니다. Thank you for taking the time to fill out a request.
- type: input
id: contact
attributes:
label: 연락처 Contact
description: 추가 정보 필요 시, 연락할 수 있는 이메일을 적어 주세요. Please include an email where we can reach you if we need more information. (Optional)
placeholder: 예) email@example.com
validations:
required: false
- type: input
id: feature-title
attributes:
label: 추가 요청 기능명 Feature Name
description: 추가를 원하는 기능명칭을 간략히 적어주세요. Write the title of the feature you'd like to add.
placeholder: 예) 게시판 첨부기능 추가 Example) Adding a bulletin board attachment
validations:
required: true
- type: textarea
id: feature-request-details
attributes:
label: 기능 상세 설명 Feature Description
description: 추가를 원하는 기능에 대해 상세히 기술해 주세요. Please describe in detail the features you would like to see added.
placeholder: 추가를 원하는 기능은 다음과 같습니다. Here are the features I'd like to see added
validations:
required: true
- type: textarea
id: solution
attributes:
label: 솔루션 상세 Solution Details
description: 위 기능을 구현하는데 도움이 되는 기술내용이 있으면 적어 주세요. If you have any technical details to help us implement the above features, please let us know.
placeholder: 위 기능을 구현하는데 도움이 되는 기술내용은 다음과 같습니다. Here are some technical details to help you implement the above features.
validations:
required: false
- type: input
id: solution-url
attributes:
label: 솔루션 관련 URL Solution-related URLs
description: 위 기능을 구현하는데 도움이 되는 웹사이트 주소가 있으면 적어 주세요. If you have a website address that can help us implement the above features, please write it down.
placeholder: Example) egovframe.go.kr
validations:
required: false

35
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,35 @@
## 수정 사유 Reason for modification
소스를 수정한 사유가 무엇인지 체크해 주세요. Please check the reason you modified the source. ([X] X는 대문자여야 합니다.)
- [x] 버그수정 Bug fixes
- [ ] 기능개선 Enhancements
- [ ] 기능추가 Adding features
- [ ] 기타 Others
## 수정된 소스 내용 Modified source
검토자를 위해 수정된 소스 내용을 설명해 주세요. Please describe the modified source for reviewers.
## JUnit 테스트 JUnit tests
테스트를 완료하셨으면 다음 항목에 [대문자X]로 표시해 주세요. When you're done testing, check the following items.
- [x] JUnit 테스트 JUnit tests
- [x] 수동 테스트 Manual testing
## 테스트 브라우저 Test Browser
테스트를 진행한 브라우저를 선택해 주세요. Please select the browser(s) you ran the test on. (다중 선택 가능 you can select multiple) [X] X는 대문자여야 합니다.
- [ ] Chrome
- [ ] Firefox
- [ ] Edge
- [ ] Safari
- [ ] Opera
- [ ] Internet Explorer
- [ ] 기타 Others
## 테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video
테스트 전과 후의 스크린샷 또는 캡처 영상을 이곳에 첨부해 주세요. Please attach screenshots or video captures of your before and after tests here.

4
.gitignore vendored
View File

@@ -56,8 +56,10 @@ HELP.md
**/out/ **/out/
# production # production
**/build !**/build/
**/build/*
**/dist **/dist
!backend/module-common/build/libs/
# misc # misc
**.DS_Store **.DS_Store

201
LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

222
README-en.md Normal file
View File

@@ -0,0 +1,222 @@
# MSA templates (for training)
![Spring](https://img.shields.io/badge/Spring_Boot-F2F4F9?style=for-the-badge&logo=spring-boot)
![Gradle](https://img.shields.io/badge/Gradle-02303A.svg?style=for-the-badge&logo=Gradle&logoColor=white)
![React](https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB)
![NextJS](https://img.shields.io/badge/Next-black?style=for-the-badge&logo=next.js&logoColor=white)
![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white)
![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white)
![Kubernetes](https://img.shields.io/badge/kubernetes-%23326ce5.svg?style=for-the-badge&logo=kubernetes&logoColor=white)
This is the training source code for the Microservices Architecture (MSA) template created as part of the "Supporting the Spread of Cloud-Native Administrative and Public Services (2021)" project.
## Directory structure
```
├─backend
│ ├─apigateway
│ ├─board-service
│ ├─config
│ ├─discovery
│ ├─module-common
│ ├─portal-service
│ ├─reserve-check-service
│ ├─reserve-item-service
│ ├─reserve-request-service
│ └─user-service
├─config
├─docker-compose
│ ├─app
│ │ ├─mesh
│ │ └─service
│ ├─elk
│ │ ├─kibana
│ │ │ └─config
│ │ └─logstash
│ │ ├─config
│ │ └─pipeline
│ ├─mysql
│ │ └─init
│ └─opensearch
│ └─logstash
│ ├─config
│ └─pipeline
├─frontend
│ ├─admin
│ │ ├─public
│ │ │ ├─images
│ │ │ └─locales
│ │ ├─server
│ │ ├─src
│ │ │ ├─@types
│ │ │ ├─components
│ │ │ ├─constants
│ │ │ ├─hooks
│ │ │ ├─libs
│ │ │ ├─pages
│ │ │ ├─service
│ │ │ ├─stores
│ │ │ ├─styles
│ │ │ └─utils
│ │ └─test
│ ├─portal
│ │ ├─public
│ │ │ ├─locales
│ │ │ └─styles
│ │ ├─src
│ │ │ ├─@types
│ │ │ ├─components
│ │ │ ├─constants
│ │ │ ├─hooks
│ │ │ ├─libs
│ │ │ │ └─Storage
│ │ │ ├─pages
│ │ │ ├─service
│ │ │ ├─stores
│ │ │ ├─styles
│ │ │ └─utils
│ │ └─test
│ └─practice-image
└─k8s
├─applications
│ ├─backend
│ │ ├─apigateway
│ │ │ └─ingress
│ │ ├─board-service
│ │ ├─config
│ │ ├─discovery
│ │ │ └─ingress
│ │ ├─portal-service
│ │ ├─reserve-check-service
│ │ ├─reserve-item-service
│ │ ├─reserve-request-service
│ │ └─user-service
│ └─frontend
│ ├─admin
│ │ └─ingress
│ └─portal
│ └─ingress
└─environments
├─configmaps
├─databases
│ └─mysql
│ └─init
├─jenkins
├─logging
│ └─elk
│ ├─elasticsearch
│ ├─kibana
│ │ └─ingress
│ └─logstash
├─nfs
├─rabbitmq
│ └─ingress
├─storage
├─vagrant
└─zipkin
└─ingress
```
### Contents
- `/backend`: Services on the backend based on Spring Boot
- `/backend/apigateway`: API management and monitoring service for microservices (service mesh)
- `/backend/board-service`: Bulletin Board Service (Manage boards, posts, and attachments)
- `/backend/config`: Provide environment-independent services by offering separate, unified configuration management services (service mesh)
- `/backend/discovery`: Register and manage microservices and find and invoke them on demand (service mesh)
- `/backend/user-service`: User services (login, sign up, forgot password, admin)
- `/backend/portal-service`: Portal common services (menu, code, content, permissions, authorizations, banners, attachment management)
- `/backend/reserve-check-service`: Reservation Confirmation Service (non-blocking)
- `/backend/reserve-item-service`: Reserved Item Service (non-blocking)
- `/backend/reserve-request-service`: Reservation Request Service (non-blocking)
- `/config`: A folder containing a collection of configuration YAML files used by the CONFIG server in the backend.
- `/docker-compose`: YAML configuration files to manage the running of multiple containers in Docker
- `/frontend/admin`: Admin Dashboard built with Next.js + Typescript + Material UI.
- `/frontend/portal`: React based frontend built with Next.js + Typescript.
- `/frontend/practice-image`: Banner images
- `/k8s`: Resource template yaml file for deploying to a Kubernetes environment
- `/k8s/applications`: K8s Resource template yaml files for the backend and frontend applications
- `/k8s/environments/configmaps`: objects stored as key-value pairs as environment variables used by Pods.
- `/k8s/environments/databases`: MySQL-related objects
- `/k8s/environments/jenkins`: Jenkins-related objects
- `/k8s/environments/logging`: ELK-specific objects for Centralized Logging
- `/k8s/environments/nfs`: NFS Node Volumes Configuration
- `/k8s/environments/rabbitmq`: Message Broker-related objects
- `/k8s/environments/storage`: PersistentVolumeClaim objects
- `/k8s/environments/vagrant`: Vagrant-specific definitions that make it easy to configure the creation of a virtualized software development environment
- `/k8s/environments/zipkin`: Zipkin-specific definitions for distributed transaction tracing
## How to run backend
- Run the Eclipse IDE in your development environment.
- From the Eclipse IDE menu, click File>Import....
- In the Import window that opens, select Gradle>Existing Gradle Project
- Click Next when the Import Gradle Project window opens.
- Select ${home}/workspace.edu/egovframe-msa-edu/backend/config from the project root directory and click the Finish button.
- Repeat the above to import the following projects (1-6 for small, 1-9 for large).
1. config
2. discovery
3. apigateway
4. user-service
5. portal-service
6. board-service
7. reserve-check-service
8. reserve-item-service
9. reserve-request-service
- After importing all the projects and checking the Project Explorer, the board-service, portal-service, and user-service projects show errors. You need to add the classes that are generated by querydsl to the build path.
- Click Window>Show View>Other, select Gradle>Gradle Tasks in the opened window, and click the Open button to open the Gradle Tasks tab.
- Click the View Menu button in the top right corner of Gradle Tasks and check Show All Tasks.
- In Gradle Tasks, double-click portal-service>other>compileQuerydsl or right-click and click Run Gradle Tasks to start the build.
- In the Project Explorer, select board-service, portal-service, user-service, and press F5 or right-click and click Refresh to refresh the project.
- In Project Explorer, right-click the board-service, portal-service, or user-service, and then click Properties.
- In the Properties window that opens, select Java Build Path from the left menu and click the Add Folder... button on the right Source tab.
- In the Source Folder Selection window that opens, check build>generated>querydsl and click the OK button.
- When you click the Apply and Close button in the Properties window, the window closes and the project rebuilds and the error message disappears.
(For more information about ELK configuration, Config, OAuth 2.0 setup, API call and JUnit Test, please refer to [02.MSA template backend configuration and practice(KOR).pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084631/02.MSA._.pdf).)
## How to run frontend
```
node : 14.8.0
npm : 6.14.7
Visual Studio Code : latest
```
- Download and install from https://nodejs.org/en/download and check the version.
```
node -v
npm -v
```
- In Visual Studio Code, open the frontend/admin folder.
- In a terminal, run the following
```
npm install
npm run dev
```
- On the login screen, enter '1@gmail.com' in the email field and 'test1234!' in the password field to log in.
(For more information, please refer to [03.MSA template frontend configuration and practice(KOR).pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084632/03.MSA._.pdf).)
## Screenshots reference
![Microservices Architecture](./images/msa.png)
![Authentication/Authorization-JWT](./images/jwt.png)
![Frontend](./images/frontend.png)
![Login](./images/login.png)
![Admin](./images/admin.png)
## Training materials
Only available in Korean.
- [01.MSA template overview and development environment practice(KOR).pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084628/01.MSA._._.pdf)
- [01.MSA Template Overview and Development Environment Theory(KOR).pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084629/01.MSA._._.pdf)
- [02.MSA template backend configuration and practice(KOR).pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084631/02.MSA._.pdf)
- [03.MSA template frontend configuration and practice(KOR).pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084632/03.MSA._.pdf)
- [04.MSA template event stream configuration and practice(KOR).pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084633/04.MSA._.pdf)

223
README.md
View File

@@ -1,2 +1,221 @@
# egovframe-msa-edu # MSA 템플릿 (교육용)
[Egovframe MSA Template] 클라우드 네이티브 기반의 행정,공공기관 서비스 확산 지원 사업, 온라인 교육 소스
![Spring](https://img.shields.io/badge/Spring_Boot-F2F4F9?style=for-the-badge&logo=spring-boot)
![Gradle](https://img.shields.io/badge/Gradle-02303A.svg?style=for-the-badge&logo=Gradle&logoColor=white)
![React](https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB)
![NextJS](https://img.shields.io/badge/Next-black?style=for-the-badge&logo=next.js&logoColor=white)
![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white)
![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white)
![Kubernetes](https://img.shields.io/badge/kubernetes-%23326ce5.svg?style=for-the-badge&logo=kubernetes&logoColor=white)
'클라우드 네이티브 기반 행정·공공 서비스 확산 지원(2021)' 사업의 일환으로 제작된 MSA(Microservices Architecture) 템플릿의 교육 소스코드이다.
## 디렉토리 구조
```
├─backend
│ ├─apigateway
│ ├─board-service
│ ├─config
│ ├─discovery
│ ├─module-common
│ ├─portal-service
│ ├─reserve-check-service
│ ├─reserve-item-service
│ ├─reserve-request-service
│ └─user-service
├─config
├─docker-compose
│ ├─app
│ │ ├─mesh
│ │ └─service
│ ├─elk
│ │ ├─kibana
│ │ │ └─config
│ │ └─logstash
│ │ ├─config
│ │ └─pipeline
│ ├─mysql
│ │ └─init
│ └─opensearch
│ └─logstash
│ ├─config
│ └─pipeline
├─frontend
│ ├─admin
│ │ ├─public
│ │ │ ├─images
│ │ │ └─locales
│ │ ├─server
│ │ ├─src
│ │ │ ├─@types
│ │ │ ├─components
│ │ │ ├─constants
│ │ │ ├─hooks
│ │ │ ├─libs
│ │ │ ├─pages
│ │ │ ├─service
│ │ │ ├─stores
│ │ │ ├─styles
│ │ │ └─utils
│ │ └─test
│ ├─portal
│ │ ├─public
│ │ │ ├─locales
│ │ │ └─styles
│ │ ├─src
│ │ │ ├─@types
│ │ │ ├─components
│ │ │ ├─constants
│ │ │ ├─hooks
│ │ │ ├─libs
│ │ │ │ └─Storage
│ │ │ ├─pages
│ │ │ ├─service
│ │ │ ├─stores
│ │ │ ├─styles
│ │ │ └─utils
│ │ └─test
│ └─practice-image
└─k8s
├─applications
│ ├─backend
│ │ ├─apigateway
│ │ │ └─ingress
│ │ ├─board-service
│ │ ├─config
│ │ ├─discovery
│ │ │ └─ingress
│ │ ├─portal-service
│ │ ├─reserve-check-service
│ │ ├─reserve-item-service
│ │ ├─reserve-request-service
│ │ └─user-service
│ └─frontend
│ ├─admin
│ │ └─ingress
│ └─portal
│ └─ingress
└─environments
├─configmaps
├─databases
│ └─mysql
│ └─init
├─jenkins
├─logging
│ └─elk
│ ├─elasticsearch
│ ├─kibana
│ │ └─ingress
│ └─logstash
├─nfs
├─rabbitmq
│ └─ingress
├─storage
├─vagrant
└─zipkin
└─ingress
```
### 디렉토리 설명
- `/backend`: Spring Boot를 기반으로 백앤드에 올려지는 서비스들
- `/backend/apigateway`: Microservice에 대한 API 관리 및 모니터링 서비스
- `/backend/board-service`: 게시판 서비스 (게시판, 게시물, 첨부파일 관리)
- `/backend/config`: 별도의 통합된 설정 관리 서비스 제공을 통해 환경 독립적 서비스 제공
- `/backend/discovery`: 마이크로서비스들을 등록하여 관리하고 요청 시 해당 서비스를 찾아 호출
- `/backend/user-service`: 사용자 서비스 (로그인, 회원가입, 비밀번호 찾기, 관리자)
- `/backend/portal-service`: 포털 공통 서비스 (메뉴, 코드, 컨텐츠, 권한, 인가, 배너, 첨부파일 관리)
- `/backend/reserve-check-service`: 예약 확인 서비스
- `/backend/reserve-item-service`: 예약 물품 서비스
- `/backend/reserve-request-service`: 예약 신청 서비스
- `/config`: backend 의 config 서버에서 사용하는 설정 yaml 파일 모음 폴더
- `/docker-compose`: Docker에 여러 컨테이너의 실행을 관리하는 yaml 구성 파일들
- `/frontend/admin`: Next.js + Typescript + Material UI 활용한 Admin Dashboard.
- `/frontend/portal`: Next.js + Typescript 활용한 React 기반 프론트엔드.
- `/frontend/practice-image`: 배너 이미지
- `/k8s`: Kubernetes 환경 배포를 위한 Resource 템플릿 yaml 파일
- `/k8s/applications`: Backend와 Frontend 애플리케이션의 k8s Resource 템플릿 yaml 파일
- `/k8s/environments/configmaps`: Pods에서 사용하는 환경변수로서 Key-Value 쌍의 형태로 저장된 객체 정의
- `/k8s/environments/databases`: MySQL 관련 객체 정의
- `/k8s/environments/jenkins`: Jenkins 관련 객체 정의
- `/k8s/environments/logging`: Centralized Logging을 위한 ELK 관련 객체 정의
- `/k8s/environments/nfs`: NFS 노드 볼륨 구성
- `/k8s/environments/rabbitmq`: Message Broker 관련 객체 정의
- `/k8s/environments/storage`: PersistentVolumeClaim 정의
- `/k8s/environments/vagrant`: 가상화 소프트웨어 개발환경의 생성을 쉽게 구성하도록 하는 Vagrant 관련 정의
- `/k8s/environments/zipkin`: 분산 트랜잭션 추적을 위한 Zipkin 관련 정의
## 백앤드 구동 방법
- 개발환경 Eclipse IDE 를 실행한다.
- Eclipse IDE 메뉴에서 File>Import… 를 클릭한다.
- Import 창이 열리면 Gradle>Existing Gradle Project 를 선택하고 Next 버튼을 클릭한다.
- Import Gradle Project 창이 열리면 Next 버튼을 클릭한다.
- Project root directory 에서 ${home}/workspace.edu/egovframe-msa-edu/backend/config를 선택하고 Finish 버튼을 클릭한다.
- 위의 과정을 반복하여 아래의 프로젝트를 import 한다. (소규모는 1-6, 대규모는 1-9)
1. config
2. discovery
3. apigateway
4. user-service
5. portal-service
6. board-service
7. reserve-check-service
8. reserve-item-service
9. reserve-request-service
- 모든 프로젝트를 import 하고 Project Explorer 를 확인하면 board-service, portal-service, user-service 프로젝트에 오류 표시가 출력된다. querydsl 로 generate 되는 클래스들을 build path 에 추가해야 한다.
- Window>Show View>Other 을 클릭해서 열린 창에서 Gradle>Gradle Tasks 를 선택하고 Open 버튼을 클릭하면 Gradle Tasks 탭이 열린다.
- Gradle Tasks 오른쪽 윗부분의 View Menu 버튼을 클릭해서 Show All Tasks 를 체크한다.
- Gradle Tasks 에서 portal-service>other>compileQuerydsl 을 더블클릭 또는 우클릭 후 Run Gradle Tasks 를 클릭하면 build 가 시작된다.
- Project Explorer 에서 board-service, portal-service, user-service 를 선택하고 F5 또는 우클릭 후 Refresh 를 클릭해서 프로젝트를 새로고침한다.
- Project Explorer 에서 board-service, portal-service, user-service 를 우클릭하고 Properties 를 클릭한다.
- Properties 창이 열리면 왼쪽 메뉴에서 Java Build Path를 선택하고 오른쪽 Source 탭에서 Add Folder… 버튼을 클릭한다.
- Source Folder Selection 창이 열리면 build>generated>querydsl 을 체크하고 OK 버튼을 클릭한다.
- Properties 창에서 Apply and Close 버튼을 클릭하면 창이 닫히면서 프로젝트를 다시 빌드하고 오류 표시는 사라진다.
(ELK 설정, Config 설정, OAuth 2.0 설정, API 호출 및 JUnit 테스트 관련해서는 [02.MSA템플릿 백엔드구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084631/02.MSA._.pdf) 파일을 참조한다.)
## 프론트앤드 구동 방법
```
node : 14.8.0
npm : 6.14.7
Visual Studio Code : latest
```
- https://nodejs.org/en/download 에서 다운로드 후 설치하고 버전을 확인한다.
```
node -v
npm -v
```
- Visual Studio Code 에서 frontend/admin 폴더를 연다.
- Terminal 에서 다음을 실행한다.
```
npm install
npm run dev
```
- 로그인 화면에서 email 란에 '1@gmail.com', password 란에 'test1234!' 입력 후 로그인한다.
(기타 상세한 내용은 [03.MSA템플릿 프론트엔드구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084632/03.MSA._.pdf) 파일을 참조한다.)
## 참조 화면
![Microservices Architecture](./images/msa.png)
![Authentication/Authorization-JWT](./images/jwt.png)
![Frontend](./images/frontend.png)
![Login](./images/login.png)
![Admin](./images/admin.png)
## 교육 교재
- [01.MSA템플릿 개요 및 개발환경 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084628/01.MSA._._.pdf)
- [01.MSA템플릿 개요 및 개발환경 이론.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084629/01.MSA._._.pdf)
- [02.MSA템플릿 백엔드구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084631/02.MSA._.pdf)
- [03.MSA템플릿 프론트엔드구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084632/03.MSA._.pdf)
- [04.MSA템플릿 이벤트스트림구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084633/04.MSA._.pdf)

View File

@@ -1,12 +1,12 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id "org.sonarqube" version "3.3" id 'org.sonarqube' version '3.5.0.2730'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
repositories { repositories {
@@ -14,8 +14,8 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
@@ -28,11 +28,11 @@ dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' // config implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' // config
implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus
implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73'
implementation 'net.logstash.logback:logstash-logback-encoder:7.2' // logstash logback implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'javax.xml.bind:jaxb-api:2.3.1' implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.6.9' implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.7.0'
compileOnly 'org.projectlombok:lombok' compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok'

View File

@@ -69,7 +69,7 @@ management:
info: info:
app: app:
name: Spring Cloud Gateway name: Spring Cloud Gateway
description: API <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD>/<2F><>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> ȿ<><C8BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> description: API 라우팅 및 보안, 모니터링/메트릭 등의 기능을 간단하고 효과적인 방법으로 제공
swagger-ui: http://localhost:8000/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config swagger-ui: http://localhost:8000/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config
messages: messages:

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <!DOCTYPE xml>
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
@@ -45,4 +46,4 @@
</root> </root>
</springProfile> </springProfile>
</configuration> </Configuration>

View File

@@ -1,14 +1,14 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id "org.sonarqube" version "3.3" id 'org.sonarqube' version '3.5.0.2730'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
// querydsl // querydsl
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
configurations { configurations {
@@ -23,14 +23,14 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
// implementation files('../../module-common/build/libs/module-common-0.1.jar') // 공통 모듈, @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다 // implementation files('../module-common/build/libs/module-common-4.2.0-plain.jar') // 공통 모듈, @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다
implementation 'org.egovframe.cloud:module-common:0.1' implementation 'org.egovframe.cloud:module-common:4.2.0'
implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.1.0') { implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.2.0') {
exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging' exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging'
} }
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
@@ -48,8 +48,8 @@ dependencies {
implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.73'
implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73'
implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.73'
implementation 'net.logstash.logback:logstash-logback-encoder:7.2' // logstash logback implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
implementation 'mysql:mysql-connector-java' implementation 'mysql:mysql-connector-java:8.0.33'
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
// querydsl // querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0' implementation 'com.querydsl:querydsl-jpa:5.0.0'
@@ -62,8 +62,8 @@ dependencies {
implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit' implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit'
// openapi docs // openapi docs
implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.6.9' implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.7.0'
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
// lombok // lombok
implementation 'org.projectlombok:lombok' implementation 'org.projectlombok:lombok'
@@ -72,10 +72,11 @@ dependencies {
testAnnotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'com.h2database:h2' testImplementation 'com.h2database:h2'
testImplementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.0' // 테스트시에만 출력 testImplementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.1' // 테스트시에만 출력
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.javassist:javassist:3.29.0-GA' implementation 'org.javassist:javassist:3.29.2-GA'
implementation 'org.webjars:webjars-locator-core:0.53'
} }
dependencyManagement { dependencyManagement {

View File

@@ -30,4 +30,4 @@ management:
info: info:
app: app:
name: Board Service name: Board Service
description: <EFBFBD>Խ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>, <20>Խù<D4BD><C3B9><EFBFBD><EFBFBD><EFBFBD>, ÷<><C3B7><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD><CFB0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> description: 게시판관리, 게시물관리, 첨부파일관리 기능을 제공

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <!DOCTYPE xml>
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
@@ -45,4 +46,4 @@
</root> </root>
</springProfile> </springProfile>
</configuration> </Configuration>

View File

@@ -1,11 +1,11 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
repositories { repositories {
@@ -13,8 +13,8 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
@@ -27,7 +27,7 @@ dependencies {
implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.73'
implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73'
implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.73'
implementation 'net.logstash.logback:logstash-logback-encoder:7.2' // logstash logback implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
} }

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <!DOCTYPE xml>
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
@@ -45,4 +46,4 @@
</root> </root>
</springProfile> </springProfile>
</configuration> </Configuration>

View File

@@ -1,11 +1,11 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
repositories { repositories {
@@ -13,8 +13,8 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {

View File

@@ -1,14 +1,14 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
// querydsl // querydsl
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
id 'java' id 'java'
id "org.sonarqube" version "2.7" id 'org.sonarqube' version '3.5.0.2730'
} }
group 'org.egovframe.cloud' group 'org.egovframe.cloud'
version '4.1.0' version '4.2.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
repositories { repositories {
@@ -30,13 +30,13 @@ configurations {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
// EgovAbstractServiceImpl // EgovAbstractServiceImpl
implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.1.0') { implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.2.0') {
exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging' exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging'
} }
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
@@ -44,7 +44,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation' // LocalValidatorFactoryBean implementation 'org.springframework.boot:spring-boot-starter-validation' // LocalValidatorFactoryBean
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'javassist:javassist:3.12.1.GA' implementation 'org.javassist:javassist:3.29.2-GA'
// querydsl // querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0' implementation 'com.querydsl:querydsl-jpa:5.0.0'
@@ -55,8 +55,8 @@ dependencies {
//openapi docs //openapi docs
implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.6.9' implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.7.0'
implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.6.9' implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.7.0'
//reactive //reactive
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc' implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -8,6 +8,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
@@ -41,6 +42,7 @@ public class MessageSourceConfig {
@Value("${spring.profiles.active:default}") @Value("${spring.profiles.active:default}")
private String profile; private String profile;
private static final String FILE_SEPARATOR = File.separator;
@Bean @Bean
public MessageSource messageSource() { public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
@@ -48,6 +50,9 @@ public class MessageSourceConfig {
if ("default".equals(profile)) { if ("default".equals(profile)) {
Path fileStorageLocation = Paths.get(messagesDirectory).toAbsolutePath().normalize(); Path fileStorageLocation = Paths.get(messagesDirectory).toAbsolutePath().normalize();
String dbMessages = StringUtils.cleanPath("file://" + fileStorageLocation + MESSAGES); String dbMessages = StringUtils.cleanPath("file://" + fileStorageLocation + MESSAGES);
if(FILE_SEPARATOR.equals("\\")) {//윈도우기반 자바시스템일 때 Could not parse properties file 에러방지
dbMessages = StringUtils.cleanPath("file:///" + fileStorageLocation + MESSAGES);
}
messageSource.setBasenames(dbMessages); messageSource.setBasenames(dbMessages);
} else { } else {
messageSource.setBasenames(messagesDirectory + MESSAGES); messageSource.setBasenames(messagesDirectory + MESSAGES);

View File

@@ -1,14 +1,14 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id "org.sonarqube" version "3.3" id 'org.sonarqube' version '3.5.0.2730'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
// querydsl // querydsl
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
configurations { configurations {
@@ -23,14 +23,14 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
// implementation files('../../module-common/build/libs/module-common-0.1.jar') // 공통 모듈, @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다 // implementation files('../module-common/build/libs/module-common-4.2.0-plain.jar') // 공통 모듈, @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다
implementation 'org.egovframe.cloud:module-common:0.1' implementation 'org.egovframe.cloud:module-common:4.2.0'
implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.1.0') { implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.2.0') {
exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging' exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging'
} }
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
@@ -50,9 +50,10 @@ dependencies {
implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.73'
implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73'
implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.73'
implementation 'net.logstash.logback:logstash-logback-encoder:7.2' // logstash logback implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
implementation 'commons-net:commons-net:3.8.0' // FTPClient implementation 'commons-io:commons-io:2.13.0'
implementation 'mysql:mysql-connector-java' implementation 'commons-net:commons-net:3.9.0' // FTPClient
implementation 'mysql:mysql-connector-java:8.0.33'
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
//messaging //messaging
@@ -64,7 +65,7 @@ dependencies {
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0' annotationProcessor 'com.querydsl:querydsl-apt:5.0.0'
// openapi docs // openapi docs
implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.6.9' implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.7.0'
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
// lombok // lombok
@@ -74,10 +75,11 @@ dependencies {
testAnnotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'com.h2database:h2' testImplementation 'com.h2database:h2'
testImplementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.0' // 테스트시에만 출력 testImplementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.1' // 테스트시에만 출력
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.javassist:javassist:3.29.0-GA' implementation 'org.javassist:javassist:3.29.2-GA'
implementation 'org.webjars:webjars-locator-core:0.53'
} }
dependencyManagement { dependencyManagement {

View File

@@ -150,7 +150,12 @@ public class AttachmentService extends AbstractService {
*/ */
@Transactional(readOnly = true) @Transactional(readOnly = true)
public AttachmentImageResponseDto loadImage(String imagename) { public AttachmentImageResponseDto loadImage(String imagename) {
return storageUtils.loadImage(imagename.replaceAll(EDITOR_FILE_SEPARATOR, FILE_SEPARATOR)); if(FILE_SEPARATOR.equals("\\")) {//윈도우기반 자바시스템일 때 하이픈 character to be escaped is missing 에러방지
imagename = imagename.replaceAll(EDITOR_FILE_SEPARATOR, "\\\\"); //getFileSystem().getPath에서 디스크의 경로를 사용할 때
} else { //리눅스 또는 맥 기반 자바시스템 경로일 때(아래)
imagename = imagename.replaceAll(EDITOR_FILE_SEPARATOR, FILE_SEPARATOR);
}
return storageUtils.loadImage(imagename);
} }
/** /**

View File

@@ -51,10 +51,16 @@ public class FileStorageUtils implements StorageUtils {
private final Path fileStorageLocation; private final Path fileStorageLocation;
private final Environment environment; private final Environment environment;
private final MessageUtil messageUtil; private final MessageUtil messageUtil;
private static final String FILE_SEPARATOR = File.separator;
public FileStorageUtils(Environment environment, MessageUtil messageUtil) { public FileStorageUtils(Environment environment, MessageUtil messageUtil) {
this.environment = environment; this.environment = environment;
this.fileStorageLocation = Paths.get(environment.getProperty("file.directory")).toAbsolutePath().normalize(); String envFileDir = "";
envFileDir = environment.getProperty("file.directory");
if(FILE_SEPARATOR.equals("\\")) {//윈도우기반 자바시스템일 때 경로 에러방지
envFileDir = envFileDir.replaceAll("/", "\\\\");
}
this.fileStorageLocation = Paths.get(envFileDir).toAbsolutePath().normalize();
this.messageUtil = messageUtil; this.messageUtil = messageUtil;
} }
@@ -185,8 +191,9 @@ public class FileStorageUtils implements StorageUtils {
Path path = getStorePath(basePath); Path path = getStorePath(basePath);
Path target = path.resolve(filename); Path target = path.resolve(filename);
Files.copy(file.getInputStream(), target, StandardCopyOption.REPLACE_EXISTING); InputStream inputStream = file.getInputStream();
Files.copy(inputStream, target, StandardCopyOption.REPLACE_EXISTING);
inputStream.close(); //윈도우 시스템에서도 업로드 시 Temp폴더의 delete file 에러방지코드 추가
return filename; return filename;
} catch (IOException ex) { } catch (IOException ex) {
log.error("Could not stored file", ex); log.error("Could not stored file", ex);

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <!DOCTYPE xml>
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
@@ -45,4 +46,4 @@
</root> </root>
</springProfile> </springProfile>
</configuration> </Configuration>

View File

@@ -1,11 +1,11 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
configurations { configurations {
@@ -20,14 +20,14 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
// implementation files('../../module-common/build/libs/module-common-0.1.jar') // @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다 // implementation files('../module-common/build/libs/module-common-4.2.0-plain.jar') // @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다
implementation 'org.egovframe.cloud:module-common:0.1' implementation 'org.egovframe.cloud:module-common:4.2.0'
implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.1.0') { implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.2.0') {
exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging' exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging'
} }
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc' implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
@@ -41,11 +41,11 @@ dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j' implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73'
implementation 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.1' implementation 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.11'
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth' implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin' implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
implementation 'net.logstash.logback:logstash-logback-encoder:7.2' // logstash logback implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
//messaging //messaging
implementation 'org.springframework.cloud:spring-cloud-stream' implementation 'org.springframework.cloud:spring-cloud-stream'
@@ -54,10 +54,10 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'dev.miku:r2dbc-mysql:0.8.2.RELEASE' implementation 'dev.miku:r2dbc-mysql:0.8.2.RELEASE'
implementation 'mysql:mysql-connector-java' implementation 'mysql:mysql-connector-java:8.0.33'
// openapi docs // openapi docs
implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.6.9' implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.7.0'
//lombok //lombok
implementation 'org.projectlombok:lombok' implementation 'org.projectlombok:lombok'
@@ -71,6 +71,8 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test' testImplementation 'io.projectreactor:reactor-test'
testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.webjars:webjars-locator-core:0.53'
} }
test { test {

View File

@@ -6,8 +6,6 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import reactivefeign.spring.config.EnableReactiveFeignClients; import reactivefeign.spring.config.EnableReactiveFeignClients;
//import reactor.blockhound.BlockHound;
import java.security.Security; import java.security.Security;
@ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reservechecksevice"}) // org.egovframe.cloud.common package 포함하기 위해 @ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reservechecksevice"}) // org.egovframe.cloud.common package 포함하기 위해

View File

@@ -15,4 +15,4 @@ management:
info: info:
app: app:
name: Reserve Check Service name: Reserve Check Service
description: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>Ȯ<EFBFBD><C8AE>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> description: 예약시스템 기능 중 예약확인, 예약승인/취소 기능을 제공

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <!DOCTYPE xml>
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
@@ -45,4 +46,4 @@
</root> </root>
</springProfile> </springProfile>
</configuration> </Configuration>

View File

@@ -1,11 +1,11 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
configurations { configurations {
@@ -20,14 +20,14 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
// implementation files('../../module-common/build/libs/module-common-0.1.jar') // @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다 // implementation files('../module-common/build/libs/module-common-4.2.0-plain.jar') // @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다
implementation 'org.egovframe.cloud:module-common:0.1' implementation 'org.egovframe.cloud:module-common:4.2.0'
implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.1.0') { implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.2.0') {
exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging' exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging'
} }
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc' implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
@@ -41,19 +41,19 @@ dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j' implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73'
implementation 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.1' implementation 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.11'
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth' implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin' implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
implementation 'net.logstash.logback:logstash-logback-encoder:7.2' // logstash logback implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
implementation 'dev.miku:r2dbc-mysql:0.8.2.RELEASE' implementation 'dev.miku:r2dbc-mysql:0.8.2.RELEASE'
implementation 'mysql:mysql-connector-java' implementation 'mysql:mysql-connector-java:8.0.33'
// openapi docs // openapi docs
implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.6.9' implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.7.0'
//messaging //messaging
implementation 'org.springframework.cloud:spring-cloud-stream' implementation 'org.springframework.cloud:spring-cloud-stream'
@@ -71,6 +71,8 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test' testImplementation 'io.projectreactor:reactor-test'
testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.webjars:webjars-locator-core:0.53'
} }
test { test {

View File

@@ -15,4 +15,4 @@ management:
info: info:
app: app:
name: Reserve Item Service name: Reserve Item Service
description: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>๰ǰ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> description: 예약시스템 기능 중 예약지역, 예약물품 관리 기능을 제공

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <!DOCTYPE xml>
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
@@ -45,4 +46,4 @@
</root> </root>
</springProfile> </springProfile>
</configuration> </Configuration>

View File

@@ -1,11 +1,11 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
configurations { configurations {
@@ -20,15 +20,14 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
// implementation files('../../module-common/build/libs/module-common-0.1.jar') // @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다 // implementation files('../module-common/build/libs/module-common-4.2.0-plain.jar') // @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다
implementation 'org.egovframe.cloud:module-common:0.1' implementation 'org.egovframe.cloud:module-common:4.2.0'
implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.1.0') { implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.2.0') {
exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging' exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging'
} }
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc' implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
@@ -42,11 +41,11 @@ dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j' implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73'
implementation 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.1' implementation 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.11'
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth' implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin' implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
implementation 'net.logstash.logback:logstash-logback-encoder:7.2' // logstash logback implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
//messaging //messaging
implementation 'org.springframework.cloud:spring-cloud-stream' implementation 'org.springframework.cloud:spring-cloud-stream'
@@ -57,10 +56,10 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'dev.miku:r2dbc-mysql:0.8.2.RELEASE' implementation 'dev.miku:r2dbc-mysql:0.8.2.RELEASE'
implementation 'mysql:mysql-connector-java' implementation 'mysql:mysql-connector-java:8.0.33'
// openapi docs // openapi docs
implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.6.9' implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.7.0'
//lombok //lombok
implementation 'org.projectlombok:lombok' implementation 'org.projectlombok:lombok'
@@ -75,6 +74,8 @@ dependencies {
testImplementation 'io.projectreactor:reactor-test' testImplementation 'io.projectreactor:reactor-test'
testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.springframework.amqp:spring-rabbit-test' testImplementation 'org.springframework.amqp:spring-rabbit-test'
implementation 'org.webjars:webjars-locator-core:0.53'
} }
test { test {

View File

@@ -15,4 +15,4 @@ management:
info: info:
app: app:
name: Reserve Request Service name: Reserve Request Service
description: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> description: 예약시스템 기능 중 예약신청 기능을 제공

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <!DOCTYPE xml>
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
@@ -45,4 +46,4 @@
</root> </root>
</springProfile> </springProfile>
</configuration> </Configuration>

View File

@@ -1,14 +1,14 @@
plugins { plugins {
id 'org.springframework.boot' version '2.7.0' id 'org.springframework.boot' version '2.7.12'
id "org.sonarqube" version "2.7" id 'org.sonarqube' version '3.5.0.2730'
id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
// querydsl // querydsl
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
id 'java' id 'java'
} }
group = 'org.egovframe.cloud' group = 'org.egovframe.cloud'
version = '0.1' version = '1.0.0'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
configurations { configurations {
@@ -23,14 +23,14 @@ repositories {
} }
ext { ext {
set('springCloudVersion', "2021.0.3") set('springCloudVersion', '2021.0.7')
set('log4j2.version', "2.17.2") // log4j 보안 패치 set('log4j2.version', '2.20.0') // log4j 보안 패치
} }
dependencies { dependencies {
// implementation files('../../module-common/build/libs/module-common-0.1.jar') // 공통 모듈, @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다 // implementation files('../module-common/build/libs/module-common-4.2.0-plain.jar') // 공통 모듈, @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다
implementation 'org.egovframe.cloud:module-common:0.1' implementation 'org.egovframe.cloud:module-common:4.2.0'
implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.1.0') { implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.2.0') {
exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging' exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging'
} }
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
@@ -50,8 +50,8 @@ dependencies {
implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.73'
implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.73'
implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.73' implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:9.0.73'
implementation 'net.logstash.logback:logstash-logback-encoder:7.2' // logstash logback implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
implementation 'mysql:mysql-connector-java' implementation 'mysql:mysql-connector-java:8.0.33'
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
// querydsl // querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0' implementation 'com.querydsl:querydsl-jpa:5.0.0'
@@ -61,10 +61,10 @@ dependencies {
implementation 'org.ehcache:ehcache' implementation 'org.ehcache:ehcache'
implementation 'javax.cache:cache-api' // expiry를 위해 필요 implementation 'javax.cache:cache-api' // expiry를 위해 필요
implementation 'com.google.api-client:google-api-client:1.35.1' implementation 'com.google.api-client:google-api-client:2.2.0'
// openapi docs // openapi docs
implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.6.9' implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.7.0'
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
// lombok // lombok
@@ -73,11 +73,12 @@ dependencies {
testImplementation 'org.projectlombok:lombok' testImplementation 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'com.h2database:h2' testImplementation 'com.h2database:h2'
testImplementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.0' testImplementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.javassist:javassist:3.29.0-GA' implementation 'org.javassist:javassist:3.29.0-GA'
implementation 'org.webjars:webjars-locator-core:0.53'
} }
dependencyManagement { dependencyManagement {

View File

@@ -2,12 +2,13 @@ package org.egovframe.cloud.userservice.config;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.egovframe.cloud.userservice.service.user.UserService; import org.egovframe.cloud.userservice.service.user.UserService;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.SecurityFilterChain;
import static org.egovframe.cloud.common.config.GlobalConstant.SECURITY_PERMITALL_ANTPATTERNS; import static org.egovframe.cloud.common.config.GlobalConstant.SECURITY_PERMITALL_ANTPATTERNS;
@@ -31,11 +32,15 @@ import static org.egovframe.cloud.common.config.GlobalConstant.SECURITY_PERMITAL
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@EnableWebSecurity // Spring Security 설정들을 활성화시켜 준다 @EnableWebSecurity // Spring Security 설정들을 활성화시켜 준다
public class SecurityConfig extends WebSecurityConfigurerAdapter { public class SecurityConfig {
private final TokenProvider tokenProvider; private final TokenProvider tokenProvider;
private final UserService userService; private final UserService userService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
@Bean
AuthenticationManager authenticationManager(AuthenticationConfiguration authConfiguration) throws Exception {
return authConfiguration.getAuthenticationManager();
}
/** /**
* 스프링 시큐리티 설정 * 스프링 시큐리티 설정
@@ -43,11 +48,21 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
* @param http * @param http
* @throws Exception * @throws Exception
*/ */
@Override @Bean
protected void configure(HttpSecurity http) throws Exception { public SecurityFilterChain configure(HttpSecurity http) throws Exception {
AuthenticationManager authenticationManager = authenticationManager(http.getSharedObject(AuthenticationConfiguration.class));
/**
* 로그인 인증정보를 받아 토큰을 발급할 수 있도록 필터를 등록해준다.
*
* @return
* @throws Exception
*/
AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager, tokenProvider, userService);
http http
.csrf().disable() .csrf().disable().headers().frameOptions().disable()
.headers().frameOptions().disable()
.and() .and()
.sessionManagement() .sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 토큰 사용하기 때문에 세션은 비활성화 .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 토큰 사용하기 때문에 세션은 비활성화
@@ -56,32 +71,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers(SECURITY_PERMITALL_ANTPATTERNS).permitAll() .antMatchers(SECURITY_PERMITALL_ANTPATTERNS).permitAll()
.anyRequest().access("@authorizationService.isAuthorization(request, authentication)") // 호출 시 권한 인가 데이터 확인 .anyRequest().access("@authorizationService.isAuthorization(request, authentication)") // 호출 시 권한 인가 데이터 확인
.and() .and()
.addFilter(getAuthenticationFilter()) .addFilter(authenticationFilter)
.logout() .logout()
.logoutSuccessUrl("/"); .logoutSuccessUrl("/");
}
/** return http.build();
* 로그인 인증정보를 받아 토큰을 발급할 수 있도록 필터를 등록해준다.
*
* @return
* @throws Exception
*/
private AuthenticationFilter getAuthenticationFilter() throws Exception {
return new AuthenticationFilter(authenticationManager(), tokenProvider, userService);
}
/**
* 인증 관련 - 로그인 처리
* DB 에서 조회하여 일치하는지 체크한다.
*
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// userService.loadUserByUsername 메소드
auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
} }
} }

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <!DOCTYPE xml>
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
@@ -45,4 +46,4 @@
</root> </root>
</springProfile> </springProfile>
</configuration> </Configuration>

View File

@@ -3,7 +3,7 @@ database:
spring: spring:
datasource: datasource:
url: ${database.url}?serverTimezone=Asia/Seoul url: ${database.url}?serverTimezone=Asia/Seoul&autoReconnect=true&validationQuery=select 1
username: msaportal username: msaportal
password: msaportal password: msaportal
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver

View File

@@ -3,7 +3,7 @@ database:
spring: spring:
datasource: datasource:
url: ${database.url}?serverTimezone=Asia/Seoul url: ${database.url}?serverTimezone=Asia/Seoul&autoReconnect=true&validationQuery=select 1
username: msaportal username: msaportal
password: msaportal password: msaportal
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver

View File

@@ -3,7 +3,7 @@ database:
spring: spring:
datasource: datasource:
url: ${database.url}?serverTimezone=Asia/Seoul url: ${database.url}?serverTimezone=Asia/Seoul&autoReconnect=true&validationQuery=select 1
username: msaportal username: msaportal
password: msaportal password: msaportal
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,10 @@
"scripts": { "scripts": {
"start:dev": "next", "start:dev": "next",
"dev": "ts-node --project tsconfig.server.json server/index.ts", "dev": "ts-node --project tsconfig.server.json server/index.ts",
"dev:sm": "SITE_ID=4 ts-node --project tsconfig.server.json server/index.ts", "dev:sm": "SITE_ID=4 npm run dev",
"dev:lg": "SITE_ID=1 npm run dev",
"dev:smWin": "set SITE_ID=4&&npm run dev",
"dev:lgWin": "set SITE_ID=1&&npm run dev",
"clean:dev": "rimraf .next", "clean:dev": "rimraf .next",
"build:server": "tsc --project tsconfig.server.json", "build:server": "tsc --project tsconfig.server.json",
"build:next": "next build", "build:next": "next build",

View File

@@ -7,7 +7,7 @@
"npm": "6.14.7" "npm": "6.14.7"
}, },
"scripts": { "scripts": {
"dev": "next dev", "dev": "ts-node --transpile-only --project tsconfig.server.json server/index.ts",
"dev:sm": "SITE_ID=3 npm run dev", "dev:sm": "SITE_ID=3 npm run dev",
"dev:lg": "SITE_ID=2 npm run dev", "dev:lg": "SITE_ID=2 npm run dev",
"dev:smWin": "set SITE_ID=3&&npm run dev", "dev:smWin": "set SITE_ID=3&&npm run dev",

View File

@@ -1137,6 +1137,7 @@ footer div > span a {
font-size: 32px; font-size: 32px;
line-height: 32px; line-height: 32px;
text-shadow: 10px 10px 10px rgba(0, 0, 0, 0.5); text-shadow: 10px 10px 10px rgba(0, 0, 0, 0.5);
background: rgba(0, 0, 0, 0.3);
/* overflow: hidden; /* overflow: hidden;
white-space: break-spaces; white-space: break-spaces;
word-break: keep-all; */ word-break: keep-all; */
@@ -1147,6 +1148,7 @@ footer div > span a {
left: 6vw; left: 6vw;
color: rgba(255, 255, 255, 0.7); color: rgba(255, 255, 255, 0.7);
font-size: 1.7vw; font-size: 1.7vw;
background: rgba(0, 0, 0, 0.3);
} }
#main .slideBox a:before { #main .slideBox a:before {
content: '╋'; content: '╋';
@@ -1185,7 +1187,7 @@ footer div > span a {
#main .slide .reservBox { #main .slide .reservBox {
position: absolute; position: absolute;
top: 600px; top: 650px;
left: 0; left: 0;
z-index: 10; z-index: 10;
width: 100%; width: 100%;

View File

@@ -1140,7 +1140,8 @@ footer div > span a {
overflow: hidden; overflow: hidden;
} }
#main .slide div.slide-title p { #main .slide div.slide-title p {
height: 12vw; /* height: 12vw; */
background: rgba(0, 0, 0, 0.3);
color: #fff; color: #fff;
font-size: 2.7vw; font-size: 2.7vw;
font-weight: 600; font-weight: 600;
@@ -1171,6 +1172,7 @@ footer div > span a {
left: 6vw; left: 6vw;
color: rgba(255, 255, 255, 0.7); color: rgba(255, 255, 255, 0.7);
font-size: 1.7vw; font-size: 1.7vw;
background: rgba(0, 0, 0, 0.3);
} }
#main .slide a:before { #main .slide a:before {
content: '╋'; content: '╋';

View File

@@ -0,0 +1,30 @@
import { loadEnvConfig } from '@next/env'
import express, { Request, Response } from 'express'
import next from 'next'
loadEnvConfig('./', process.env.NODE_ENV !== 'production')
const port = process.env.PORT || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const startServer = async () => {
try {
await app.prepare()
const server = express()
server.all('*', (req: Request, res: Response) => {
return handle(req, res)
})
server.listen(port, (err?: any) => {
if (err) throw err
console.log(`> Ready on localhost:${port} - env ${process.env.NODE_ENV}`)
})
} catch (error) {
console.error(error)
process.exit(1)
}
}
startServer()

View File

@@ -146,15 +146,18 @@ const BoardEdit = (props: BoardEditProps) => {
data = produce(data, draft => { data = produce(data, draft => {
draft.attachmentCode = result draft.attachmentCode = result
}) })
}
}
})
}
})
}
save(data) save(data)
} }
}
})
}else{
save(data)
}
})
}else{
save(data)
}
}
}, [postData, attachList]) }, [postData, attachList])
useEffect(() => { useEffect(() => {

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json", // 기본설정을 포함한다
"compilerOptions": {
"module": "commonjs", // commonJs 사용하도록 override
"outDir": "dist", // 빌드 파일 경로 (production mode)
"noEmit": false // 서버에 대한 결과 파일을 내보내지 않음 (production mode)
},
"include": ["server"] // server/ 디렉토리 아래에 있는 파일만 컴파일 (production mode)
}

BIN
images/admin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
images/frontend.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

BIN
images/jwt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
images/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

BIN
images/msa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

77
k8s/README.md Normal file
View File

@@ -0,0 +1,77 @@
# Deploy services on Kubernetes
In Kubernetes, the service consists of two components,
1. Environments
2. Applications
And you can choose the storage in the application either NFS or Cinder provided by Openstack(used by [Pasta](http://paas-ta.kr))
# Prerequisites
## Install kustomize
If you are using kubectl 1.14 or later, it embeded kustomize. So please ignore this section.
I recommend that you install the latest version of [kubectl](https://kubectl.docs.kubernetes.io/installation/kubectl/) for your cluster instead of installing kustomize.
Even so, if you want to use kustomize, refer to [official kustomize doc](https://kustomize.io/).
# Deploy service
You must follow deployment order.
## Deployenvironments
```sh
$ kustomize build k8s/environments | kubectl apply -f -
```
or if you are using the kubectl only,
```sh
$ kubectl apply -k k8s/environments
```
## Deploy applications
If you want to use NFS as a main storage,
```sh
$ kustomize build k8s/stoage/nfs | kubectl apply -f -
```
or
```sh
$ kubectl apply -k k8s/stoage/nfs
```
In case of using Openstack storage(CINDER) as a main storage,
```sh
$ kustomize build k8s/stoage/openstack | kubectl apply -f -
```
or
```sh
$ kubectl apply -k k8s/stoage/openstack
```
# Shutdown service
Simply apply deployment in reverse order.
If you are using nfs,
```sh
$ kustomize build k8s/environments | kubectl delete -f -
$ kustomize build k8s/stoage/nfs | kubectl delete -f - --wait
```
or
```sh
$ kubectl delete -k k8s/environments
$ kubectl delete -k k8s/stoage/nfs --wait
```
The case of openstack is similar, so it is omitted.

View File

@@ -0,0 +1,75 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- config/service.yaml
- discovery/service.yaml
- portal-service/service.yaml
- reserve-item-service/service.yaml
- user-service/service.yaml
- board-service/service.yaml
- reserve-request-service/service.yaml
- reserve-check-service/service.yaml
- discovery/ingress/ingress.yaml
- apigateway/ingress/ingress.yaml
- config/deployment.yaml
- discovery/deployment.yaml
- portal-service/deployment.yaml
- reserve-item-service/deployment.yaml
- user-service/deployment.yaml
- board-service/deployment.yaml
- apigateway/deployment.yaml
- apigateway/service.yaml
- reserve-request-service/deployment.yaml
- reserve-check-service/deployment.yaml
- portal-service/autoscaler.yaml
- reserve-item-service/autoscaler.yaml
- user-service/autoscaler.yaml
- board-service/autoscaler.yaml
- apigateway/autoscaler.yaml
- reserve-request-service/autoscaler.yaml
- reserve-check-service/autoscaler.yaml
images:
- name: egovframe/egovframe-msa-edu-backend-apigateway:latest
# newName: foobar/egovframe-msa-edu-backend-apigateway
newTag: latest
- name: egovframe/egovframe-msa-edu-backend-board-service:latest
# newName: foobar/egovframe-msa-edu-backend-board-service
newTag: latest
- name: egovframe/egovframe-msa-edu-backend-config:latest
# newName: foobar/egovframe-msa-edu-backend-config
newTag: latest
- name: egovframe/egovframe-msa-edu-backend-discovery:latest
# newName: foobar/egovframe-msa-edu-backend-discovery
newTag: latest
- name: egovframe/egovframe-msa-edu-backend-portal-service:latest
# newName: foobar/egovframe-msa-edu-backend-portal-service
newTag: latest
- name: egovframe/egovframe-msa-edu-backend-reserve-check-service:latest
# newName: foobar/egovframe-msa-edu-backend-reserve-check-service
newTag: latest
- name: egovframe/egovframe-msa-edu-backend-reserve-item-service:latest
# newName: foobar/egovframe-msa-edu-backend-reserve-item-service
newTag: latest
- name: egovframe/egovframe-msa-edu-backend-reserve-request-service:latest
# newName: foobar/egovframe-msa-edu-backend-reserve-request-service
newTag: latest
- name: egovframe/egovframe-msa-edu-backend-user-service:latest
# newName: foobar/egovframe-msa-edu-backend-user-service
newTag: latest
patches:
- target:
name: apigateway-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: "<TODO: 백엔드 API 게이트웨이 도메인>"
- target:
name: discovery-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: "<TODO: 백엔드 유레카 서버 도메인>"

View File

@@ -0,0 +1,35 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- portal/service.yaml
- admin/service.yaml
- portal/ingress/ingress.yaml
- admin/ingress/ingress.yaml
- portal/deployment.yaml
- admin/deployment.yaml
- portal/autoscaler.yaml
- admin/autoscaler.yaml
images:
- name: egovframe/egovframe-msa-edu-frontend-admin:latest
# newName: foobar/egovframe-msa-edu-frontend-admin
newTag: latest
- name: egovframe/egovframe-msa-edu-frontend-portal:latest
# newName: foobar/egovframe-msa-edu-frontend-portal
newTag: latest
patches:
- target:
name: frontend-portal-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: "<TODO: 프론트엔드 포털 도메인>"
- target:
name: frontend-admin-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: "<TODO: 프론트엔드 관리자 도메인>"

View File

@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- frontend/
- backend/

View File

@@ -0,0 +1,60 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- configmaps/backend-configmap.yaml
- configmaps/common-configmap.yaml
- nfs/sa.yaml
- nfs/sc.yaml
- nfs/deployment.yaml
- databases/mysql/secret.yaml
- databases/mysql/configmap.yaml
- databases/mysql/service.yaml
- databases/mysql/pvc.yaml
- databases/mysql/statefulset.yaml
- rabbitmq/service.yaml
- rabbitmq/ingress/ingress.yaml
- rabbitmq/deployment.yaml
- zipkin/service.yaml
- zipkin/ingress/ingress.yaml
- zipkin/deployment.yaml
- jenkins/sa.yaml
- jenkins/service.yaml
- jenkins/ingress.yaml
- jenkins/pvc.yaml
- jenkins/statefulset.yaml
- logging/elk/kibana/configmap.yaml
- logging/elk/kibana/service.yaml
- logging/elk/kibana/ingress/ingress.yaml
- logging/elk/kibana/deployment.yaml
- logging/elk/logstash/service.yaml
- logging/elk/logstash/configmap.yaml
- logging/elk/logstash/deplyment.yaml
- logging/elk/elasticsearch/service.yaml
- logging/elk/elasticsearch/deployment.yaml
patches:
- target:
name: rabbitmq-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: "<TODO: RabbitMQ 도메인>"
- target:
name: zipkin-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: "<TODO: Zipkin 도메인>"
- target:
name: jenkins-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: "<TODO: 젠킨스 도메인>"
- target:
name: kibana-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: "<TODO: ELK Kibana 도메인>"

View File

@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../environments
resources:
- pvc-nfs.yaml

View File

@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../environments
resources:
- pvc-egovcp.yaml