목록전체 글 (107)
신비한 개발사전
간단한 콘솔 기반 자바 애플리케이션을 빌드해서 java -jar로 실행하려고 했을 때 일어난 일이다. "./build/libs/java-janggi-1.0-SNAPSHOT.jar에 기본 Manifest 속성이 없습니다." 오류 메세지가 뜨면서 애플리케이션이 실행되지 않았다. 이 한 줄 외에 다른 정보는 없었다. 무엇이 문제였나?우리가 코딩한 자바 애플리케이션은 JVM이 실행해준다. 이때 JVM은 애플리케이션의 entrypoint, 즉 진입점을 알아야 한다. 어느 클래스에 구현된 main() 함수를 실행시켜야 이 애플리케이션이 우리가 설계한 대로 동작할지 JVM은 알 수 없기 때문에, 우리가 명시적으로 알려줘야 한다. 그리고 그 방법은 이정표 역할을 하는 manifest 파일(MANIFEST.MF)에 Ma..
개요사용자의 출발지점에 따라 만날 장소를 추천해주는 모잇지 서비스는 다양한 외부 API를 사용하고 있다. 공공데이터포털의 OpenAPI로부터 철도 정보를 받아오고, LLM 모델에 장소 추천을 받기 위해 Gemini와 Perplexity의 API를 쓴다. 거기에 더불어 사용자들이 방문해볼 만한 장소를 보여주기 위한 Naver API까지.. 외부 API 호출로 시작해 또다른 외부 API 호출로 끝나는 로직이 구현돼있다. 외부 API는 우리가 제어하는 영역 밖이며, 응답하는 포맷 또한 제각각이다. 사용자 입장에서 예측하기 어려운 정책 변경도 무시할 수 없을 것이다. 외부와 통신하는 부분을 코어 비즈니스 로직에서 최대한 선명하게 분리해두고, 변동사항이나 응답 실패에 최대한 방어하거나 쉽게 갈아끼울 수 있도록 설..
1편: https://dydk1215.tistory.com/266 지난번, 서버 애플리케이션이 돌아가고 있는 EC2 인스턴스에서 로그 파일이 없어지는 현상을 보고 auditd를 설치했었다. auditd는 디렉토리나 파일에 대한 변경사항을 감지해 어떤 이벤트가 발생했는지 파악할 수 있는 툴이다. auditd 설치 후 드디어 로그 파일 삭제 이력이 기록으로 남아서 그 결과를 정리해봤다. 이벤트 분석auditd 로그에 아래와 같은 이벤트가 여러번 발생했다. /usr/bin/git clean -ffdx 명령어가 실행됐고, 그 결과 backend 디렉토리는 물론 frontend 디렉토리까지 파일 삭제 작업이 진행됐던 것이다. 삭제된 파일마다 동일한 이벤트 메타 데이터가 로깅됐다. 아쉽게도 해당 명령어를 실행시킨..
CloudWatch에 한동안 잘 뜨고 있던 로그가 어느 순간을 기점으로 뚝 끊겨있었다. EC2에 접속해 확인해보니, 백엔드 디렉토리 안에 뒀던 logs 폴더가 사라져있었다. 로그 디렉토리가 어쩌다 사라졌을까? 당연하게도 팀원 중 누구도 디렉토리를 지우지 않았을 뿐더러, 지울 이유도 없었다. logs 외에 build 폴더도 없어졌길래 처음엔 빌드 실패 때문일지 의심했다. 우리 CI/CD 파이프라인은 ./gradlew clean build 명령어를 호출하고 있었기 때문에, clean으로 인해 build 폴더를 삭제한 상태로 빌드를 시작한다. 다만 빌드 과정에서 logs 폴더는 건드릴 일이 없으니, clean build가 원인일 리 없었다. 문제를 어디서부터 해결하면 좋을지 고민하다가, 파일이나 디렉토리에 대..
우여곡절 끝에 팀 프로젝트에 적용한 CloudWatch 지표와 로그 모니터링이 잘 돌아가고 있음을 확인하고, 더이상 인프라를 건드릴 일은 없을 거라며 뿌듯해하고 있을 때쯤이었다. 어느날 CloudWatch에서 운영환경 서버에 찍힌 로그들을 살펴보니 이상한 요청들이 기록돼있는 것을 알게 됐다. 당연히 우리가 구현한 API 중에 "/schar-papushak"이란 것은 없다. 팀원이나 일반 사용자 중 그 누구도 저런 엔드포인트에 접근하려고 하지 않았을 텐데, 접근 기록이 남아있다. 뿐만 아니라 "/assets" 나 "/v3" 등, 실제로 구현하진 않았지만 충분히 있을 법한 URL에도 접근하려 한 흔적이 있었는데, 요청한 URI와 호출 timestamp를 보고 누군가 자동화 프로그램으로 보낸 스팸 요청이라는 ..
자바 빌드 파일에 JUnit Jupiter와 JUnit Platform 의존성을 잘못 추가하면 생길 수 있는 문제와, 그런 문제를 해결한 과정을 통해 알게 된 것들을 정리해보려고 한다. 버전 불일치클론해온 모 프로젝트의 테스트 코드를 실행하자 콘솔창이 빨간 텍스트로 채워지면서 테스트가 시작도 못해보고 강제 종료되었다. 테스트 자체를 실행할 수 없는 문제는 지금까지 한 번도 겪어보지 못했는데, 심지어 콘솔창에 남는 오류 관련 정보가 없어서 따로 생성된 Test Summary 리포트 파일에 직접 들어가서 이슈를 파악해야 했다. Stack trace에는 아래와 같은 내용이 있었다.The following conflicting versions were detected:- org.junit.jupiter.api:..
WHERE 절은 SELECT 전에 처리되기 때문에 WHERE 절에서 alias를 사용할 수 없다. SQL 질의 처리 순서에 대해 학습하면서 알게 된 것 중에 가장 의아했던 문장이다. 문장의 내용과 반대되게 내가 직접 WHERE 절에서 alias를 쓴 기억이 있기 때문이다. 확인하기 위해 SQLite에서 아래 쿼리문을 실행해봤다.SELECT price AS pFROM "availabilities"WHERE p > 100LIMIT 10; WHERE 절에서 alias인 "p"로 조건을 붙여도 오류 없이 잘 동작하는 것을 볼 수 있다: 결론부터 말하자면, 이건 SQLite이 예외적으로 WHERE 절에서도 alias 사용을 허용하기 때문이다. 같은 맥락으로 MySQL에서도 동일하게 WHERE 절에 alias를 사..
서버 애플리케이션에서 찍는 로그를 AWS 콘솔에서 보기 위해 CW Agent를 EC2 인스턴스에 설치했다. CW Agent는 지정한 로그 파일의 내용을 읽어와 아마존 CloudWatch에서 볼 수 있도록 해준다. 공식 문서의 안내에 따라 내 EC2 인스턴스 운영체제에 맞는 CW Agent를 설치하고 돌리니 CloudWatch에 Logback으로 로깅한 기록이 뜨기 시작했다. 근데 이유를 알 수 없는 문제가 발생했다. 💥 CW Agent가 로그를 가져오는 timestamp 칼럼의 값들이 다 똑같이 찍힌다.. 처음엔 추적할 로그 파일이 이미 있는 상태에서 CW Agent가 가동하면 기존 로그들을 한꺼번에 읽어올 테니까 같은 시간으로 뜨는 거라고 생각했다. 그런데 이후에 새로 찍히는 로그의 timestamp..