오늘 공부해볼 내용은 '형식 맞추기' 챕터이다. 이글을 읽고 느낀점은 다음과 같다.
첫째, 코드 형식이 단순한 ‘꾸밈’이 아니라 의사소통 수단이라는 점이 인상 깊다. 빈 행 하나, 공백 하나에도 “이건 한 덩어리 개념이야” 혹은 “이 부분은 밀접하게 엮여 있어”라는 메시지를 담을 수 있다는 생각이 신기하다. 덕분에 무심코 지나쳤던 줄바꿈의 의미를 곱씹어 보게 되었고, 앞으로 코드를 쓸 때마다 ‘내가 동료에게 어떤 생각을 전하려 하나?’를 먼저 떠올리게 될 것 같다.
둘째, 밀집도와 코드 간 거리를 적절히 조절하면 코드가 눈에 들어오는 방식이 달라진다는 사실을 이 글로 재확인했다. 예전 프로젝트를 할때 이 부분들이 늘 헷갈리고 고민됐는데, 앞으로 “사용 위치 바로 앞에 변수 선언하기”나 “종속 함수는 호출하는 쪽 밑에 두기” 같은 작은 규칙들로 확신하고 프로젝트의 가독성을 높여 갈 수 있을것이다.
셋째, IDE의 Formatter 기능을 적극 활용하자, 현재 프로젝트에 도입해 보자는 생각이 들었다. 이제까지 읽은 규칙들을 바타응로 IDE 포매터를 적용해 보는 작업을 해볼 것 이다.
마무리로, 이 챕터를 읽고 나니 ‘리팩터링은 곧 형식 다듬기’라는 생각이 든다. 이제 원칙들을 하나씩 체크리스트에 올려두고 실천해 보려 한다.
이번 스터디에서 중점 토론한 내용은 아래와 같다.
Q. assertTrue(), assertFalse()처럼 "종속성 순서"와 "개념적 유사성"이 충돌할 때 무엇을 우선순위로 두는 게 좋을까?
MapService {
getAddress {
googleAddressApiService();
}
getPlace {
googlePlaceApiService();
}
googleAddressApiService {...}
googlePlaceApiService {...}
}
먼저 위는 "개념적 유사성"을 우선으로 한 코드로, 추상화 레벨이 같은 함수끼리 묶는다.
윗단에는 추상화 함수 로직(public), 아래에 해당 함수의 세부 하위 로직을 둔다.(private)
MapService {
getAddress {
googleAddressApiService();
}
googleAddressApiService {...}
getPlace {
googlePlaceApiService();
}
googlePlaceApiService {...}
}
위는, 클린코드 원칙대로 "종속성 순서"에 우위를 둔 코드이다.
✅ 토론의 결론부터 말하면:
"종속성 순서"를 우선시하는 것이 바람직하다.
개념적 유사성을 우선했을때는, 추상화 레벨이 같다.
💬 의견 정리 – 코드 구조에 대한 관점
"비즈니스 로직이 한군데 묶여 있다는 점에서 두번째 구조가 매력적이다. 접근 제어자(public, private)를 통해 충분히 추상화 레벨이 구분 가능하고, 클래스 분리 시에도 유리한 형태이다."
- 비즈니스 로직의 집중도와 가독성을 높일 수 있음
- 비즈니스 로직 단위로 분리되어 있기때문에 코드 리팩토링 할때 편리함
- 구조가 단순하고 코드 길이가 짧을 경우, 이 방식이 더 적합하다고 판단됨
"물론, 코드 줄 수가 길어지면 public 메서드만 먼저 보이는 구조가 더 직관적일 수 있다. 하지만 그런 경우라면 해당 클래스는 너무 커졌다는 신호이며, 결국 클래스를 분리하는 것이 정답이라는 의견이 도출됐다."
- 코드의 확장성과 유지보수를 위해서는 적절한 클래스 분리가 중요하다. 위의 의견은 결국 코드가 길어진다는 전제인데, 그렇다면 SOLID 원칙에 따라 분리하는게 적절해 보인다! (+ 파서드 패턴)
"예를 들어, 아래와 같이 도메인 기반으로 클래스가 분리되어 있는 구조는 좋은 방향이다!"
- GoogleAddressApiService
- GooglePlaceApiService
- MapService
또한, 코드 원칙을 정할때는
1. 팀의 원칙을 우선한다.
2. 애매하다면 해당언어의 규칙을 우선한다!
각 언어의 형식 규칙은 아래처럼 문서화가 잘 되어있다.
https://google.github.io/styleguide/javaguide.html
https://peps.python.org/pep-0008/
Google Java Style Guide
1 Introduction This document serves as the complete definition of Google's coding standards for source code in the Java™ Programming Language. A Java source file is described as being in Google Style if and only if it adheres to the rules herein. Like ot
google.github.io
PEP 8 – Style Guide for Python Code | peps.python.org
This document gives coding conventions for the Python code comprising the standard library in the main Python distribution. Please see the companion informational PEP describing style guidelines for the C code in the C implementation of Python.
peps.python.org
이제 책의 내용을 정리해본다.
1. 형식을 맞추는 목적
- 소통 수단: 코드 스타일은 곧 의사소통 방식이다.
- 표준화: 팀이 합의한 규칙을 따르고, 도구로 자동화하자.
2. 적절한 행 길이를 유지하라
- 파일 길이: 보통 200줄 이내가 이해하기 좋다.
- 행 길이: 120자 정도를 넘기지 않도록 주의.
- 너무 긴 파일이나 행은 분할 리팩토링의 신호일 수 있습니다.
3. 신문 기사처럼 작성하라
- 소스 파일명: 짧고 모듈을 대표할 만큼 설명적이어야 한다.
- 상단 요약: 파일의 핵심 개념과 알고리즘을 간단히 기술한다.
- 점진적 세부화: 하위 구현은 아래로 내려오면서 차차 드러내고, 상위단은 추상화.
4. 개념은 빈 행으로 분리하라
- 빈 행 = 완결된 생각 사이의 틈.
- 의미 단위마다 한 줄 띄우면 가독성이 확 올라간다.
// 💡 빈 행 없을 때: 한 덩어리처럼 보임
doFirst();
doSecond();
handleResult();
// 💡 빈 행 있을 때: 단계가 분명해짐
doFirst();
doSecond();
handleResult();
5. 세로 밀집도 (Vertical Density)
- 연관 코드끼리 배치: 서로 관련 깊은 선언이나 메서드는 가까이 둬야 한다.
- 불필요 주석 제거: 이를 통해 코드 밀집도를 높여, 핵심 파악이 잘 되도록 한다.
6. 수직 거리 (Vertical Distance)
- 변수 선언은 사용하는 위치에 최대한 가깝게 둔다.
- 인스턴스 변수는 클래스 최상단(자바 기준)에 모아두고, 서로 간에 간격 없이 둔다.
7. 세로 순서 (Vertical Order)
- 고차원 → 저차원: 의존성 순서대로 메서드를 배치.
- 호출하는 메서드 바로 아래에, 호출되는 메서드를 정의하면 예측 가능성이 높아진다.
8. 가로 형식 맞추기
- 행 길이: 80~120자 사이 권장.
- 짧고 명확한 행이 읽기 쉽다.
9. 들여쓰기 (Indentation)
- 들여쓰기는 구조의 언어.
- 단 한 줄이라도, 명확한 범위 표현을 위해 반드시 지키자!
12. 가짜 범위 (Empty Block)
- 빈 while, for 블록은 가급적 피하되, 불가피하다면
12. 가짜 범위 (Empty Block)
- 빈 while, for 블록은 가급적 피하되, 불가피하다면처럼 주석으로 의도를 명시적으로 표시하자.
while (condition) {
// intentionally left empty
}
13. 팀 규칙 (Team Convention)
- 최우선: 개인 스타일보다 팀의 합의를 지키자.
- IDE Formatter 설정을 미리 공유해, 자동 적용하기!
포매터 적용하기
인터넷에 구글링 하면 공개된 포매터를 무료로 다운로드 받을 수 있다. 나는 타임딜 프로젝트에 내가 선택한 우테코 스타일의 포매터를 적용해봤다. (나중이라는 핑계로 미루면 다음은 없음을 잘 알기에-바로적용)
클린 코드 “형식 맞추기” 원칙과 매핑되는 주요 IntelliJ 포매터 설정만 골라 정리했다.
아래참고:)
1. 일관된 들여쓰기 | INDENT_SIZE=4, USE_TAB_CHARACTER=false |
스페이스 4칸으로 통일, 이어쓰기에는 두 배(8칸) 들여쓰기. 탭 문자는 사용하지 않아 모두 같은 폭을 유지. |
2. 개념 별 빈 행 구분 | KEEP_BLANK_LINES_IN_CODE=1 | 최대 1줄 빈칸 허용. 논리적 덩어리(메소드, 필드 그룹, 제어문 전후)마다 한 줄씩 비워 “완결된 생각”을 분리하자. |
3. 적절한 행 길이 유지 | RIGHT_MARGIN=120 | 120자 이상 넘어가면 IDE가 경고 표시. 긴 행은 자동으로 래핑하거나 리팩토링 신호로 활용하자! |
4. 중괄호 강제 사용 | IF_BRACE_FORCE=3... | 모든 제어문에 중괄호를 강제(Force braces always). 한 줄짜리 블록이라도 가독성과 안전을 위해 중괄호를 쓰자! |
5. 연산자·토큰 래핑 | - BINARY_OPERATION_SIGN_ON_NEXT_LINE=true... | 이항 연산자 등을 다음 줄로 내리고, 필요 시 자동 래핑(Wrap if long)한다. |
6. 임포트 그룹 분리 | IMPORT_LAYOUT_TABLE에서 static, 일반 import 사이에 빈 줄 | 관련 없는 import 그룹을 빈 줄로 나눠, “비슷한 개념끼리 묶고” “다른 개념은 분리”하는 원칙을 반영한다. |
포매터..미리적용좀할걸;
'개발프로젝트' 카테고리의 다른 글
[CleanCode] 실제 프로젝트에서 Clean Code 원칙을 적용한 예외 처리 리팩토링 경험기 (1) | 2025.05.26 |
---|---|
[개발프로젝트] 스프링 API 예외 처리, 이제 try-catch는 그만! (1) | 2025.05.26 |
[CleanCode] 주석은 변명이 아니다 – 네이버 쇼핑 API 응용 코드로 알아보는 클린 코드 (3) | 2025.05.19 |
[CleanCode] 함수 – 클린코드 원칙대로 리뷰 기능 함수를 리팩토링 해보자 (1) | 2025.05.19 |
[개발프로젝트] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 chapter 10- 24시간 365일 중단 없는 서비스를 만들자 (1) | 2024.01.14 |