{"id":18679876,"url":"https://github.com/sh1nj1/springboot-template","last_synced_at":"2025-04-12T03:14:30.761Z","repository":{"id":166302602,"uuid":"641782700","full_name":"sh1nj1/springboot-template","owner":"sh1nj1","description":"Springboot Project Base Template with lombok, mapstruct, jwt, spock, mysql","archived":false,"fork":false,"pushed_at":"2024-06-30T15:13:42.000Z","size":112,"stargazers_count":5,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-12T03:14:23.060Z","etag":null,"topics":["gradle","jacoco","mysql","spock","spring-boot","spring-security","springboot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sh1nj1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-17T06:50:59.000Z","updated_at":"2024-11-20T05:48:57.000Z","dependencies_parsed_at":"2023-06-09T01:45:39.754Z","dependency_job_id":"b1ccfdee-a186-40f2-9583-fd754a22bde7","html_url":"https://github.com/sh1nj1/springboot-template","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sh1nj1%2Fspringboot-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sh1nj1%2Fspringboot-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sh1nj1%2Fspringboot-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sh1nj1%2Fspringboot-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sh1nj1","download_url":"https://codeload.github.com/sh1nj1/springboot-template/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248510001,"owners_count":21116130,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle","jacoco","mysql","spock","spring-boot","spring-security","springboot"],"created_at":"2024-11-07T09:46:08.015Z","updated_at":"2025-04-12T03:14:30.742Z","avatar_url":"https://github.com/sh1nj1.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SpringBoot Server 프로젝트 개발 가이드\n\nSpringboot 를 사용하여 서버를 개발하기 공통 모듈과 개발 가이드를 제공한다.\n본 프로젝트 템플릿은 중/소 규모 백엔드 API 서버 개발에 최적화 되어 있다.\n\n## 개발 환경 설정\n\n패키지명을 변경하여 사용하여야 한다. 다음에서 \"com.vrerv.springboottemplate.server\" =\u003e \"com.mycompany.myproject\" 로 변경한다.\n\n* build.gradle\n* src/main/java\n* src/test/groovy\n* src/test/java\n\n\n### 개발 환경 설명\n\n#### OS\n\n최신 리눅스나 Mac OS X 에서 개발할 것을 추천한다. Windows OS 의 경우 10 이상 버전을 사용하고 WSL2 환경에서 개발하는 것을 추천한다.\n본 문서에서는 해당 환경에서 작동하는 것을 가정한다. 만약 Windows OS 에서 WSL 을 사용하지 않을 경우 일부 기능이 작동되지 않을 수 있다.\n\n* [Windows 에서 WSL2 설치](https://learn.microsoft.com/ko-kr/windows/wsl/install)\n\n#### 필요한 소프트웨어\n\n* Sdkman - Java 개발을 위한 소프트웨어를 설치하고 관리한다.\n* Java 17 - 코드를 빌드하고 구동한다.\n* Git - 소스 코드를 관리한다.\n* Docker - 배포용 이미지를 생성하고 로컬에 설치하면 구동한다.\n* IntelliJ - 코드를 개발한다. 개발자의 역량에 따라 다른 개발툴을 사용하여도 무난하다.\n* MySQL DB - 8.0.32 이상을 로컬에 설치하여, 로컬 개발시 사용한다.\n\n### Java 설치\n\n* java 17 설치 - [sdkman](https://sdkman.io/) 으로 설치한다.\n* `~/.sdkman` 디렉토리를 `/opt/sdkman` 으로 링크한다. (Windows 의 경우 WSL 사용)\n  만약 디렉토리를 링크하거나 바꿀수 없거나 다른 곳으로 설정한다면, `gradle.properties` 안에 jdk 경로를 수동으로 설정해주어야 한다.\n  해당 파일은 git 에 관리되는 파일로 되어 있으므로 되도록 기존 디렉토리 구조를 따르도록 한다.\n\n```bash\nsdk install java 17.0.5-amzn\n```\n\n### DB\n\n#### MSSQL \n\nMSSQL - docker 사용\n\n* `docker run -e \"ACCEPT_EULA=Y\" -e \"MSSQL_SA_PASSWORD=P@ssw0rd\" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2022-latest`\n\nMac book M1 docker\n\n* `docker run --cap-add SYS_PTRACE -e \"ACCEPT_EULA=Y\" -e \"MSSQL_SA_PASSWORD=P@ssw0rd\" -p 1433:1433 --name sqledge -d mcr.microsoft.com/azure-sql-edge`\n\n```sql\ncreate database test_db;\nuse test_db;\n\ncreate login test_user with password = 'P@ssw0rd';\ncreate user test_user for login test_user;\ngrant select, insert, update, delete, alter, references on DATABASE::test_db to test_user;\n```\n\n#### MySQL 준비\n\n* MySQL 을 local 에 설치한다. \n* 로컬 구동을 위한 데이터베이스와 계정을 생성한다.\n```sql\nCREATE DATABASE test_db;\nCREATE USER 'test_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'P@ssw0rd';\nGRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, REFERENCES, CREATE TEMPORARY TABLES, LOCK TABLES ON test_db.* TO 'test_user'@'localhost';\nGRANT FILE ON *.* TO 'test_user'@'localhost';\nFLUSH PRIVILEGES;\n```\n\n### IntelliJ 에서 개발\n\n* 프로젝트 폴더의 root (server directory) 를 IntelliJ 에서 오픈한다.\n* 기본 JDK 설정이 17이 아니라면 프로젝트 JDK 를 설치된 Java 17 으로 설정한다.\n* 설정에서 gradle 검색후 gradle 구동 JDK 를 \"Project SDK\" 로 설정한다.\n\n### 명령행에서 개발\n\n빌드: \n`./gradlew clean buid`\n\n구동: \n`./gradlew bootRun`\n\n## 개발 상세\n\n### 개발 프로젝트 구조\n\n* src/main/java - Java 소스 코드\n* src/main/resources - Java 프로젝트 설정 파일\n* src/test/java - Java 테스트 코드\n* src/test/resources - Java 테스트 코드 설정 파일\n* src/test/http - IntelliJ http client 테스트 파일\n* src/test/grovvy - Groovy Spock 테스트 코드\n\n#### 패키지 구조\n\n* {basePackagePrefix}.{module}.{layer} - 기본 패키지 구조\n* {module} - common(공통), 그외 관련 모듈이름\n* {layer}\n    * domain - 도메인 모델 관련 레이어\n    * application - 서비스, 비즈니스 로직 레이어\n    * presentation - 웹 API, UI 레이어\n\n각 레이어는 정확히 DDD(Domain Driven Develop)의 레이어와는 일치하지 않는다.\nSpringFramework, hibernate, String data JPA 등에 강하게 연결되어 있기 때문이다.\n다만, 각 레이어간에 정형화를 통해 개발과정을 단순화하고 일관성을 유지하기 위해 레이어를 정의하였다.\n\n도메인 레이어 \u003c- 애플리케이션 레이어 \u003c- 프레젠테이션 레이어 순으로 의존성이 존재한다.\n모듈 간의 호출에서는 presentation 레이어의 Endpoint 로 호출한다.\n\n##### 도메인 레이어\n\n* entity 와 repository 를 주로 다룬다, DB 설계와 도메인 모델의 기본 룰을 설정한다.\n\n##### 애플리케이션 레이어\n\n* 비지니스 로직을 수행한다.\n\n##### 프레젠테이션 레이어\n\n* 웹 API, UI 레이어\n* Spring controller 등 \n\n#### 클래스 명명\n\n특정 타입에 대한 클래스명 접미사\n\n* `Repo` - spring data repository\n* `Service` - 비지니스 로직 수행\n* `Endpoint` - 웹 API endpoint\n* `Model` - DTO or VO\n* `Mapper` - MapStruct mapper or Java Bean converter\n* `Config` - Spring configuration or any 인프라 설정\n\n### Web API 개발 방법\n\n#### Authentication\n\n* JWT 토큰 인증을 사용한다.\n\n#### Web API 문서화\n\n* SpringDoc 이 적용되어 서버의 [Swagger UI](http://localhost:8080/swagger-ui.html) 로 서버에 존재하는 API 확인할 수 있다.\n* API 의 명세는 `build` 시 `openapi.json` 으로 자동 생성된다.\n\n#### API client project 생성\n\n[openapi-generator](https://github.com/OpenAPITools/openapi-generator-cli) 를 사용하여 API client project 를 생성할 수 있다.\nCLI 는 여러가지를 지원함으로 필요한 CLI 를 설치해서 사용한다. 아래는 docker 를 사용한 예이다.\n\n아래 docker 명령으로 API client project 를 생성할 수 있다.(server directory 에서 실행)\n`-i /local/app/openapi.json` 대신에 `http://localhost:8080/v3/api-docs` \n(docker 로 실행시에는 ip가 컨테이너 내부에서 host 를 바라보도록 해야 함) 를 사용할 수도 있다.\n\n```bash\nexport PACKAGE_BASE_NAME=com.vrerv.springboottemplate.server\ndocker run --rm -v \"${PWD}:/local\" openapitools/openapi-generator-cli generate \\\n    -i /local/app/openapi.json \\\n    -g java --library retrofit2 \\\n    --group-id ${PACKAGE_BASE_NAME} \\\n    --artifact-id api-client-java \\\n    --package-name ${PACKAGE_BASE_NAME}.client \\\n    --api-package ${PACKAGE_BASE_NAME}.client.api \\\n    --model-package ${PACKAGE_BASE_NAME}.client.api.model \\\n    --invoker-package ${PACKAGE_BASE_NAME}.client \\\n    -o /local/api-client-java\n```\n\njavascript api client library 생성은 아래와 같이 하면 된다.\n\n```bash\nexport PACKAGE_BASE_NAME=vrerv.springboottemplate\ndocker run --rm -v \"${PWD}:/local\" openapitools/openapi-generator-cli generate \\\n    -i /local/app/openapi.json \\\n    -g javascript \\\n    --group-id ${PACKAGE_BASE_NAME} \\\n    --artifact-id api-client-java \\\n    --package-name ${PACKAGE_BASE_NAME}.client \\\n    --api-package ${PACKAGE_BASE_NAME}.client \\\n    --model-package ${PACKAGE_BASE_NAME}.client \\\n    --invoker-package ${PACKAGE_BASE_NAME}.client \\\n    -o /local/api-client-javascript\n```\n\n### DB 레이어 개발\n\n* 모든 `Entity` 는 `Long id` 필드를 갖는 `EntityId` 클래스를 상속하여 작성한다.\n* `Setter` 는 업데이트가 가능한 필드만 `public` 으로 선언한다.\n\n#### MapStruct 를 통한 VO, DTO, Entity 변환\n\n* `MapStruct` 를 사용하여 `DTO`, `Entity` 또는 `VO` 간에 서로 변환한다.\n\n### Test 코드 작성\n\n#### IntelliJ Http Client\n\n[IntelliJ http client](https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html) 를 사용하여 수동 테스트를 처리할 수 있다.\n다른 api 테스트 툴을 사용한다면, `openapi.json` 을 해당 툴에 임포트 하여 쉽게 생성할 수 있을 것이다.\n\nAPI 추가/수정/삭제시 해당 .http 파일을 업데이트한다. 본 테스트는 개발자에 의한 수동 테스트를 위한 것으로 개발중에 \n개발자가 필요에 따라 추가하여, API 호출을 테스트할 수 있다.\n\n#### Spock Test\n\n* [Spock](https://spockframework.org/spock/docs/2.3/index.html) 을 사용하여 테스트 코드를 작성한다.\n\n## Tech Stack\n\n* Java 17 - [Amazon Corretto 17](https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/downloads-list.html)\n* Gradle 7.6.1\n    * [SpringDoc OpenApi Plugin](https://github.com/springdoc/springdoc-openapi-gradle-plugin)\n\n* Springboot 2.7.10\n    * Spring-web\n    * Spring-security\n    * Spring-doc\n    * Spring-data\n* Lombok\n* MapStruct - bean mapper [Reference](https://mapstruct.org/documentation/stable/reference/html/)\n* JWT token authentication\n* Testing\n    * JUnit5\n    * Spock\n\n* MySQL DB 8.0.32\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsh1nj1%2Fspringboot-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsh1nj1%2Fspringboot-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsh1nj1%2Fspringboot-template/lists"}