강령의 구조: 조직 및 협약
잘 구성된 코드 구조는 유지 관리 가능한 프로젝트의 기초입니다. Claude는 규칙을 정의하고, 폴더를 구성하고, 유지 관리하는 데 도움을 줄 수 있습니다. 우려의 분리 개발 전반에 걸쳐 일관되게.
이 기사에서는 프로젝트 구성에 대한 모범 사례를 살펴보겠습니다. 스프링부트 e 모난, 명명 규칙에 중점을 두고, 구성 관리 및 코드 구성 패턴.
무엇을 배울 것인가
- 확장 가능한 프로젝트를 위한 폴더 구성
- 파일, 클래스 및 변수에 대한 명명 규칙
- 효과적인 우려사항 분리
- 다중 환경 구성 관리
- 공유 코드 패턴
조직 원칙
코드 구조의 5가지 원칙
| 원칙 | 설명 | 혜택 |
|---|---|---|
| 코로케이션 | 주변 관련 파일 | 빠른 탐색, 적은 컨텍스트 전환 |
| 예측 가능성 | 일관된 구조 | 빠른 온보딩, 오류 감소 |
| 모듈성 | 격리된 기능 | 재사용성, 독립적인 테스트 |
| 확장성 | 리팩토링 없이 성장 | 장기 유지보수 |
| 명시성 | 설명적인 이름 | 자체 문서화 코드 |
백엔드 구조: 스프링 부트
기능별 패키지와 레이어별 패키지
레이어별 패키지
com.company.app/
├── controller/
│ ├── OrderController
│ ├── ProductController
│ └── CustomerController
├── service/
│ ├── OrderService
│ ├── ProductService
│ └── CustomerService
├── repository/
│ ├── OrderRepository
│ └── ProductRepository
└── model/
├── Order
└── Product
장점: 단순함, 친숙함
에 맞서: 결합도가 높아 탐색이 어려움
기능별 패키지
com.company.app/
├── order/
│ ├── OrderController
│ ├── OrderService
│ ├── OrderRepository
│ └── Order
├── product/
│ ├── ProductController
│ ├── ProductService
│ └── Product
└── shared/
└── ...
장점: 높은 응집력, 쉬운 탐색
에 맞서: 규율이 필요하다
추천
개인 프로젝트 및 소규모 팀의 경우 기능별 패키지 바람직하다. 관련 코드를 함께 유지하고 향후 마이크로서비스에서 쉽게 리팩터링할 수 있도록 해줍니다.
완전한 스프링 부트 구조
order-service/
├── src/
│ ├── main/
│ │ ├── java/com/company/orders/
│ │ │ ├── OrderServiceApplication.java
│ │ │ │
│ │ │ ├── order/ # Feature: Orders
│ │ │ │ ├── api/ # Web layer
│ │ │ │ │ ├── OrderController.java
│ │ │ │ │ ├── OrderMapper.java
│ │ │ │ │ └── dto/
│ │ │ │ │ ├── CreateOrderRequest.java
│ │ │ │ │ ├── OrderResponse.java
│ │ │ │ │ └── OrderItemDto.java
│ │ │ │ ├── domain/ # Business logic
│ │ │ │ │ ├── Order.java
│ │ │ │ │ ├── OrderItem.java
│ │ │ │ │ ├── OrderStatus.java
│ │ │ │ │ └── OrderService.java
│ │ │ │ ├── persistence/ # Data access
│ │ │ │ │ ├── OrderRepository.java
│ │ │ │ │ ├── OrderEntity.java
│ │ │ │ │ └── OrderJpaMapper.java
│ │ │ │ └── event/ # Domain events
│ │ │ │ ├── OrderCreatedEvent.java
│ │ │ │ └── OrderEventPublisher.java
│ │ │ │
│ │ │ ├── payment/ # Feature: Payments
│ │ │ │ ├── api/
│ │ │ │ ├── domain/
│ │ │ │ └── client/ # External integration
│ │ │ │ ├── StripeClient.java
│ │ │ │ └── StripeConfig.java
│ │ │ │
│ │ │ ├── shared/ # Cross-cutting
│ │ │ │ ├── exception/
│ │ │ │ │ ├── BusinessException.java
│ │ │ │ │ ├── NotFoundException.java
│ │ │ │ │ └── GlobalExceptionHandler.java
│ │ │ │ ├── validation/
│ │ │ │ │ └── ValidOrderStatus.java
│ │ │ │ └── util/
│ │ │ │ └── DateUtils.java
│ │ │ │
│ │ │ └── config/ # Configuration
│ │ │ ├── SecurityConfig.java
│ │ │ ├── WebConfig.java
│ │ │ ├── KafkaConfig.java
│ │ │ └── properties/
│ │ │ └── AppProperties.java
│ │ │
│ │ └── resources/
│ │ ├── application.yml
│ │ ├── application-dev.yml
│ │ ├── application-prod.yml
│ │ └── db/migration/ # Flyway
│ │ ├── V1__create_orders.sql
│ │ └── V2__add_payment_ref.sql
│ │
│ └── test/
│ └── java/com/company/orders/
│ ├── order/
│ │ ├── api/
│ │ │ └── OrderControllerTest.java
│ │ └── domain/
│ │ └── OrderServiceTest.java
│ └── integration/
│ └── OrderIntegrationTest.java
│
├── docker/
│ └── Dockerfile
├── pom.xml
└── README.md
명명 규칙 Java
## CLASSI
# Controllers: {{ '{' }}Entity{{ '}' }}Controller
OrderController, ProductController, CustomerController
# Services: {{ '{' }}Entity{{ '}' }}Service o {{ '{' }}UseCase{{ '}' }}Service
OrderService, PaymentProcessingService, NotificationService
# Repositories: {{ '{' }}Entity{{ '}' }}Repository
OrderRepository, CustomerRepository
# DTOs: {{ '{' }}Action{{ '}' }}{{ '{' }}Entity{{ '}' }}Request/Response
CreateOrderRequest, OrderResponse, UpdateOrderRequest
# Entities: {{ '{' }}Entity{{ '}' }} o {{ '{' }}Entity{{ '}' }}Entity (per evitare conflitti)
Order, OrderEntity (se c'è domain model separato)
# Exceptions: {{ '{' }}Causa{{ '}' }}Exception
OrderNotFoundException, PaymentFailedException, ValidationException
# Events: {{ '{' }}Entity{{ '}' }}{{ '{' }}Action{{ '}' }}Event
OrderCreatedEvent, PaymentProcessedEvent, OrderShippedEvent
## METODI
# Controller: verbo HTTP implicito nel mapping
@PostMapping → create(...)
@GetMapping("/{id}") → getById(...)
@GetMapping → getAll(...)
@PutMapping → update(...)
@DeleteMapping → delete(...)
# Service: verbo esplicito
createOrder(), findOrderById(), updateOrderStatus(), cancelOrder()
# Repository: Spring Data naming
findById(), findByStatus(), findByCustomerIdAndStatus()
## VARIABILI
# Collections: plurale
List<Order> orders, Set<String> tags
# Singoli: singolare
Order order, Customer customer
# Booleani: is/has/can prefix
boolean isActive, boolean hasPayment, boolean canCancel
프런트엔드 구조: 각도
src/
├── app/
│ ├── core/ # Singleton, app-wide
│ │ ├── services/
│ │ │ ├── api.service.ts
│ │ │ ├── auth.service.ts
│ │ │ ├── storage.service.ts
│ │ │ └── index.ts # Barrel export
│ │ ├── interceptors/
│ │ │ ├── auth.interceptor.ts
│ │ │ ├── error.interceptor.ts
│ │ │ └── loading.interceptor.ts
│ │ ├── guards/
│ │ │ ├── auth.guard.ts
│ │ │ └── role.guard.ts
│ │ └── models/
│ │ ├── user.model.ts
│ │ └── api-response.model.ts
│ │
│ ├── shared/ # Riutilizzabili
│ │ ├── components/
│ │ │ ├── button/
│ │ │ │ ├── button.component.ts
│ │ │ │ ├── button.component.html
│ │ │ │ ├── button.component.css
│ │ │ │ └── button.component.spec.ts
│ │ │ ├── modal/
│ │ │ ├── table/
│ │ │ ├── form-field/
│ │ │ └── index.ts
│ │ ├── pipes/
│ │ │ ├── currency-format.pipe.ts
│ │ │ └── date-ago.pipe.ts
│ │ ├── directives/
│ │ │ └── click-outside.directive.ts
│ │ └── utils/
│ │ └── validators.ts
│ │
│ ├── features/ # Feature modules
│ │ ├── orders/
│ │ │ ├── components/
│ │ │ │ ├── order-list/
│ │ │ │ │ ├── order-list.component.ts
│ │ │ │ │ └── order-list.component.html
│ │ │ │ ├── order-detail/
│ │ │ │ ├── order-form/
│ │ │ │ └── order-card/ # Dumb component
│ │ │ ├── pages/ # Route components
│ │ │ │ ├── orders-page/
│ │ │ │ └── order-detail-page/
│ │ │ ├── services/
│ │ │ │ └── order.service.ts
│ │ │ ├── models/
│ │ │ │ ├── order.model.ts
│ │ │ │ └── order-status.enum.ts
│ │ │ └── orders.routes.ts
│ │ │
│ │ ├── products/
│ │ ├── customers/
│ │ └── dashboard/
│ │
│ ├── layouts/
│ │ ├── main-layout/
│ │ │ ├── main-layout.component.ts
│ │ │ ├── header/
│ │ │ ├── sidebar/
│ │ │ └── footer/
│ │ └── auth-layout/
│ │
│ ├── app.component.ts
│ ├── app.config.ts
│ └── app.routes.ts
│
├── assets/
│ ├── images/
│ ├── icons/
│ └── i18n/ # Traduzioni
│
├── environments/
│ ├── environment.ts
│ └── environment.prod.ts
│
└── styles/
├── _variables.css
├── _mixins.css
└── global.css
명명 규칙 Angular
## FILE
# Componenti: kebab-case.component.ts
order-list.component.ts
order-detail.component.ts
user-profile-card.component.ts
# Servizi: kebab-case.service.ts
order.service.ts
auth.service.ts
notification.service.ts
# Models: kebab-case.model.ts
order.model.ts
user.model.ts
# Pipes: kebab-case.pipe.ts
currency-format.pipe.ts
date-ago.pipe.ts
# Guards: kebab-case.guard.ts
auth.guard.ts
role.guard.ts
## CLASSI
# Componenti: PascalCase + Component suffix
export class OrderListComponent
export class UserProfileCardComponent
# Servizi: PascalCase + Service suffix
export class OrderService
export class AuthService
# Models/Interfaces: PascalCase (no suffix)
export interface Order
export type OrderStatus = 'PENDING' | 'COMPLETED'
## SELETTORI
# Prefix app- + kebab-case
selector: 'app-order-list'
selector: 'app-user-card'
## VARIABILI
# Signals: nomeSignal o nome (opinabile)
ordersSignal = signal<Order[]>([]);
loading = signal(false);
# Observables: nome$ suffix
orders$ = this.http.get<Order[]>(...)
user$ = this.authService.currentUser$
# Boolean: is/has prefix
isLoading = signal(false);
hasError = signal(false);
구성 관리
스프링 부트: 다중 환경
spring:
application:
name: order-service
datasource:
url: ${DATABASE_URL}
username: ${DATABASE_USER}
password: ${DATABASE_PASSWORD}
jpa:
hibernate:
ddl-auto: validate
open-in-view: false
app:
cors:
allowed-origins: ${CORS_ORIGINS:http://localhost:4200}
security:
jwt-secret: ${JWT_SECRET}
jwt-expiration: 3600000
spring:
datasource:
url: jdbc:postgresql://localhost:5432/orders_dev
jpa:
show-sql: true
logging:
level:
com.company.orders: DEBUG
org.hibernate.SQL: DEBUG
app:
cors:
allowed-origins: http://localhost:4200
Angular: 환경 파일
export const environment = {{ '{' }}
production: false,
apiUrl: 'http://localhost:8080/api/v1',
features: {{ '{' }}
enableAnalytics: false,
enableDarkMode: true,
{{ '}' }},
auth: {{ '{' }}
tokenKey: 'auth_token',
refreshTokenKey: 'refresh_token',
{{ '}' }}
{{ '}' }};
코드 구조 체크리스트
프로젝트 조직 체크리스트
- README에 문서화된 폴더 구조
- 명명 규칙이 정의되고 공유됨
- 높은 응집력을 위한 기능별 패키지
- 기능별로 구분된 공유/코어
- 환경별 구성(개발, 스테이징, 프로덕션)
- 청정 수입을 위한 배럴 수출
- 소스 코드와 함께 배치된 테스트
결론 및 다음 단계
이 기사에서 우리는 코드 구조의 기초를 정의했습니다. 유지 관리 및 확장이 가능합니다. 에서 다음 기사, 우리는 탐구할 것입니다 고급 기술 신속한 엔지니어링 얻기 위해 복잡한 시나리오에서 Claude를 최대한 활용할 수 있습니다.
기억해야 할 핵심 사항
- 기능별 패키지: 관련 코드를 함께 유지
- 일관된 이름 지정: 팀 전체를 위한 명확한 규칙
- 코어/공유/기능: 명확한 책임 분리
- 환경별 구성: 하드코딩된 것이 없으며 모든 것이 구성 가능합니다.
- 구조를 문서화하십시오. 폴더 트리가 포함된 README







