코드 스타일
기본 원칙
- 메서드 길이: 30줄 이하
- 중첩 if/for: 3단계 이하
null반환 금지 →Optional또는 예외 처리- 매직 넘버/스트링 금지 → 상수 또는 Enum 사용
- 중복 코드 3회 이상 반복 → 메서드 추출
블록 사용 필수
// 잘못된 예 — 블록 없이 한 줄
if (condition)
doSomething();
// 올바른 예 — 항상 블록 사용
if (condition) {
doSomething();
}
메서드 30줄 이하
메서드가 30줄을 초과하면 책임이 너무 많다는 신호다. 메서드를 분리한다.
// 잘못된 예 — 너무 긴 메서드
public void runDigest() {
// 뉴스 조회 로직 (10줄)
// AI 처리 로직 (15줄)
// DB 저장 로직 (10줄)
// 메일 발송 로직 (10줄)
// 총 45줄 — 분리 필요
}
// 올바른 예 — 책임 분리
public void runDigest() {
List<NewsItem> news = collectRecentNews(); // 위임
List<DigestNews> digests = processWithAi(news); // 위임
saveDigests(digests); // 위임
sendMail(digests); // 위임
}
중첩 if/for 3단계 이하
// 잘못된 예 — 4단계 중첩
for (Category category : categories) {
for (Source source : sources) {
if (source.isActive()) {
if (source.getCategory().equals(category)) {
process(source); // 4단계 중첩 — 금지
}
}
}
}
// 올바른 예 — early return / Stream 활용
for (Category category : categories) {
sources.stream()
.filter(Source::isActive)
.filter(s -> s.getCategory().equals(category))
.forEach(this::process);
}
null 반환 금지
// 잘못된 예 — null 반환
public PostDetailRes getPost(Long id) {
return postRepository.findById(id)
.map(PostDetailRes::from)
.orElse(null); // 호출 측에서 NPE 위험
}
// 올바른 예 1 — 예외 처리
public PostDetailRes getPost(Long id) {
return postRepository.findById(id)
.map(PostDetailRes::from)
.orElseThrow(() -> new IllegalArgumentException("포스트를 찾을 수 없습니다: " + id));
}
// 올바른 예 2 — Optional 반환
public Optional<PostDetailRes> findPost(Long id) {
return postRepository.findById(id).map(PostDetailRes::from);
}
// 올바른 예 3 — 빈 컬렉션 반환 (목록)
public List<PostDetailRes> getPostList() {
return postRepository.findAll().stream()
.map(PostDetailRes::from)
.toList();
// null 대신 빈 List 반환
}
매직 넘버/스트링 금지
// 잘못된 예 — 매직 넘버
Pageable pageable = PageRequest.of(page, 10); // 10이 뭘 의미하는가?
if (retryCount > 3) { ... } // 3이 뭘 의미하는가?
// 올바른 예 — 상수 사용
Pageable pageable = PageRequest.of(page, PagingConstant.DEFAULT_SIZE);
if (retryCount > CollectConstant.MAX_RETRY_COUNT) { ... }
// 잘못된 예 — 매직 스트링
if ("PUBLISHED".equals(post.getStatus())) { ... }
// 올바른 예 1 — 상수 사용
if (PostConstant.STATUS_PUBLISHED.equals(post.getStatus())) { ... }
// 올바른 예 2 — Enum 사용
public enum PostStatus {
PUBLISHED, DRAFT, DELETED
}
if (PostStatus.PUBLISHED == post.getStatus()) { ... }
파라미터 3개 초과 시 객체로 묶기
// 잘못된 예 — 파라미터 4개
public List<NewsListRes> getNewsList(String category, String keyword, int page, int size) { ... }
// 올바른 예 — 요청 객체로 묶기
public List<NewsListRes> getNewsList(NewsSearchReq req) { ... }
Stream 활용
// 명령형 스타일
List<PostDetailRes> result = new ArrayList<>();
for (Post post : posts) {
if (post.getCategory().equals(category)) {
result.add(PostDetailRes.from(post));
}
}
// Stream 스타일 (권장)
List<PostDetailRes> result = posts.stream()
.filter(p -> p.getCategory().equals(category))
.map(PostDetailRes::from)
.toList();
코드 스타일 체크리스트
- [ ] 모든 if/for 블록
{}사용 - [ ] 메서드 30줄 이하
- [ ] 중첩 if/for 3단계 이하
- [ ]
null반환 없음 - [ ] 매직 넘버/스트링 없음
- [ ] 파라미터 3개 초과 시 요청 객체 사용
- [ ] 중복 코드 3회 이상 → 메서드 추출