Code Convention - prgrms-web-devcourse-final-project/WEB4_5_ServerSOS_BE GitHub Wiki

β˜‘οΈ μ½”λ“œ μ»¨λ²€μ…˜

주석은 μ„€λͺ…ν•˜λ €λŠ” ꡬ문에 맞좰 λ“€μ—¬μ“°κΈ° ν•©λ‹ˆλ‹€.

// Good
function someFunction() {
  ...

  // statement에 κ΄€ν•œ 주석
  statements
}

β˜‘οΈ μ½”λ“œ μ»¨λ²€μ…˜μ΄ ν•„μš”ν•œ 이유

  • νŒ€μ›λΌλ¦¬ μ½”λ“œλ₯Ό κ³΅μœ ν•˜κΈ° λ•Œλ¬Έμ— μΌκ΄€μ„±μžˆλŠ” μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄ μ„œλ‘œ μ΄ν•΄ν•˜κΈ° 쉽닀.
  • λ‚˜μ€‘μ— μž…μ‚¬ 지원 μ‹œ ν”„λ‘œμ νŠΈλ₯Ό ν•˜λ©° μ½”λ“œ μ»¨λ²€μ…˜μ„ λ§Œλ“€μ–΄ μ§„ν–‰ν–ˆλ‹€κ³  ν•˜λ©΄ ν˜‘μ—… λ©΄μ—μ„œ μœ λ¦¬ν•˜κ²Œ μž‘μš©ν•  수 μžˆλ‹€.

μ°Έκ³ 

μ½”λ”©μ»¨λ²€μ…˜

πŸ“Œ Spring boot Java Coding Standards

✨ 1. κΈ°λ³Έ 원칙

  • 가독성 μ΅œμš°μ„ 
  • νŠΉλ³„ν•œ μ΄μœ κ°€ μ—†λŠ” 경우 IntelliJ IDEA μžλ™ μ„œμ‹ μ€€μˆ˜
  • νŠΉλ³„ν•œ μ΄μœ κ°€ μ—†λŠ” 경우 IntelliJ IDEA κ²½κ³  제거

🏷 2. 넀이밍 κ·œμΉ™

πŸ”Ή 클래슀 (PascalCase)

  • 클래슀λͺ…은 파슀칼 μΌ€μ΄μŠ€(PascalCase) μ‚¬μš©
// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ
public class UserAccount { }
public class OrderService { }

πŸ”Ή λ³€μˆ˜ 및 λ©”μ„œλ“œ (camelCase)

  • λ³€μˆ˜ 및 λ©”μ„œλ“œλŠ” 카멜 μΌ€μ΄μŠ€(camelCase) μ‚¬μš©
  • @Valueλ₯Ό μ‚¬μš©ν•œ ν”„λ‘œνΌν‹° 값도 카멜 μΌ€μ΄μŠ€ 적용
// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ
private String userName;
public void processOrder() { }

πŸ”Ή μΆ•μ•½μ–΄ (camelCase)

  • 좕약어도 카멜 μΌ€μ΄μŠ€ 적용
// ❌ 잘λͺ»λœ μ˜ˆμ‹œ
String HTTP;
String DTO;

// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ
String Http;
String Dto;

πŸ”Ή μƒμˆ˜ (UPPER_SNAKE_CASE)

  • μƒμˆ˜λŠ” λŒ€λ¬Έμž μŠ€λ„€μ΄ν¬ μΌ€μ΄μŠ€(UPPER_SNAKE_CASE) μ‚¬μš©
// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ
public static final int MAX_USER_COUNT = 100;
public static final String API_KEY = "1234";

πŸ”Ή νŒ¨ν‚€μ§€λͺ… (μ†Œλ¬Έμž)

  • νŒ¨ν‚€μ§€λͺ…은 μ „λΆ€ μ†Œλ¬Έμž μ‚¬μš©
// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ
com.example.service;
org.myproject.utils;

πŸ”Ή μ€„μž„λ§ μ‚¬μš© κΈˆμ§€

  • λ…Όμ˜λœ 경우λ₯Ό μ œμ™Έν•˜κ³  μ€„μž„λ§ μ‚¬μš© κΈˆμ§€
// ❌ 잘λͺ»λœ μ˜ˆμ‹œ
String msg;
String err;

// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ
String message;
String error;

πŸ”Ή CRUD method λͺ…λͺ… κ·œμΉ™

κΈ°λŠ₯ Controller λ©”μ„œλ“œλͺ… Service λ©”μ„œλ“œλͺ… Repository λ©”μ„œλ“œλͺ…
Create (POST) createUser(UserForm userForm) createUser(UserForm userForm) save(User user) (JPA κΈ°λ³Έ)
Read (단일 쑰회) (GET) getUserById(Long id) getUserById(Long id) findById(Long id) (JPA κΈ°λ³Έ)
Read (λͺ©λ‘ 쑰회) (GET) getUserList() getUserList() findAll() (JPA κΈ°λ³Έ)
Update (PUT) updateUser(Long id, UserForm userForm) updateUser(Long id, UserForm userForm) save(User user) (JPA κΈ°λ³Έ, ID 쑴재 μ‹œ μ—…λ°μ΄νŠΈ)
Delete (DELETE) deleteUserById(Long id) deleteUserById(Long id) deleteById(Long id) (JPA κΈ°λ³Έ)

βœ… 일관성 μœ μ§€:

  • Controller & Service β†’ get, create, update, delete
  • Repository β†’ find, save, deleteById
  • DTO (UserDto) β†’ μ‘λ‹΅μš©, Form (UserForm) β†’ μž…λ ₯용

πŸ”Ή HTTP URL λͺ…λͺ… κ·œμΉ™

  • prefix 둜 api λ₯Ό κ°–μŒ (ν”„λ‘œμ νŠΈ λ ˆλ²¨μ—μ„œ μ„€μ • μ™„λ£Œ, controller μ—μ„œ μ„€μ •ν•  ν•„μš” μ—†μŒ)
  • λ™μ‚¬λŠ” μ‚¬μš©ν•˜μ§€ μ•Šκ³  http method λ₯Ό ν™œμš©
// ❌ 잘λͺ»λœ μ˜ˆμ‹œ
/api/v1/order/create
/api/v1/order/delete

// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ
(post) /api/v1/order
(delete) /api/v1/order

  • λ¦¬μ†ŒμŠ€λŠ” 항상 λ³΅μˆ˜ν˜• μ‚¬μš©
// ❌ 잘λͺ»λœ μ˜ˆμ‹œ (λ‹¨μˆ˜ν˜• λ¦¬μ†ŒμŠ€)
GET /api/v1/user
POST /api/v1/order

// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ (λ³΅μˆ˜ν˜• λ¦¬μ†ŒμŠ€)
GET /api/v1/users
POST /api/v1/orders

  • λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 λ“€μ–΄κ°„ **ν–‰μœ„(Action)은 동사 포함 (approve, ban, login λ“±)
// βœ… μ•‘μ…˜μ΄ ν•„μš”ν•œ 경우
POST /api/v1/auth/login
POST /api/v1/auth/logout
POST /api/v1/orders/123/approve  // 주문 승인
POST /api/v1/users/456/ban  // μœ μ € 차단

🎨 3. μ½”λ“œ μŠ€νƒ€μΌ

πŸ”Ή μ€‘κ΄„ν˜Έ {} μ‚¬μš©

  • 단일 라인 쑰건문에도 λ°˜λ“œμ‹œ μ€‘κ΄„ν˜Έ {} μ‚¬μš©
// ❌ 잘λͺ»λœ μ˜ˆμ‹œ
if (a == 0) return a;

// βœ… μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ
if (a == 0) {
    return a;
}

πŸ”ΉDTO

  1. 도메인 DTO 말고 Entityλ₯Ό 곡유

    @GetMapping("/{id}")
    public RsData<ExampleDetailResponse> get(@PathVariable("id") Long id) {
    	ExampleDetailResponse response = exampleService.getDetail(id);
    	return RsData.from(SUCCESS, response);
    }
    
    @Transactional(readOnly = true)
    public ExampleDetailResponse getDetail(Long id) {
    	Example example = getEntity(id);
    	return ExampleDetailResponse.from(example);
    }
    
    private Example getEntity(Long id) {
    	return exampleRepository.findById(id).orElseThrow(() -> new BusinessException(NOT_FOUND));
    }
    
    • PostDto, PostWithPerformanceDto 같은 엔티티와 λŒ€μ‘λ˜λŠ” Dtoλ₯Ό λ³„λ„λ‘œ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€.
    • 컨트둀러 λ©”μ„œλ“œμ™€ λ§€ν•‘λ˜λŠ” μ„œλΉ„μŠ€ λ©”μ„œλ“œ μž‘μ„± (μ„œλΉ„μŠ€μ—μ„œ 응닡 DTO둜 미리 λ³€ν™˜ν•˜κ³  μ»¨νŠΈλ‘€λŸ¬μ— λ°˜ν™˜)
    • μΆ”κ°€λ‘œ ν•„μš”ν•œ μ„œλΉ„μŠ€ λ©”μ„œλ“œ μž‘μ„±(λ©”μ„œλ“œλΌλ¦¬ 데이터 κ³΅μœ κ°€ ν•„μš”ν•˜λ©΄ Entity 적극 μ‚¬μš©)
  2. Controllerμ—μ„œ λ°˜ν™˜ν•  DTO

    • ~~SimpleResponse ← 리슀트 데이터(λͺ©λ‘ νŽ˜μ΄μ§€)
    • ~~DetailResponse ← 상세 데이터(상세 νŽ˜μ΄μ§€)
    • PostSimpleResponse
    • PostDetailResponse

πŸ”ΉApiPathκ΄€λ ¨

  • ν•˜λ‚˜μΌλ•ŒλŠ” {id}
  • ν•˜λ‚˜μ΄μƒμΌλ•ŒλŠ” {postId}와 같이 μ‚¬μš©

곡톡객체

  • RsData ν˜•μ‹

    • 성곡: μƒνƒœ, λ©”μ‹œμ§€, 데이터

      성곡(νŽ˜μ΄μ§•)

      {
      	"code": 200,
      	"message": "μš”μ²­μ΄ μ„±κ³΅ν–ˆμŠ΅λ‹ˆλ‹€.",
      	"data": {
      		"items": [
      			{
      				"id" : 1,
      				"title" : "κ²Œμ‹œκΈ€ 제λͺ©",
      				"venue" : "곡연 μž₯μ†Œ",
      				"startDate" : "2025-04-29T14:30:45",
      				"endDate" : "2025-04-30T14:30:45",
      				"poster" : "ν¬μŠ€ν„° url"
      			},
      			{
      				"id" : 2,
      				"title" : "κ²Œμ‹œκΈ€ 제λͺ©",
      				"venue" : "곡연 μž₯μ†Œ",
      				"startDate" : "2025-04-29T14:30:45",
      				"endDate" : "2025-04-30T14:30:45",
      				"poster" : "ν¬μŠ€ν„° url"
      			}
      		],
      		"page": 1,
      		"size": 10,
      		"totalPages": 1,
      		"totalElements": 2
      	}
      }
      

      성곡(상세)

      {
      	"code": 200,
      	"message": "μš”μ²­μ΄ μ„±κ³΅ν–ˆμŠ΅λ‹ˆλ‹€.",
      	"data": {
      		"items": [
      			{
      				"postId" : 1,
      				"title" : "κ²Œμ‹œκΈ€ 제λͺ©",
      				"venue" : "곡연 μž₯μ†Œ",
      				"startDate" : "2025-04-29T14:30:45",
      				"endDate" : "2025-04-30T14:30:45",
      				"poster" : "ν¬μŠ€ν„° url"
      			},
      			{
      				"postId" : 2,
      				"title" : "κ²Œμ‹œκΈ€ 제λͺ©",
      				"venue" : "곡연 μž₯μ†Œ",
      				"startDate" : "2025-04-29T14:30:45",
      				"endDate" : "2025-04-30T14:30:45",
      				"poster" : "ν¬μŠ€ν„° url"
      			}
      		],
      		"page": 1,
      		"size": 10,
      		"totalPages": 1,
      		"totalElements": 2
      	}
      }
      
    • μ—λŸ¬ response: μƒνƒœ, μ½”λ“œ, λ©”μ‹œμ§€

      μ‹€νŒ¨

      {
      	"code" : 404,
      	"message" : "λ¦¬μ†ŒμŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.",
      	"data" : null
      }
      
  • PageDto

    • items
    • page
    • totalElements
    • totalPages
    • size