Dev Conventions Code

πŸ“ μ½”λ“œ μ»¨λ²€μ…˜

κ·œμΉ™ ID λ²”μœ„: CODE-* μ°Έκ³ : 이 μ„Ήμ…˜μ€ Team Codex의 μ½”λ“œ μ»¨λ²€μ…˜μ„ 기반으둜 μž‘μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. κ΄€λ ¨ λ¬Έμ„œ: Development-Philosophy, Dev-Architecture-NextJS

πŸ“‹ λͺ©μ°¨

  1. 곡톡 κ·œμΉ™
  2. React ν”„λ‘œμ νŠΈ κ·œμΉ™
  3. Java (Spring Boot) ν”„λ‘œμ νŠΈ κ·œμΉ™

πŸ“ 곡톡 κ·œμΉ™

넀이밍 μ»¨λ²€μ…˜

κ·œμΉ™ ID ν•­λͺ© κ·œμΉ™ μ˜ˆμ‹œ
CODE-NM-001 λ³€μˆ˜/ν•¨μˆ˜ camelCase getUserData(), isActive
CODE-NM-002 클래슀/μ»΄ν¬λ„ŒνŠΈ PascalCase UserProfile, LoginButton
CODE-NM-003 μƒμˆ˜ UPPER_SNAKE_CASE MAX_COUNT, API_URL
CODE-NM-004 파일λͺ… (μ»΄ν¬λ„ŒνŠΈ) PascalCase UserProfile.tsx
CODE-NM-005 파일λͺ… (μœ ν‹Έ) camelCase formatDate.ts
CODE-NM-006 CSS 클래슀 kebab-case user-profile, login-button
CODE-NM-007 쿼리 νŒŒλΌλ―Έν„° kebab-case ?user-id=123, ?sort-by=name

μ½”λ“œ ν’ˆμ§ˆ κ·œμΉ™

κ·œμΉ™ ID λΆ„λ₯˜ ν•­λͺ© μš”κ΅¬μ‚¬ν•­
CODE-QL-001 ν•„μˆ˜ ESLint/Prettier μ„€μ • μ€€μˆ˜ ν•„μˆ˜
CODE-QL-002 ν•„μˆ˜ console.log λ””λ²„κΉ…μš© μ½”λ“œ 제거
CODE-QL-003 ν•„μˆ˜ 주석 처리된 μ½”λ“œ λΆˆν•„μš”ν•œ μ½”λ“œ μ‚­μ œ
CODE-QL-004 ν•„μˆ˜ import 정리 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” import 제거
CODE-QL-005 ν•„μˆ˜ TODO 주석 μ΅œμ†Œν™”, ν•„μš” μ‹œ 이슈 생성
CODE-QL-100 ꢌμž₯ 단일 μ±…μž„ 원칙 ν•¨μˆ˜λŠ” ν•œ κ°€μ§€ 일만 μˆ˜ν–‰
CODE-QL-101 ꢌμž₯ μƒμˆ˜ μ‚¬μš© 맀직 λ„˜λ²„ λŒ€μ‹  μƒμˆ˜ ν™œμš©
CODE-QL-102 ꢌμž₯ 의미 μžˆλŠ” 넀이밍 λ³€μˆ˜/ν•¨μˆ˜λͺ… λͺ…ν™•ν•˜κ²Œ μž‘μ„±
CODE-QL-103 ꢌμž₯ 주석 μž‘μ„± 원칙 "μ™œ"λ₯Ό μ„€λͺ… (μ½”λ“œλŠ” "무엇"을 μ„€λͺ…)

βš›οΈ React ν”„λ‘œμ νŠΈ κ·œμΉ™

ν•„μˆ˜ κ·œμΉ™

κ·œμΉ™ ID λΆ„λ₯˜ ν•­λͺ© μš”κ΅¬μ‚¬ν•­
CODE-REACT-001 ꡬ쑰 파일 ꡬ쑰 μˆœμ„œ 1. Import β†’ 2. νƒ€μž… μ •μ˜ β†’ 3. μ»΄ν¬λ„ŒνŠΈ β†’ 4. μŠ€νƒ€μΌλ“œ μ»΄ν¬λ„ŒνŠΈ(μ΅œν•˜λ‹¨)
CODE-REACT-100 ν•„μˆ˜ μ»΄ν¬λ„ŒνŠΈ μŠ€νƒ€μΌ ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈ + Hooks μ‚¬μš©
CODE-REACT-101 ν•„μˆ˜ Props νƒ€μž… μ •μ˜ TypeScript μ‚¬μš© ν•„μˆ˜
CODE-REACT-102 ν•„μˆ˜ μŠ€νƒ€μΌλ“œ μ»΄ν¬λ„ŒνŠΈ μœ„μΉ˜ 파일 μ΅œν•˜λ‹¨μ— μ •μ˜
CODE-REACT-103 ν•„μˆ˜ useEffect μ˜μ‘΄μ„± μ˜μ‘΄μ„± λ°°μ—΄ λͺ…ν™•νžˆ 관리
CODE-REACT-200 κΈˆμ§€ ν΄λž˜μŠ€ν˜• μ»΄ν¬λ„ŒνŠΈ μ‚¬μš© κΈˆμ§€
CODE-REACT-201 κΈˆμ§€ any νƒ€μž… λ‚¨λ°œ κΈˆμ§€
CODE-REACT-202 κΈˆμ§€ inline μŠ€νƒ€μΌ κ³Όλ‹€ μ‚¬μš© κΈˆμ§€
CODE-REACT-203 κΈˆμ§€ μ»΄ν¬λ„ŒνŠΈ λ‚΄λΆ€ μ •μ˜ μ»΄ν¬λ„ŒνŠΈ 내뢀에 λ‹€λ₯Έ μ»΄ν¬λ„ŒνŠΈ μ •μ˜ κΈˆμ§€
CODE-REACT-204 ν•„μˆ˜ μ»΄ν¬λ„ŒνŠΈ 디렉토리 ꡬ쑰 Atomic Design νŒ¨ν„΄ - 각 μ»΄ν¬λ„ŒνŠΈλŠ” 독립 디렉토리 ꡬ쑰
CODE-REACT-205 ν•„μˆ˜ Next.js Path Alias @molecules/... ν˜•μ‹ μ‚¬μš© (μŠ¬λž˜μ‹œ ν•˜λ‚˜), @/molecules/... κΈˆμ§€

CODE-REACT-001: 파일 ꡬ쑰 μ˜ˆμ‹œ

// 1. Import μ„Ήμ…˜
import React from 'react';
import { useState } from 'react';
import styled from 'styled-components';

// 2. νƒ€μž… μ •μ˜
interface UserProfileProps {
  userId: string;
  onUpdate?: () => void;
}

// 3. μ»΄ν¬λ„ŒνŠΈ μ •μ˜
export const UserProfile: React.FC<UserProfileProps> = ({ userId, onUpdate }) => {
  const [data, setData] = useState(null);
  return <Container>{/* JSX */}</Container>;
};

// 4. μŠ€νƒ€μΌλ“œ μ»΄ν¬λ„ŒνŠΈ (μ΅œν•˜λ‹¨)
const Container = styled.div`
  padding: 20px;
`;

CODE-REACT-204: μ»΄ν¬λ„ŒνŠΈ 디렉토리 ꡬ쑰

Atomic Design νŒ¨ν„΄μ„ λ”°λ₯΄λŠ” ν”„λ‘œμ νŠΈμ—μ„œλŠ” 각 μ»΄ν¬λ„ŒνŠΈλ₯Ό 독립 λ””λ ‰ν† λ¦¬λ‘œ κ΅¬μ„±ν•˜μ—¬ μœ μ§€λ³΄μˆ˜μ„±κ³Ό ν™•μž₯성을 λ†’μž…λ‹ˆλ‹€.

βœ… μ˜¬λ°”λ₯Έ ꡬ쑰 (ꢌμž₯)

src/components/
β”œβ”€β”€ atoms/
β”‚   β”œβ”€β”€ Button/
β”‚   β”‚   β”œβ”€β”€ index.tsx        # μ»΄ν¬λ„ŒνŠΈ 메인 파일
β”‚   β”‚   └── Button.test.tsx  # ν…ŒμŠ€νŠΈ 파일
β”‚   β”œβ”€β”€ Input/
β”‚   β”‚   β”œβ”€β”€ index.tsx
β”‚   β”‚   └── Input.test.tsx
β”‚   └── Icon/
β”‚       └── index.tsx
β”œβ”€β”€ molecules/
β”‚   β”œβ”€β”€ SearchBar/
β”‚   β”‚   β”œβ”€β”€ index.tsx
β”‚   β”‚   └── SearchBar.test.tsx
β”‚   β”œβ”€β”€ UserAvatar/
β”‚   β”‚   β”œβ”€β”€ index.tsx
β”‚   β”‚   └── UserAvatar.test.tsx
β”‚   └── Pagination/
β”‚       β”œβ”€β”€ index.tsx
β”‚       └── Pagination.test.tsx
└── organisms/
    β”œβ”€β”€ Header/
    β”‚   β”œβ”€β”€ index.tsx
    β”‚   └── Header.test.tsx
    └── Footer/
        β”œβ”€β”€ index.tsx
        └── Footer.test.tsx

❌ 잘λͺ»λœ ꡬ쑰 (μ§€μ–‘)

src/components/
β”œβ”€β”€ atoms/
β”‚   β”œβ”€β”€ Button.tsx           # ❌ 파일 λ‹¨μœ„λ‘œ 뢄리
β”‚   β”œβ”€β”€ Button.test.tsx
β”‚   β”œβ”€β”€ Input.tsx
β”‚   └── Input.test.tsx
β”œβ”€β”€ molecules/
β”‚   β”œβ”€β”€ SearchBar.tsx        # ❌ ν…ŒμŠ€νŠΈ 파일과 λΆ„λ¦¬λ˜μ–΄ 관리 어렀움
β”‚   β”œβ”€β”€ SearchBar.test.tsx
β”‚   └── UserAvatar.tsx

ꡬ쑰 κ·œμΉ™

  1. μ»΄ν¬λ„ŒνŠΈλͺ… 디렉토리: 각 μ»΄ν¬λ„ŒνŠΈλŠ” PascalCase λ””λ ‰ν† λ¦¬λ‘œ 생성
  2. index.tsx: μ»΄ν¬λ„ŒνŠΈ 메인 둜직 (μžλ™μœΌλ‘œ default import)
  3. ComponentName.test.tsx: ν…ŒμŠ€νŠΈ μ½”λ“œ
  4. import 경둜: μ ˆλŒ€ 경둜 μœ μ§€ (@atoms/Button, @molecules/SearchBar)

Import μ˜ˆμ‹œ

// βœ… μ˜¬λ°”λ₯Έ import - 디렉토리 κ΅¬μ‘°μ—μ„œ μžλ™μœΌλ‘œ index.tsx μ°Έμ‘°
import { Button } from '@atoms/Button';
import { SearchBar } from '@molecules/SearchBar';

// ❌ 잘λͺ»λœ import - @/ ν˜•μ‹ κΈˆμ§€
import { Button } from '@/atoms/Button';
import { SearchBar } from '@/molecules/SearchBar';

// ❌ 잘λͺ»λœ import - index.tsx λͺ…μ‹œ λΆˆν•„μš”
import { Button } from '@atoms/Button/index';

μž₯점

  • πŸ“ μ»΄ν¬λ„ŒνŠΈ κ΄€λ ¨ 파일이 ν•œ 곳에 λͺ¨μ—¬ μžˆμ–΄ μœ μ§€λ³΄μˆ˜ 용이
  • πŸ§ͺ ν…ŒμŠ€νŠΈ 파일 μœ„μΉ˜κ°€ λͺ…ν™•ν•˜μ—¬ ν…ŒμŠ€νŠΈ μž‘μ„±/μ‹€ν–‰ κ°„νŽΈ
  • πŸ” ν”„λ‘œμ νŠΈ 탐색 μ‹œ μ»΄ν¬λ„ŒνŠΈ ꡬ쑰 νŒŒμ•… 쉬움
  • πŸš€ ν™•μž₯ μ‹œ κ΄€λ ¨ 파일(μŠ€ν† λ¦¬λΆ, μŠ€νƒ€μΌ λ“±) μΆ”κ°€ 용이

β˜• Java (Spring Boot) ν”„λ‘œμ νŠΈ κ·œμΉ™

넀이밍 μ»¨λ²€μ…˜

κ·œμΉ™ ID ν•­λͺ© κ·œμΉ™ μ˜ˆμ‹œ
CODE-JAVA-001 클래슀λͺ… PascalCase, λͺ…사 UserService, OrderController, ProductRepository
CODE-JAVA-002 λ©”μ„œλ“œ/λ³€μˆ˜λͺ… camelCase, λ©”μ„œλ“œλŠ” 동사 μ‹œμž‘ getUserById(), userName, isActive
CODE-JAVA-003 μƒμˆ˜ UPPER_SNAKE_CASE, static final MAX_RETRY_COUNT, DEFAULT_PAGE_SIZE
CODE-JAVA-004 νŒ¨ν‚€μ§€λͺ… μ†Œλ¬Έμž, 역도메인 ν˜•μ‹ com.semicolon.project.domain.user
CODE-JAVA-005 μΈν„°νŽ˜μ΄μŠ€/κ΅¬ν˜„μ²΄ μΈν„°νŽ˜μ΄μŠ€: λͺ…사/ν˜•μš©μ‚¬, κ΅¬ν˜„μ²΄: Impl λ˜λŠ” ꡬ체적 이름 UserService (μΈν„°νŽ˜μ΄μŠ€), UserServiceImpl (κ΅¬ν˜„μ²΄)

Java ν•„μˆ˜ κ·œμΉ™

κ·œμΉ™ ID ν•­λͺ© μš”κ΅¬μ‚¬ν•­ μ„ΈλΆ€ λ‚΄μš©
CODE-JAVA-100 Google Java Style Guide μ€€μˆ˜ ν•„μˆ˜ λ“€μ—¬μ“°κΈ° 2/4 슀페이슀, 쀄 길이 100자, import μˆœμ„œ: staticβ†’javaβ†’javaxβ†’orgβ†’com
CODE-JAVA-101 μ ‘κ·Ό μ œμ–΄μž λͺ…μ‹œ ν•„μˆ˜ λͺ¨λ“  클래슀/λ©”μ„œλ“œ/ν•„λ“œμ— λͺ…μ‹œ, μ΅œμ†Œ κΆŒν•œ 원칙 적용
CODE-JAVA-102 μ˜ˆμ™Έ 처리 ꡬ체적 처리 빈 catch κΈˆμ§€, ꡬ체적 μ˜ˆμ™Έ νƒ€μž…, μ»¨ν…μŠ€νŠΈ 포함 λ©”μ‹œμ§€
CODE-JAVA-103 null 체크 null μ•ˆμ „μ„± @NonNull/@Nullable ν™œμš©, Optional μ‚¬μš© ꢌμž₯
CODE-JAVA-104 λ¦¬μ†ŒμŠ€ 관리 try-with-resources AutoCloseable ν™œμš©, Stream/Connection λͺ…μ‹œμ  close

Spring Boot ν•„μˆ˜ κ·œμΉ™

κ·œμΉ™ ID ν•­λͺ© μš”κ΅¬μ‚¬ν•­ μ„ΈλΆ€ λ‚΄μš©
CODE-SPRING-100 계측 ꡬ쑰 3계측 ꡬ쑰 μ€€μˆ˜ Controller β†’ Service β†’ Repository
CODE-SPRING-101 μ˜μ‘΄μ„± μ£Όμž… μƒμ„±μž μ£Όμž… @RequiredArgsConstructor ν™œμš©, ν•„λ“œ/setter μ£Όμž… μ§€μ–‘
CODE-SPRING-102 μ–΄λ…Έν…Œμ΄μ…˜ 계측별 ꡬ뢄 @RestController, @Service, @Repository, @Component
CODE-SPRING-103 DTO μ‚¬μš© Entity 직접 λ…ΈμΆœ κΈˆμ§€ Request/Response DTO 뢄리 (예: UserCreateRequest, UserResponse)
CODE-SPRING-104 μ˜ˆμ™Έ 처리 μ „μ—­ 처리 @ControllerAdvice, μ»€μŠ€ν…€ μ˜ˆμ™Έ 클래슀, ν‘œμ€€ν™”λœ μ—λŸ¬ 응닡
CODE-SPRING-105 νŠΈλžœμž­μ…˜ μ„œλΉ„μŠ€ λ ˆμ΄μ–΄ 적용 @Transactional, readOnly μ˜΅μ…˜ ν™œμš©, νŠΈλžœμž­μ…˜ λ²”μœ„ μ΅œμ†Œν™”

CODE-SPRING-101: μ˜μ‘΄μ„± μ£Όμž… μ˜ˆμ‹œ

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;

    public User getUserById(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new UserNotFoundException(id));
    }
}

Java ꢌμž₯ 사항

κ·œμΉ™ ID ν•­λͺ© ꢌμž₯ 사항
CODE-JAVA-200 Lombok ν™œμš© @Getter, @Setter, @Builder, @ToString(exclude="password") 민감정보 μ œμ™Έ
CODE-JAVA-201 Stream API μ»¬λ ‰μ…˜ 처리 μ‹œ Stream μ‚¬μš©, ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°
CODE-JAVA-202 λΆˆλ³€ 객체 final ν‚€μ›Œλ“œ 적극 ν™œμš©, immutable 객체 섀계
CODE-JAVA-203 ν…ŒμŠ€νŠΈ μž‘μ„± JUnit 5, @Test, @SpringBootTest, Mockito ν™œμš©

Spring Boot ꢌμž₯ 사항

κ·œμΉ™ ID ν•­λͺ© ꢌμž₯ 사항
CODE-SPRING-200 API λ¬Έμ„œν™” Swagger/OpenAPI, @Operation, @ApiResponse μ–΄λ…Έν…Œμ΄μ…˜
CODE-SPRING-201 μ„€μ • 관리 application.yml μ‚¬μš©, ν™˜κ²½λ³„ ν”„λ‘œνŒŒμΌ 뢄리, 민감정보 ν™˜κ²½λ³€μˆ˜ 처리
CODE-SPRING-202 검증 @Valid, @Validated, Bean Validation (@NotNull, @Size, @Email)
CODE-SPRING-203 λ‘œκΉ… SLF4J + Logback, 둜그 레벨 적절히 μ„€μ •, System.out.println κΈˆμ§€

νŒ¨ν‚€μ§€ ꡬ쑰 μ˜ˆμ‹œ

com.semicolon.project
β”œβ”€β”€ domain
β”‚   β”œβ”€β”€ user
β”‚   β”‚   β”œβ”€β”€ controller
β”‚   β”‚   β”‚   └── UserController.java
β”‚   β”‚   β”œβ”€β”€ service
β”‚   β”‚   β”‚   β”œβ”€β”€ UserService.java
β”‚   β”‚   β”‚   └── UserServiceImpl.java
β”‚   β”‚   β”œβ”€β”€ repository
β”‚   β”‚   β”‚   └── UserRepository.java
β”‚   β”‚   β”œβ”€β”€ entity
β”‚   β”‚   β”‚   └── User.java
β”‚   β”‚   └── dto
β”‚   β”‚       β”œβ”€β”€ UserCreateRequest.java
β”‚   β”‚       └── UserResponse.java
β”‚   └── order
β”‚       └── ...
β”œβ”€β”€ global
β”‚   β”œβ”€β”€ config
β”‚   β”‚   └── SecurityConfig.java
β”‚   β”œβ”€β”€ exception
β”‚   β”‚   β”œβ”€β”€ GlobalExceptionHandler.java
β”‚   β”‚   └── BusinessException.java
β”‚   └── common
β”‚       └── ApiResponse.java
└── ProjectApplication.java

κΈˆμ§€ 사항

κ·œμΉ™ ID κΈˆμ§€ ν•­λͺ© μ„€λͺ…
CODE-JAVA-300 맀직 λ„˜λ²„/λ¬Έμžμ—΄ μƒμˆ˜λ‘œ μ •μ˜ ν•„μˆ˜
CODE-JAVA-301 κ³Όλ„ν•œ 주석 μ½”λ“œλ‘œ μ˜λ„ ν‘œν˜„, ν•„μš”μ‹œμ—λ§Œ 주석
CODE-JAVA-302 God Class/Method 단일 μ±…μž„ 원칙 μ€€μˆ˜, λ©”μ„œλ“œλŠ” ν•œ κ°€μ§€ 일만
CODE-SPRING-300 Controller λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 Service λ ˆμ΄μ–΄λ‘œ 뢄리
CODE-SPRING-301 Repository λ³΅μž‘ν•œ 둜직 Serviceμ—μ„œ 처리

πŸ”— κ΄€λ ¨ λ¬Έμ„œ


λ§ˆμ§€λ§‰ μ—…λ°μ΄νŠΈ: 2025-01-06 κ΄€λ¦¬μž: Semicolon Dev Team