4.2.x <- contribution
This commit is contained in:
35
.github/ISSUE_TEMPLATE/amendment_request.yml
vendored
Normal file
35
.github/ISSUE_TEMPLATE/amendment_request.yml
vendored
Normal 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
74
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal 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
|
||||||
51
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
51
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal 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
35
.github/pull_request_template.md
vendored
Normal 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
4
.gitignore
vendored
@@ -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
201
LICENSE
Normal 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
222
README-en.md
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
# MSA templates (for training)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## 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)
|
||||||
14
README.md
14
README.md
@@ -175,7 +175,7 @@
|
|||||||
- Source Folder Selection 창이 열리면 build>generated>querydsl 을 체크하고 OK 버튼을 클릭한다.
|
- Source Folder Selection 창이 열리면 build>generated>querydsl 을 체크하고 OK 버튼을 클릭한다.
|
||||||
- Properties 창에서 Apply and Close 버튼을 클릭하면 창이 닫히면서 프로젝트를 다시 빌드하고 오류 표시는 사라진다.
|
- Properties 창에서 Apply and Close 버튼을 클릭하면 창이 닫히면서 프로젝트를 다시 빌드하고 오류 표시는 사라진다.
|
||||||
|
|
||||||
(ELK 설정, Config 설정, OAuth 2.0 설정, API 호출 및 JUnit 테스트 관련해서는 [02.MSA템플릿 백엔드구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/15290484/02.MSA._.pdf) 파일을 참조한다.)
|
(ELK 설정, Config 설정, OAuth 2.0 설정, API 호출 및 JUnit 테스트 관련해서는 [02.MSA템플릿 백엔드구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084631/02.MSA._.pdf) 파일을 참조한다.)
|
||||||
|
|
||||||
## 프론트앤드 구동 방법
|
## 프론트앤드 구동 방법
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ npm run dev
|
|||||||
|
|
||||||
- 로그인 화면에서 email 란에 '1@gmail.com', password 란에 'test1234!' 입력 후 로그인한다.
|
- 로그인 화면에서 email 란에 '1@gmail.com', password 란에 'test1234!' 입력 후 로그인한다.
|
||||||
|
|
||||||
(기타 상세한 내용은 [03.MSA템플릿 프론트엔드구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/14988291/03.MSA._.pdf) 파일을 참조한다.)
|
(기타 상세한 내용은 [03.MSA템플릿 프론트엔드구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084632/03.MSA._.pdf) 파일을 참조한다.)
|
||||||
|
|
||||||
## 참조 화면
|
## 참조 화면
|
||||||
|
|
||||||
@@ -214,8 +214,8 @@ npm run dev
|
|||||||
|
|
||||||
## 교육 교재
|
## 교육 교재
|
||||||
|
|
||||||
- [01.MSA템플릿 개요 및 개발환경_실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/14988282/01.MSA._._.pdf)
|
- [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/14988284/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/15290484/02.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/14988291/03.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/14988292/04.MSA._.pdf)
|
- [04.MSA템플릿 이벤트스트림구성 및 실습.pdf](https://github.com/eGovFramework/egovframe-msa-edu/files/11084633/04.MSA._.pdf)
|
||||||
@@ -27,6 +27,7 @@ dependencies {
|
|||||||
implementation 'org.springframework.cloud:spring-cloud-starter-config' // config
|
implementation 'org.springframework.cloud:spring-cloud-starter-config' // config
|
||||||
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 'net.logstash.logback:logstash-logback-encoder:7.4' // 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'
|
||||||
|
|||||||
@@ -44,6 +44,10 @@ 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-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 'org.apache.tomcat:tomcat-annotations-api: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-websocket:9.0.73'
|
||||||
implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
|
implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
|
||||||
implementation 'mysql:mysql-connector-java:8.0.33'
|
implementation 'mysql:mysql-connector-java:8.0.33'
|
||||||
implementation 'io.jsonwebtoken:jjwt:0.9.1'
|
implementation 'io.jsonwebtoken:jjwt:0.9.1'
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ dependencies {
|
|||||||
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'
|
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'
|
||||||
implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus
|
implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-actuator' // bus
|
implementation 'org.springframework.boot:spring-boot-starter-actuator' // bus
|
||||||
|
implementation 'org.apache.tomcat:tomcat-annotations-api: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-websocket:9.0.73'
|
||||||
implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // 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'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ spring:
|
|||||||
config:
|
config:
|
||||||
server:
|
server:
|
||||||
native:
|
native:
|
||||||
search-locations: file:./config
|
search-locations: ${search.location:file:///${user.home}/workspace.edu/egovframe-msa-edu/config} # Windows
|
||||||
# search-locations: ${search.location:file:///${user.home}/workspace.edu/egovframe-msa-edu/config} # Windows
|
|
||||||
# search-locations: file://${user.home}/workspace.edu/egovframe-msa-edu/config # MacOS
|
# search-locations: file://${user.home}/workspace.edu/egovframe-msa-edu/config # MacOS
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
host: ${rabbitmq.hostname:localhost}
|
host: ${rabbitmq.hostname:localhost}
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ ext {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
|
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||||
|
implementation 'org.apache.tomcat:tomcat-annotations-api: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-websocket:9.0.73'
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
backend/module-common/build/libs/module-common-4.1.0-plain.jar
Normal file
BIN
backend/module-common/build/libs/module-common-4.1.0-plain.jar
Normal file
Binary file not shown.
BIN
backend/module-common/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
backend/module-common/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
backend/module-common/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
backend/module-common/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ dependencies {
|
|||||||
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
|
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
|
||||||
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
|
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
|
||||||
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
|
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
|
||||||
|
implementation 'org.apache.tomcat:tomcat-annotations-api: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-websocket:9.0.73'
|
||||||
implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
|
implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
|
||||||
implementation 'commons-io:commons-io:2.13.0'
|
implementation 'commons-io:commons-io:2.13.0'
|
||||||
implementation 'commons-net:commons-net:3.9.0' // FTPClient
|
implementation 'commons-net:commons-net:3.9.0' // FTPClient
|
||||||
@@ -62,7 +66,7 @@ dependencies {
|
|||||||
|
|
||||||
// openapi docs
|
// openapi docs
|
||||||
implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.7.0'
|
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'
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ 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.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 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.11'
|
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'
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ 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.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 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.11'
|
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'
|
||||||
@@ -83,3 +84,4 @@ dependencyManagement {
|
|||||||
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
|
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ 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.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 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:3.2.11'
|
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'
|
||||||
@@ -51,6 +52,7 @@ dependencies {
|
|||||||
implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit'
|
implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-amqp'
|
implementation 'org.springframework.boot:spring-boot-starter-amqp'
|
||||||
|
|
||||||
|
|
||||||
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'
|
||||||
|
|||||||
@@ -46,14 +46,16 @@ 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-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 'org.apache.tomcat:tomcat-annotations-api: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-websocket:9.0.73'
|
||||||
|
implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // logstash logback
|
||||||
implementation 'mysql:mysql-connector-java:8.0.33'
|
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'
|
||||||
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0'
|
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0'
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-cache'
|
implementation 'org.springframework.boot:spring-boot-starter-cache'
|
||||||
implementation 'org.ehcache:ehcache'
|
implementation 'org.ehcache:ehcache'
|
||||||
@@ -63,7 +65,7 @@ dependencies {
|
|||||||
|
|
||||||
// openapi docs
|
// openapi docs
|
||||||
implementation 'org.springdoc:springdoc-openapi-webmvc-core:1.7.0'
|
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'
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 one or more lines are too long
11794
frontend/admin/package-lock.json
generated
11794
frontend/admin/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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%;
|
||||||
|
|||||||
@@ -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: '╋';
|
||||||
|
|||||||
30
frontend/portal/server/index.ts
Normal file
30
frontend/portal/server/index.ts
Normal 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()
|
||||||
@@ -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(() => {
|
||||||
|
|||||||
9
frontend/portal/tsconfig.server.json
Normal file
9
frontend/portal/tsconfig.server.json
Normal 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)
|
||||||
|
}
|
||||||
77
k8s/README.md
Normal file
77
k8s/README.md
Normal 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.
|
||||||
75
k8s/applications/backend/kustomization.yaml
Normal file
75
k8s/applications/backend/kustomization.yaml
Normal 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: 백엔드 유레카 서버 도메인>"
|
||||||
35
k8s/applications/frontend/kustomization.yaml
Normal file
35
k8s/applications/frontend/kustomization.yaml
Normal 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: 프론트엔드 관리자 도메인>"
|
||||||
5
k8s/applications/kustomization.yaml
Normal file
5
k8s/applications/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- frontend/
|
||||||
|
- backend/
|
||||||
60
k8s/environments/kustomization.yaml
Normal file
60
k8s/environments/kustomization.yaml
Normal 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 도메인>"
|
||||||
6
k8s/storage/nfs/kustomization.yaml
Normal file
6
k8s/storage/nfs/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
bases:
|
||||||
|
- ../../environments
|
||||||
|
resources:
|
||||||
|
- pvc-nfs.yaml
|
||||||
16
k8s/storage/nfs/pvc-nfs.yaml
Normal file
16
k8s/storage/nfs/pvc-nfs.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: backend-pvc
|
||||||
|
labels:
|
||||||
|
env: production
|
||||||
|
tier: backend
|
||||||
|
app: pvc
|
||||||
|
name: backend-pvc
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: nfs
|
||||||
6
k8s/storage/openstack/kustomization.yaml
Normal file
6
k8s/storage/openstack/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
bases:
|
||||||
|
- ../../environments
|
||||||
|
resources:
|
||||||
|
- pvc-egovcp.yaml
|
||||||
16
k8s/storage/openstack/pvc-egovcp.yaml
Normal file
16
k8s/storage/openstack/pvc-egovcp.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: backend-pvc
|
||||||
|
labels:
|
||||||
|
env: production
|
||||||
|
tier: backend
|
||||||
|
app: pvc
|
||||||
|
name: backend-pvc
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: cinder
|
||||||
Reference in New Issue
Block a user