| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
- string
- 인텔리제이
- vscode
- html
- 정규식
- HashMap
- CSS
- ArrayList
- SpringBoot
- Array
- IntelliJ
- 자바문법
- junit5
- 자바
- 자바스크립트
- java테스트
- 배열
- 스프링부트
- Java
- math
- input
- 문자열
- js
- Visual Studio Code
- junit
- 단위테스트
- list
- javascript
- Eclipse
- 테스트자동화
- Today
- Total
목록IT/SpringBoot (67)
어제 오늘 내일
지난 시간, GitHub Actions로 자동 배포까지 성공했습니다. 하지만 치명적인 단점이 하나 있었죠."배포하는 동안에는 서비스가 멈춘다(Downtime)."이걸 해결하려면 서버를 두 대 띄우고 교대로 배포해야 하는데, 그러려면 사용자의 요청을 이리저리 토스해 줄 문지기가 필요합니다. 오늘 소개할 Nginx가 바로 그 주인공입니다.1. 리버스 프록시(Reverse Proxy)가 뭔가요?이름이 어렵지만 원리는 간단합니다.클라이언트(사용자)가 스프링 부트 서버(8080 포트)에 직접 붙는 게 아니라, Nginx(80 포트)에게 먼저 요청을 보내고, Nginx가 뒤에 있는 스프링 부트에게 대신 전달하는 구조입니다.왜 이렇게 쓰나요?무중단 배포: A 서버가 배포 중이면 B 서버로 요청을 보내면 됩니다.보안:..
지난 시간에는 GitHub가 우리 코드를 대신 빌드해 주는 것까지 성공했습니다.하지만 빌드된 파일(jar)이 GitHub 서버에만 있으면 아무 소용 없겠죠? 이걸 우리의 진짜 서버(AWS EC2)로 옮겨서 실행시켜야 합니다.오늘은 appleboy라는 아주 유명한 액션을 사용해서 파일 전송(SCP)과 명령어 실행(SSH)을 자동화해 보겠습니다.1. 준비물: AWS EC2와 Key 파일당연히 서버가 있어야겠죠? AWS EC2 인스턴스 (Ubuntu 추천) 접속용 키 파일 (.pem): 서버 만들 때 받은 그 파일입니다. 절대 잃어버리면 안 됩니다! Java 설치: 서버에 미리 자바를 설치해 두세요. # (EC2 터미널에서)sudo apt updatesudo apt install openjdk-17-jd..
혹시 아직도 배포할 때마다 이런 과정을 반복하고 계신가요? 로컬에서 ./gradlew build 실행 (한참 기다림) FTP나 SCP로 서버에 jar 파일 전송 서버 접속해서 기존 프로세스 죽이고(kill), 다시 실행(java -jar) 이 과정은 귀찮기도 하지만, 사람이 하기 때문에 반드시 실수가 발생합니다. 오늘은 이 과정을 로봇에게 맡기는 CI(Continuous Integration, 지속적 통합)를 GitHub Actions로 구현해 보겠습니다.1. CI/CD가 도대체 뭔가요?CI (Continuous Integration): "지속적 통합"개발자가 코드를 합칠(Merge) 때마다, 자동으로 빌드하고 테스트해서 "이 코드 문제없어!"라고 검증하는 과정입니다.CD (Continuous De..
"개발 끝났다!" 하고 좋아하기엔 이릅니다. 진짜 끝은 서버에서 돌아가는 것을 확인해야 끝이죠.Spring Boot가 혁명적인 이유는 바로 내장 톰캣(Embedded Tomcat) 덕분입니다. 서버를 설치하는 게 아니라, 서버를 내 코드 안에 넣어버리는 것이죠.이 모든 것을 가능하게 하는 실행 가능한 Jar(Executable Jar)의 비밀과 빌드 방법을 알아보겠습니다.1. 일반 Jar vs 실행 가능한 Jar (Fat Jar)우리가 평소에 라이브러리로 쓰는 Jar 파일과 Spring Boot가 만드는 Jar 파일은 다릅니다. 일반 Jar (Skinny Jar): 내가 짠 코드(.class)만 들어있습니다. 이것만으로는 실행 못 합니다. (의존성 라이브러리가 없으니까요) 실행 가능한 Jar (Fat..
여러분, 혹시 이런 코드를 짜보신 적 있나요?public void join(Member member) { long start = System.currentTimeMillis(); // 1. 시작 시간 측정 try { memberRepository.save(member); // 핵심 로직 (이거 하나만 진짜임!) } finally { long finish = System.currentTimeMillis(); // 2. 종료 시간 측정 long timeMs = finish - start; System.out.println("join = " + timeMs + "ms"); // 3. 로그 출력 }}회원 가입, 조회, 수정... 모든 메서드..
웹 개발을 하다 보면 "모든 요청에 대해 로그를 남겨라", "로그인 안 한 사용자는 튕겨내라" 같은 요구사항을 받게 됩니다.이걸 모든 컨트롤러 메서드에 복사-붙여넣기 하실 건가요? 절대 아니죠.스프링 부트에는 요청을 중간에 가로채서 처리하는 강력한 도구 두 가지가 있습니다. 바로 필터(Filter)와 인터셉터(Interceptor)입니다. 둘 다 비슷해 보이지만, 활동 구역과 권한이 완전히 다릅니다.1. 웹 컨테이너의 문지기: 필터 (Filter)필터는 스프링(Spring) 영역 밖, 즉 웹 컨테이너(Tomcat) 영역에서 동작합니다.위치: 요청이 DispatcherServlet에 도착하기도 전에 가장 먼저 실행됩니다.특징: 스프링과 무관한, 날것 그대로의 HTTP 요청/응답을 조작할 수 있습니다.주요 ..
안녕하세요! 개발자의 귀차니즘을 해결해 주는 IT 블로거입니다.API 문서는 개발자에게 계륵 같은 존재입니다. 없으면 협업이 불가능하고, 있으면 관리하기 너무 귀찮으니까요. 그래서 우리는 문서 자동화 도구를 사용합니다.스프링 부트 진영에는 두 가지 강력한 도구가 있습니다.Swagger (Springdoc): "쉽고 빠르고 예쁘다!" (Annotations 기반)Spring REST Docs: "테스트를 통과해야만 문서가 나온다!" (Test 기반)과연 우리 팀에는 무엇이 맞을까요?1. 쉽고 화려한: Swagger (Springdoc)가장 많이 쓰이는 도구입니다. 예전엔 springfox를 썼지만, 지금은 업데이트가 멈춰서 springdoc-openapi 라이브러리를 사용합니다.장점: 설정이 3분 컷!bu..
지난 시간에는 가짜 객체(Mock)를 써서 빠르게 로직만 검증하는 '단위 테스트'를 배웠습니다. 하지만 실무에서는 이런 일이 종종 발생합니다."테스트 코드는 다 통과했는데, 막상 서버 띄우니까 에러가 나요!" 😭이유는 간단합니다. SQL 쿼리가 틀렸거나, DB 연결 설정이 잘못되었기 때문입니다. 이런 문제는 Mock 객체로는 절대 찾을 수 없습니다.오늘은 스프링 컨테이너를 진짜로 띄워서 처음부터 끝까지 테스트하는 @SpringBootTest와, 테스트용 DB인 H2를 활용하는 방법을 알아보겠습니다. 1. 통합 테스트란?단위 테스트가 '부품 검사'라면, 통합 테스트는 '조립 검사'입니다.단위 테스트: MemberService만 떼어내서 테스트 (가짜 DB 사용) -> 빠르지만 실제 환경과 다름.통합 테..
"바빠서 테스트 짤 시간이 없어요."라는 핑계, 많이 들어보셨죠? 하지만 테스트 코드가 없는 코드는 '레거시(Legacy)'일 뿐입니다. 테스트가 없으면 리팩토링도, 기능 추가도 무서워서 못 하게 되니까요.오늘은 스프링 부트 테스트의 양대 산맥, JUnit5(실행기)와 Mockito(가짜 객체)를 사용해 서비스 계층(Service Layer)을 테스트하는 방법을 알아보겠습니다. 1. 단위 테스트(Unit Test)란?"딱 하나(Unit)만 격리해서 테스트한다"는 뜻입니다.우리가 MemberService를 테스트하고 싶은데, 이 서비스가 MemberRepository를 통해 진짜 DB에 접근한다면?테스트가 느려집니다. (DB 통신)데이터가 꼬입니다. (테스트할 때마다 DB 초기화 필요)결론: 서비스 로직..
DB를 다루는 애플리케이션에서 가장 중요한 것은 속도가 아니라 신뢰성입니다.A가 B에게 100만 원을 송금하는 로직을 짰다고 가정해 봅시다.A의 계좌에서 100만 원 차감 (UPDATE)(여기서 서버 전원 꺼짐 💥)B의 계좌에 100만 원 입금 (UPDATE)트랜잭션이 없다면 100만 원은 공중분해 됩니다. 이런 일을 막기 위해 "모두 성공하거나, 아니면 아예 없던 일로 하거나(All or Nothing)"를 보장해 주는 것이 바로 트랜잭션입니다. 1. 스프링은 어떻게 트랜잭션을 거나요? (AOP와 프록시)스프링에서 트랜잭션을 적용하는 방법은 너무나 간단합니다. 메서드나 클래스 위에 @Transactional만 붙이면 끝이죠.@Servicepublic class TransferService { ..
