π μ½λ 컨벀μ
κ·μΉ ID λ²μ: CODE-*
μ°Έκ³ : μ΄ μΉμ
μ Team Codexμ μ½λ 컨벀μ
μ κΈ°λ°μΌλ‘ μμ±λμμ΅λλ€.
κ΄λ ¨ λ¬Έμ: Development-Philosophy, Dev-Architecture-NextJS
π λͺ©μ°¨
- κ³΅ν΅ κ·μΉ
- React νλ‘μ νΈ κ·μΉ
- 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
ꡬ쑰 κ·μΉ
-
μ»΄ν¬λνΈλͺ
λλ ν 리: κ° μ»΄ν¬λνΈλ PascalCase λλ ν λ¦¬λ‘ μμ±
-
index.tsx: μ»΄ν¬λνΈ λ©μΈ λ‘μ§ (μλμΌλ‘ default import)
-
ComponentName.test.tsx: ν
μ€νΈ μ½λ
-
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