🚀 CI → CD → CI/CD 통합 초기에는 배포까지는 고려하지 않고 CI만 구현한 상태로, 빌드는 잘 작동하고 있었다. 하지만 기능이 하나둘 늘어나며 EC2에 직접 배포가 필요해졌고, 기존 CI는 그대로 두고 CD workflow만 별도로 새로 작성했다. 그러
logback 이란? Spring Boot에서 기본으로 사용하는 로깅 프레임워크는 Logback이다. Logback은 SLF4J(Simple Logging Facade for Java)를 구현한 프레임워크로, 성능과 유연성이 뛰어나고 설정이 간편해서 널리 사용된다.
✅ 오늘 한 일 UserController의 /api/signup API에 대한 유효성 검증 실패 테스트 코드를 작성했다. Spring Boot 3.4.4 환경에서 @WebMvcTest를 기반으로 컨트롤러 단위 테스트를 구현했다. @Valid 유효성 검사가 제대로 동작
🛠️ 초기 상태: 단순 pkill 방식 프로젝트 초반에는 EC2에서 Spring Boot 애플리케이션을 배포할 때 아래처럼 아주 단순한 방식으로 start.sh를 작성해 사용했다. ⚠️ 문제점 pkill -f는 애플리케이션 이름에 기반한 강제 종료이기 때문에 실행
⚠️ 문제 상황 기존 운영 환경에서 MySQL 접속 시 다음과 같은 설정을 사용하고 있었다. 이 설정은 개발 및 테스트 환경에서는 간편하지만, 운영 환경에서는 보안상 매우 위험한 옵션이다. ❓ 왜 allowPublicKeyRetrieval=true가 보안에 취약한가
1. 무료 도메인 생성 (내도메인.한국) 사용하고 싶은 도메인을 검색해 등록한다. 도메인 등록 후 DNS 설정에서 EC2 퍼블릭 IP로 A 레코드 추가 공백, www 모두 설정 2. EC2 인스턴스에서 Nginx + Certbot 설치 Nginx 설치 Cerb
1. Swagger 설정 후 401 에러 발생 Swagger UI 적용을 위해 다음 의존성을 추가했다. 그런데 /swagger-ui/index.html 접속 시 401 Unauthorized 에러가 발생했고, 콘솔에는 NoSuchMethodError와 Control
✅ 목표 AccessToken + RefreshToken 인증 구조 완성 RefreshToken은 Redis에 저장 로그아웃 시 Redis에서 RefreshToken 제거 AccessToken을 블랙리스트로 Redis에 등록하여 차단 Redis 키 값 확인을 위
로컬, 테스트, 운영 환경을 나눠서 각각의 DB 설정, AWS 설정, 보안 값을 관리하기 위함설정 충돌 없이 profile에 따라 필요한 설정만 자동으로 불러오도록 구성하고자 했음공통 설정 (JPA, Redis, AWS 리전, 파일 업로드 설정 등)을 여기에 작성.pr
처음 프로젝트를 시작할 땐 그냥 익숙한 대로 하나의 모듈에 컨트롤러, 서비스, 엔티티, 레포지토리, 설정 파일까지 다 몰아넣어서 진행했다.나름대로 user, item, order 같은 디렉토리로 분리해서 관리는 했지만, 점점 코드가 많아지고 기능이 늘어날수록 구조적으로
요청(request)과 응답(response)의 traceId를 로그에 자동 포함하고 요청 본문(JSON, multipart/form-data)과 응답 바디를 전문 로깅하며 멀티 스레드 환경에서도 traceId 유지 및 추적 가능하게 만들었다.MDC (Mapped Di
❓ 소나큐브(SonarQube)란? SonarQube는 정적 코드 분석 도구로, 코드 품질을 점검하고 버그, 취약점, 코드 스멜 등을 찾아내어 개발자가 더 나은 코드를 작성할 수 있게 도와준다. Git Bash에서 Docker 설치 및 SonarQube 시작 Win
⚠️ 문제 상황 GitHub Actions를 통해 EC2에 배포할 때마다 application-secret.yml 파일을 echo 명령으로 만들어 설정을 생성하고 있었다. 그런데 매번 덮어쓰는 게 아니라 >> 연산자를 사용하다 보니, 같은 spring: 키가 계속 아래
MDC는 요청별 로그 흐름을 구분할 수 있도록 도와주는 로깅 컨텍스트이다. 멀티스레드 환경에서 각 요청은 별도의 스레드에서 처리되기 때문에 MDC는 내부적으로 ThreadLocal<Map<String, String>> 형태로 동작하며 현재 스레드에 컨텍스트
기존에는 accessToken, refreshToken을 UserController에서 직접 HttpServletResponse를 통해 헤더에 수동으로 설정하고 있었다.하지만 이 방식은 Controller가 Servlet API에 강하게 의존하게 되며 관심사 분리가 잘
API 문서를 테스트 기반으로 자동 생성해주는 도구이다. Swagger처럼 어노테이션 기반이 아니라, 실제 API 요청/응답을 테스트하면서 정확한 문서 조각을 생성하는 게 특징이다.벡엔드와 프론트엔드 협업 시 신뢰할 수 있는 API 명세서를 제공한다.테스트 코드 작성만
❓AOP란? AOP(Aspect-Oriented Programming)는 "공통된 관심사"를 핵심 로직에서 분리해서 재사용할 수 있도록 도와주는 관점 지향 프로그래밍이다. Aspect : 반복 로직을 담는 클래스 Target : Aspect를 적용하는 곳 Advice
프로젝트에서 외부 쇼핑몰 API(Naver 쇼핑 오픈API)를 연동한 NaverApiClient 클래스를 구현했고 이 클래스에 대한 단위 테스트를 작성했다. @SpringBootTest를 붙여 통합 테스트로 구성하는 대신 Mockito를 활용한 순수 단위 테스트로 작성
Spring Web 애플리케이션을 개발하다 보면 공통적으로 처리해야 할 기능이 생긴다. 예를 들어 로그인 검증, 요청/응답 로깅, 요청 시간 측정, 트랜잭션 처리 등은 서비스 로직과는 별개로 공통 처리가 필요한 기능이다. 이럴 때 Spring에서는 크게 Filter와
서블릿(Java Servlet)이란? 자바를 사용하여 웹 페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 사양을 말하며 흔히 "서블릿"이라 불린다. 자바 서블릿은 웹 서버의 성능을 향상 시키기 위해 사용되는 자바 클래스의 일종이다. 즉, 서블릿(Servlet)은 클
Spring에서 @Transactional(readOnly = true)를 자주 보긴 했지만 단순히 “조회 전용이라서 쓴다”는 정도의 인식만 있었고 왜 그렇게 써야 하는지, 정확히 어떤 최적화가 발생하는지, 주의할 점은 무엇인지 깊이 이해하지 못한 채 넘겨왔다. 그러다
서비스를 운영하다 보면 서버를 재시작하거나 종료해야 하는 순간이 오기 마련이다. 이때 진행 중이던 요청을 중단하지 않고 마무리까지 처리한 뒤 안전하게 종료하는 방식이 바로 Graceful Shutdown이다. 왜 필요한가? Graceful Shutdown이 구현되지
웹 애플리케이션을 배포할 때 우리는 흔히 JAR 또는 WAR 형식으로 빌드한다. 대부분은 Spring Boot 프로젝트를 jar로 패키징해 배포하지만 일부 기업에서는 여전히 war 방식을 고수하기도 한다. 그래서 JAR와 WAR는 어떤 것이고 어떤 차이점이 있는지 작성