Semteul Battle์ ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ ํ์ด ๋ํ๋ฅผ ์ด์ํ๊ณ ์ฐธ๊ฐํ ์ ์๋ ์น ํ๋ซํผ์ ๋๋ค.
์ฌ์ฉ์๋ ๋ํ์ ์ฐธ๊ฐํ์ฌ ๋ฌธ์ ๋ฅผ ํ๊ณ ์ฝ๋๋ฅผ ์ ์ถํ ์ ์์ผ๋ฉฐ, ์ถ์ ์์ ๊ด๋ฆฌ์๋ ๋ํ, ๋ฌธ์ , ๊ณต์ง์ฌํญ, ์ง๋ฌธ ๊ฒ์ํ ๋ฑ์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
๋ณธ ํ๋ก์ ํธ๋ ๋๋ฉ์ธ ์ค์ฌ ํจํค์ง ๊ตฌ์กฐ(Domain-Oriented Package Structure) ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
src/main/java/Winter_Project/Semteul_Battle
โโโ domain
โ โโโ user
โ โโโ contest
โ โโโ problem
โ โโโ menu
โ โโโ mail
โโโ global
๊ฐ ๋๋ฉ์ธ์ ๋ค์ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฆ ๋๋ค.
domain/{domain}
โโโ controller
โโโ service
โโโ repository
โโโ entity
โโโ dto
โ โโโ request
โ โโโ response
โโโ exception
๊ณตํต ๊ธฐ๋ฅ์ global ํจํค์ง์์ ๊ด๋ฆฌํฉ๋๋ค.
global
โโโ config
โโโ security
โโโ exception
โโโ response
โโโ status
โโโ util
- ๋๋ฉ์ธ ๊ด๋ จ ์ฝ๋๋
domain/{domain}๋ด๋ถ์ ์์ฑํฉ๋๋ค. - ์ฌ๋ฌ ๋๋ฉ์ธ์์ ์ฌ์ฉํ๋ ๊ณตํต ์ฝ๋๋
global์ ์์ฑํฉ๋๋ค. - DTO๋
request,response๋ก ๋ถ๋ฆฌํฉ๋๋ค. - Entity๋ฅผ API ์๋ต์ผ๋ก ์ง์ ๋ฐํํ์ง ์์ต๋๋ค.
- ๋๋ฉ์ธ ์์ธ๋ ๊ฐ ๋๋ฉ์ธ์
exceptionํจํค์ง์์ ๊ด๋ฆฌํฉ๋๋ค.
| ๋์ | ๊ท์น |
|---|---|
| Class | PascalCase |
| Method | camelCase |
| Variable | camelCase |
| Constant | UPPER_SNAKE_CASE |
| Package | lowercase |
private static final long REFRESH_TOKEN_TTL_SECONDS = 604800L;
public void updateProfile(String profile) {
this.profile = profile;
}| Type | Convention | Example |
|---|---|---|
| Controller | {Domain}Controller |
UserController |
| Service | {Domain}Service |
UserService |
| Service Impl | {Domain}ServiceImpl |
UserServiceImpl |
| Repository | {Entity}Repository |
UserRepository |
| Exception | {Domain}Exception |
UserException |
| Request DTO | {Action}RequestDto |
SignUpRequestDto |
| Response DTO | {Data}ResponseDto |
UserResponseDto |
- ๋จ์ผ ๊ฐ์ ์๋ฏธ๊ฐ ๋๋ฌ๋๋ ์ด๋ฆ์ ์ฌ์ฉํฉ๋๋ค.
- ์ปฌ๋ ์ ์ ๋ณต์ํ์ ์ฌ์ฉํฉ๋๋ค.
- ID๋
{domain}Idํ์์ ์ฌ์ฉํฉ๋๋ค. - Boolean ๊ฐ์
is,has,can์ ๋์ด๋ฅผ ์ฌ์ฉํฉ๋๋ค.
Long userId;
List<Contest> contests;
boolean isChecked;
boolean hasPermission;@Setter,@Data์ฌ์ฉ ๊ธ์ง- ์ํ ๋ณ๊ฒฝ์ ๋ช ์์ ์ธ ๋ฉ์๋๋ก ์ํ
- ์ฐ๊ด๊ด๊ณ๋ ๊ธฐ๋ณธ์ ์ผ๋ก
LAZY - Entity๋ฅผ API ์๋ต์ผ๋ก ์ง์ ๋ฐํํ์ง ์์
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
public void updateName(String name) {
this.name = name;
}- ์์ฒญ DTO โ
dto.request - ์๋ต DTO โ
dto.response - ์์ฒญ DTO์๋ Validation ์ ์ฉ
- ๋ถํ์ํ Setter ์ฌ์ฉ ์ง์
- ์๋ต DTO๋ ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋ ์ฌ์ฉ ๊ฐ๋ฅ
@Getter
@NoArgsConstructor
public class SignUpRequestDto {
@NotBlank
private String loginId;
@NotBlank
private String password;
}- ์์ฒญ ๊ฒ์ฆ ๋ด๋น
- ์๋ต ๋ฐํ ๋ด๋น
- ๋น์ฆ๋์ค ๋ก์ง ์์ฑ ๊ธ์ง
@Valid์ฌ์ฉBaseResponseํ์์ผ๋ก ์๋ต ํต์ผ
@PostMapping
public BaseResponse<Void> create(
@RequestBody @Valid CreateRequestDto request
) {
service.create(request);
return BaseResponse.onSuccess(null);
}- ๋น์ฆ๋์ค ๋ก์ง ๋ด๋น
Optional.get()์ฌ์ฉ ๊ธ์งorElseThrow()์ฌ์ฉ- ์ฐ๊ธฐ ์์
โ
@Transactional - ์กฐํ ์์
โ
@Transactional(readOnly = true) - ๋๋ฉ์ธ ์์ธ ์ฌ์ฉ
User user = userRepository.findById(userId)
.orElseThrow(() -> new UserException(ErrorStatus.NOT_FOUND));- ํ
์ด๋ธ๋ช
:
snake_case - ์ปฌ๋ผ๋ช
:
snake_case - PK:
id - FK:
{table_name}_id - ์คํค๋ง ๋ณ๊ฒฝ์ Flyway๋ก ๊ด๋ฆฌ
V1__init_schema.sql
V2__add_user_unique_constraints.sql
type/short-description
| Type | Description |
|---|---|
| feat | ๊ธฐ๋ฅ ์ถ๊ฐ |
| fix | ๋ฒ๊ทธ ์์ |
| refactor | ๋ฆฌํฉํ ๋ง |
| docs | ๋ฌธ์ ์์ |
| chore | ์ค์ ๋ฐ ๊ธฐํ ์์ |
| test | ํ ์คํธ ์ฝ๋ |
| ci | CI/CD ์ค์ |
feat/auth-sign-up
fix/token-refresh
refactor/entity-dto-cleanup
docs/readme-convention
type: ์์
๋ด์ฉ ์์ฝ
feat: ํ์๊ฐ์
์ด๋ฉ์ผ ์ธ์ฆ ์ถ๊ฐ
fix: refresh token ๊ฒ์ฆ ๋ก์ง ์์
refactor: DTO setter ์ ๊ฑฐ
docs: README ์ปจ๋ฒค์
์ถ๊ฐ
PR ์ ๋ชฉ์ Commit Message ํ์์ ๋ฐ๋ฆ ๋๋ค.
type: ์์
๋ด์ฉ ์์ฝ
PR ๋ณธ๋ฌธ์ ํ๋ก์ ํธ PR ํ ํ๋ฆฟ์ ์ฌ์ฉํฉ๋๋ค.
๋ชจ๋ API ์๋ต์ BaseResponse ํ์์ ์ฌ์ฉํฉ๋๋ค.
{
"isSuccess": true,
"code": "COMMON200",
"message": "์ฑ๊ณต์
๋๋ค.",
"result": {}
}