2주차는 진짜 엄청나게 빡셌다..
진짜 빡셨다
커피챗 프로젝트를 본격적으로 시작하기 전에, 크게 세 가지로 나눠서 정리해볼 수 있을 것 같다.
이번 글에서는 2번, 팀원이랑 매일 밤 10시까지 카톡을 붙잡고 논의했던 기술 스택 선정 과정을 정리해보려고 한다.
이 부분은 아예 팀원한테 맡겼다. 왜냐면 이런 건 팀원이랑 하나하나 논의하면서 세팅값 찾는 게 더 좋다고 생각했기 때문.
ESLint + Prettier (프론트엔드), Checkstyle (백엔드)로 관리하기로 했다.
처음부터 에어비앤비처럼 빡빡한 규칙 대신, 널널하게 시작하기로 했다. 일단 개발 시작해보면서 불편한 부분 생기면 그때그때 룰 추가하는 게 낫더라.
코드 컨벤션을 정하면서 "왜 이렇게 해야 하는지" 고민한 흔적들을 남겨둔다.
결정: /user-profile, /order-items 이런 식으로
근거:
/userProfile vs /UserProfile 혼동 가능결정: 들여쓰기는 무조건 Tab(\t) 사용
왜 Space 안 쓰냐면...
Space는 ' '를 여러 번 반복하는 거잖아? 근데 Tab은 단일 문자 \t 하나다.
과거 환경이나 일부 시스템에서 Tab과 Space를 서로 다른 문자로 인식해서, 혼용하면 diff 볼 때나 정렬할 때 난리남. Python 해봤으면 알 거임ㅋㅋ
Tab 쓰면 좋은 점:
핵심: 들여쓰기의 "의미"는 Tab으로, 보여지는 "폭"은 에디터 설정에 맡긴다.
-> 하지만 우리는 단 둘이라서 별 신경 안쓰기로 했지롱 하하!!!!!!
❌ 이런 거 쓰지 마세요
import java.util.*;
⭕ 이렇게 쓰세요
import java.util.List;
import java.util.Map;
근거:
"가독성보다 의도 명확성을 우선한다"
처음엔 이것저것 정하는 게 귀찮았는데, 막상 정해두니까 PR 날릴 때 쓸데없는 논쟁이 줄어들더라. 역시 선제적 합의가 답이다.
관련으로 재밌는 이슈가 있어서 공유한다
Change useTabs to true by default (Prettier #7475)
Prettier 2.0 버전에서 여러 기본 옵션을 변경하면서 useTabs 옵션의 기본값도 false에서 true로 변경하자는 제안이다.
"TDD를 진행해봅시다!" 라고 제안했다.
왜 TDD를 고민하게 됐냐면...
사실 우리 프로젝트는 FastAPI에서 Java/Spring으로 마이그레이션하는 게 핵심이잖아?
기존 Python 코드를 Java로 옮기면서 "이 로직이 제대로 동작하는지" 계속 확인해야 하는데, 매번 서버 띄워서 Postman으로 찔러보기엔 너무 비효율적이다.
그리고 마이그레이션이라는 게... 기존 기능을 그대로 옮기는 거잖아? "이전이랑 똑같이 동작하는가?"를 검증하는 게 제일 중요한데, 테스트 코드 없이 어떻게 확신할 수 있겠어?
그래서 TDD가 딱 맞다고 생각했다:
1. 기존 Python API 스펙 보고 → 테스트 케이스 먼저 작성
2. Java로 구현
3. 테스트 통과하면 → 마이그레이션 성공
이렇게 하면 회귀 테스트(Regression Test)도 자동으로 되고, 나중에 리팩토링할 때도 "내가 뭘 망가뜨렸나?" 걱정 안 해도 되니까.
근데 나도 TDD를 제대로 해본 적이 없어서, 팀원이랑 같이 공부하면서 적용해보자는 마음으로 인프런 강의에서 키워드를 얻어봤다
📚 추천한 강의: "더 자바, 애플리케이션을 테스트하는 다양한 방법" (총 5시간 16분)섹션 1. JUnit 5 (2시간 13분)
섹션 2. Mockito (1시간 4분)
섹션 3. 도커와 테스트 (54분)
섹션 4. 성능 테스트 (33분)
섹션 5. 운영 이슈 테스트 (27분)
섹션 6. 아키텍처 테스트 (39분)
일단 JUnit이랑 모키토를 나도 공부해봐야겠다
자, 여기서부터가 진짜 핵심이다. Spring Boot 버전이랑 Java 버전 선택하는 게 생각보다 고민이 많았다.
처음엔 나도 Spring Boot 4.0이 솔직히 좀 당겼다.
4.0의 매력
근데 현실은...
결국 팀원이랑 논의 끝에 Spring Boot 3.5.9로 결정했다.
📌 Spring Boot 4.0.1 주요 변경사항 (접기/펼치기)최종 결정 근거
- ✅ 안정적인 LTS 버전
- ✅ 레퍼런스 충분함
- ✅ 일정 밀리지 않고 진도 나갈 수 있다고 확답 가능
- ✅ 마이그레이션 프로젝트라는 목적에 충분히 적합
4.0이 궁금했던 사람을 위해 간단정리
주요 변경사항
spring-boot-restclient 의존성 필수버그 수정 (실무 관련)
의존성 업그레이드
더 자세한 내용은 공식 릴리스 노트 참고!
Java 버전도 고민이 많았다.
왜 여기에 17이 없냐고 묻는다면 귀찮아서 논의하지 않았다...
Java 21 (LTS)
Java 25 (최신)
우리 서비스 예상 트래픽이... DAU 10명 내외라서 (허공 응시2) Virtual Thread까지 필요한가 싶었다. 채팅 기능 같은 거라도 있으면 모를까.
그리고 Java 21의 Virtual Thread에 핀잉(pinning) 문제가 있어서, 가상 스레드 쓰려면 25가 낫다는데... 우리 프로젝트엔 과한 것 같았다.
최종 결정: Java 21 + Spring Boot 3.5.9
- ✅ LTS 버전으로 안정성 확보
- ✅ 충분한 레퍼런스와 커뮤니티 지원
- ✅ JVM 고민도 할 수 있음 (이자나, 오브젝트, 토끼책 등)
- ✅ 일정 준수 가능
Jira 대신 GitHub 생태계를 전부 활용하기로 했다.
챌린지: CI/CD에서 변경사항 감지 및 선택적 배포 구현
근거: 1인 프로젝트로 시작했지만, CI/CD 학습 관점에서는 오히려 더 어렵고 좋은 경험이 될 것 같았다.
자, 이제 실전이다. 모노레포 구조에서 Spring Boot 서버 어떻게 띄우는지 정리해본다.

이런 장문의 설명을 냅다 카톡으로만 봐주신 팀원에게 감사인사를...
IntelliJ에서 File → Project Structure → SDK로 들어가면 Java 다운받을 수 있다.

여기서 OpenJDK 21을 다운받는다.
왜 OpenJDK?
지금은 일단 OpenJDK로 시작하고, 나중에 Docker 이미지 크기 비교해서 최적화할 때 GraalVM Community 버전으로 바꿀 예정이다.
사유 : docker 이미지 최적화를 할정도의 시간이 남을지도 의문이고 graalvm을 잘 다룰 수 있을지도 아직 확신이 안서 이런 결정을 하게 되었다
Run/Debug Configurations 편집해본 적 있는가?

모노레포라서 프로젝트 루트가 cohi-chat인데, Gradle 세팅은 backend에 있다. 그래서 IntelliJ가 "어? Gradle 세팅 어디있어?" 하고 잉잉거린다.
이때 "아~ 내 루트 디렉토리는 backend야~" 하고 알려줘야 한다.
settings.gradle에서 이렇게 설정한다:
rootProject.name = 'backend'
Gradle Wrapper 배치 파일이다. Tomcat의 start.bat 같은 거라고 생각하면 된다.
@rem 주석
@if "%DEBUG%"=="" @echo off // debug 모드 설정
if "%OS%"=="Windows_NT" setlocal // OS 확인
set DIRNAME=%~dp0 // 디렉토리 경로 설정
@rem JVM 옵션 설정
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
여기서 JVM 튜닝 가능하다! 힙 메모리 최대/최소값 조정하고 싶으면 여기 수정하면 됨.
Spring Boot가 Bean 등록을 자동으로 해주잖아? 그 자동으로 등록된 걸 어딘가에 잘 모아둬야 하고, Tomcat이 알아서 JAR을 배포해주면 좋겠잖아?
그게 gradle/wrapper/gradle-wrapper.jar이다.
.gradle: Gradle 설정 파일.idea: IntelliJ 설정 (Eclipse가 맨날 잘못 읽고 울어버림ㅋㅋ 그래서 gitignore하는 곳도 있는데 난 귀찮아서 안 함)2주차 1편은 여기까지!
다음 편에서는 "내가 다 한 것들"을 정리해볼 예정이다. 에러 수정, 배포 설정, 그리고... 혼자 밤새 삽질한 이야기들ㅎㅎ