현재 프로젝트의 폴더 구조를 분석해보면 다음과 같은 계층형 구조로 되어 있습니다:
Backend/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com.example.gc_coffee/
│ │ │ ├── domain/
│ │ │ │ ├── admin/
│ │ │ │ ├── item/
│ │ │ │ └── order/
│ │ │ └── global/
│ │ │ ├── exceptions/
│ │ │ ├── springDoc/
│ │ │ └── util/
│ └── test/
폴더 구조가 중요한 이유:
도메인 주도 설계(DDD) 반영
관심사의 분리
계층 구조의 명확성
domain/
├── admin/
│ ├── controller/
│ ├── service/
│ └── entity/
테스트 용이성
확장성
현재 코드베이스에서 이러한 구조가 잘 적용된 예시:
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // 비밀번호 암호화
}
@Bean
public UserDetailsService userDetailsService() {
// 관리자 계정 설정 (메모리 기반)
UserDetails admin = User.builder()
.username("team4@admin.com")
.password(passwordEncoder().encode("admin_team4")) // 비밀번호 암호화
.roles("ADMIN") // ADMIN 역할 부여
.build();
return new InMemoryUserDetailsManager(admin);
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService()); // UserDetailsService 연결
provider.setPasswordEncoder(passwordEncoder()); // PasswordEncoder 연결
return provider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager(); // AuthenticationManager 설정
}
}
이러한 체계적인 폴더 구조는 프로젝트의 확장성, 유지보수성, 테스트 용이성을 크게 향상시키며, 팀 멤버들의 코드 이해와 협업을 더욱 효과적으로 만듭니다.
현재 위치:
domain/admin/login/SecurityConfig.java
개선안:
global/config/security/SecurityConfig.java
이유: Security는 특정 도메인이 아닌 애플리케이션 전체의 설정이므로 global 영역으로 이동해야 함
현재:
domain/admin/
├── login/
│ ├── controller/
│ └── service/
└── service/AdminService.java
개선안:
domain/admin/
├── controller/
├── service/
├── repository/
├── entity/
└── dto/
현재:
global/
├── exceptions/
├── springDoc/
└── util/
개선안:
global/
├── config/ # 각종 설정 파일
│ ├── security/
│ ├── swagger/
│ └── web/
├── common/ # 공통 컴포넌트
│ ├── response/
│ └── util/
└── error/ # 예외 처리
├── exception/
└── handler/
src/
├── main/
│ ├── java/
│ │ └── com.project/
│ │ ├── domain/ # 도메인 별 패키지
│ │ ├── global/ # 공통 설정 및 유틸
│ │ └── infrastructure/ # 외부 인프라 연동
│ └── resources/
│ ├── static/
│ └── application.yml
domain/webtoon/
├── controller/
│ ├── WebtoonController.java
│ └── dto/
│ ├── request/
│ └── response/
├── service/
│ ├── WebtoonService.java
│ └── dto/
├── repository/
│ ├── WebtoonRepository.java
│ └── dto/
└── entity/
└── Webtoon.java
global/
├── config/ # 설정 클래스
│ ├── SecurityConfig.java
│ ├── JpaConfig.java
│ └── WebConfig.java
├── common/ # 공통 컴포넌트
│ ├── annotation/
│ ├── response/
│ │ ├── ApiResponse.java
│ │ └── ErrorResponse.java
│ └── util/
├── error/ # 예외 처리
│ ├── exception/
│ │ ├── BusinessException.java
│ │ └── ErrorCode.java
│ └── handler/
│ └── GlobalExceptionHandler.java
└── security/ # 보안 관련
├── jwt/
└── oauth/
// Controller Layer
@RestController
@RequestMapping("/api/webtoons")
public class WebtoonController {
@GetMapping("/{id}")
public ApiResponse<WebtoonResponse> getWebtoon(@PathVariable Long id) {
WebtoonDto webtoonDto = webtoonService.getWebtoon(id);
return ApiResponse.success(WebtoonResponse.from(webtoonDto));
}
}
// Service Layer
@Service
public class WebtoonService {
public WebtoonDto getWebtoon(Long id) {
Webtoon webtoon = webtoonRepository.findById(id)
.orElseThrow(() -> new BusinessException(ErrorCode.WEBTOON_NOT_FOUND));
return WebtoonDto.from(webtoon);
}
}
test/
├── java/
│ └── com.project/
│ ├── domain/
│ │ └── webtoon/
│ │ ├── controller/
│ │ ├── service/
│ │ └── repository/
│ └── common/
└── resources/
└── application-test.yml
명확한 레이어 구분
일관된 응답 형식
public class ApiResponse<T> {
private final boolean success;
private final T data;
private final ErrorResponse error;
}
public enum ErrorCode {
WEBTOON_NOT_FOUND(404, "W001", "웹툰을 찾을 수 없습니다."),
INVALID_REQUEST(400, "C001", "잘못된 요청입니다.");
// ...
}
# application.yml
spring:
profiles:
active: local
# application-local.yml
# application-dev.yml
# application-prod.yml
이러한 구조화를 통해 코드의 가독성, 유지보수성, 테스트 용이성이 크게 향상될 것입니다.