Stay Hungry Stay Foolish
728x90

분류 전체보기 494

[구현 기록] CustomException + ErrorCode 구조 설계

BACKENDCustomException + ErrorCode 구조 설계목차1. 배경2. 전체 구조3. ApiResponse — 공통 응답 래퍼4. ErrorCode — 에러 중앙 관리5. CustomException — 비즈니스 예외6. GlobalExceptionHandler — 전역 예외 처리7. 실제 동작 흐름8. 정리Spring Boot 프로젝트에서 예외 응답 형식을 통일하기 위해 CustomException, ErrorCode, GlobalExceptionHandler 구조를 설계했다.1. 배경Spring Boot 프로젝트에서 예외 처리를 별도로 설계하지 않으면 여러 문제가 생긴다.서비스 레이어마다 예외 처리 방식이 달라진다.에러 메시지를 문자열로 직접 작성하면 오타가 생기거나 일관성이 깨진다..

[설계의사결정] 시리즈 목록

ARCHITECTURE[설계 의사결정] 시리즈 목록단순히 기능을 구현하는 것보다 더 중요했던 건 “왜 이 방식을 선택했는가?”에 대한 고민이었다.목차1. 이미지 업로드 정책 결정 과정2. 페이지네이션 방식 선택 과정3. 독서 리마인더 알림 구현 방식 선택 과정4. 국내 도서 검색 API 선택 과정5. JWT + Redis 인증 설계이 시리즈는 Booktine 개발 과정에서 실제로 고민했던 설계 선택 과정들을 정리한 글이다. 단순 구현 방법보다는 “왜 이 구조를 선택했는가”를 중심으로 기록했다.01이미지 업로드 정책 결정 과정Booktine에는 책 표지 이미지와 프로필 이미지 두 가지 이미지가 존재한다. 이미지를 저장하는 방식으로 외부 URL 직접 저장, 서버에서 S3 재업로드, Presigned URL을..

[설계의사결정] JWT + Redis 인증

AUTHJWT + Redis 인증 설계 - 세션 대신 JWT를 선택한 이유목차1. 배경2. 인증 방식 비교3. 세션을 선택하지 않은 이유4. 결정 — JWT + Redis5. JWT의 한계Booktine은 로그인 기반 기능이 많은 서비스다. 따라서 인증 구조를 어떻게 설계할지가 서비스 전체 구조에 큰 영향을 줬다.1. 배경Booktine은 로그인한 사용자만 이용할 수 있는 기능이 많다. 독서 기록 작성, 메모, 진행률 관리 등 대부분의 핵심 기능이 인증을 전제로 한다. 따라서 어떤 방식으로 인증을 처리할지가 중요한 설계 결정 중 하나였다. 핵심 기준은 다음과 같았다.서버 확장성프론트엔드(React)와의 연동 편의성구현 복잡도 2. 인증 방식 비교방식설명확장성구현 난이도세션서버 메모리에 인증 정보를 저장..

[프로젝트 개요] 프로젝트 소개 및 기획

목차프로젝트 소개기획 배경서비스 목표타겟 사용자기능 범위 결정 과정개발 일정 설계주요 기능기술 스택BackendFrontendInfra시스템 아키텍처ERD프로젝트 소개 GitHub 바로가기 기획 배경평소 독서를 좋아하고 읽은 책을 기록하는 습관이 있었다. 그런데 막상 꾸준히 기록하려고 하면 마땅한 공간이 없었다. 메모 앱, 노트, 사진 등 여러 곳에 나눠서 적다 보면 어느 순간 흐름이 끊기고 기록 자체를 포기하게 된다. 기록은 있는데 한눈에 보이지 않으니 내가 얼마나 읽었는지, 어떤 책을 좋아하는지도 파악하기 어렵다. 그러다 문득 "내가 원하는 대로 직접 만들면 되겠다"는 생각이 들었다. 마침 백엔드 개발자를 목표로 하고 있었고, 내가 실제로 쓰고 싶은 서비스를 만드는 게 가장 좋은 공부라고 생각했다...

[설계의사결정] 국내 도서 검색 API 선택 과정

PROJECT국내 도서 검색 API 선택 과정목차1. 왜 도서 API를 비교하게 됐나?2. 국내에서 사용 가능한 도서 API3. API별 비교4. 알라딘 Open API5. 카카오 책 검색 API6. 네이버 책 검색 API7. 국립중앙도서관 Open API8. 도서관 정보나루 API9. 최종 선택: 알라딘 API10. 마무리독서 습관 관리 서비스를 개발하고 있는데 “도서 데이터를 어디서 가져올 것인가?” 에 대한 고민이 생겼다.1. 왜 도서 API를 비교하게 됐나?처음에는 단순히 제목만 검색되면 될 줄 알았다. 그런데 막상 구현하려고 보니 생각보다 고려해야 할 요소가 많았다.표지 이미지 제공 여부신간 / 베스트셀러 데이터 제공 여부가격 정보 제공 여부JSON 지원 여부API 관리 상태키 발급 속도특히 독..

[Infrastructure] Spring Boot × Docker × AWS 배포 흐름 한 번에 이해하기

DEPLOYMENTSpring Boot 앱을 Docker로 AWS에 배포하는 전체 흐름 정리목차Docker가 왜 필요한가?Docker와 AWS의 차이AWS 서비스 역할 정리전체 아키텍처 흐름Dockerfile 작성과 배포배포 방식 비교마치며Docker와 AWS를 처음 접하면 가장 헷갈리는 부분이 있다. “Docker를 쓰는 건가? AWS를 쓰는 건가?” 이 둘의 관계부터 실제 배포 흐름까지 한 번에 정리해보자. Docker가 무엇인지 알고 싶다면 👇 Docker📋 목차도커란?핵심 개념VM과 Docker 차이배포한다고 가정할 때기본 명령어참고 링크📌 도커란?컨테이너 기반 가상화 도구 (2013년 등장)리눅스의 프로세스 격리 기술을 활용해 앱 실행 환경을 컨dev-cloud.tistory.com1. ..

[Web] REST API, RESTful API 개념

WEBREST API, RESTful API 개념과 차이목차1. API2. REST3. REST API vs RESTful API4. REST API 설계 방법5. HTTP 상태 코드도 중요하다6. 마치며백엔드 공부를 시작하면 가장 먼저 마주치는 단어, REST API. 근데 RESTful API는 또 뭔가? 같은 건가 다른 건가? 오늘 한 번에 정리해보자.1. APIREST API를 이해하려면 먼저 API가 뭔지 알아야 한다. API(Application Programming Interface)란, 서로 다른 소프트웨어가 서로 통신할 수 있도록 정해놓은 인터페이스다. 쉽게 말하면, 클라이언트(프론트엔드, 앱 등)가 서버에게 “이 데이터 줘” 하고 요청하고, 서버가 “여기 있어” 하고 응답하는 그 창구가..

🌐 CS & Infra/Web 2026.05.08

[Kotlin] 코틀린 개요

KOTLIN코틀린(Kotlin) 개요목차1. 코틀린이 무엇인가?2. 왜 Kotlin을 쓰는가?3. 어디에 쓰이나?4. 자프링 vs 코프링5. 어떤 걸 선택해야 할까?6. 마치며Java는 들어봤는데, Kotlin은 뭔가요?요즘 Android 개발이나 백엔드에서 심심찮게 보이는 그 언어, 오늘 제대로 알아보자.1. 코틀린이 무엇인가?코틀린(Kotlin)은 JetBrains가 만든 정적 타입 프로그래밍 언어다. 2016년에 공식 출시됐고, 2017년에는 구글이 Android 공식 개발 언어로 채택하면서 폭발적으로 주목받았다. 가장 큰 특징은 Java와 100% 호환된다는 점이다. Kotlin 코드는 JVM 위에서 동작하기 때문에, 기존 Java 라이브러리를 그대로 사용할 수 있고, 하나의 프로젝트 안에서 Ja..

☕ Backend/Kotlin 2026.05.08

[리팩토링] 유지보수성을 높이기 위한 가독성 리팩토링 기록

REFACTORING중복 코드와 매직 스트링 제거로 가독성 개선하기목차1. 왜 가독성 리팩토링을 했는가2. 공통적으로 발견한 문제 패턴3. 구체적인 개선 사례4. 돌아보며1. 왜 가독성 리팩토링을 했는가기능 구현이 마무리된 시점에 전체 코드를 다시 훑어봤다. 동작에는 문제가 없었지만 군데군데 읽기 불편한 지점들이 눈에 띄었다.컨트롤러마다 SecurityUtils.getCurrentUserId()를 반복 호출하고 있었다.인증 목적을 나타내는 문자열이 상수가 아닌 리터럴로 여기저기 흩어져 있었다.하나의 메서드가 너무 많은 일을 하고 있어서 흐름을 파악하려면 한참 읽어야 했다.기능 개발 중에는 “일단 돌아가게” 하는 것이 우선이다 보니 이런 부분들이 자연스럽게 쌓인다. 하지만 이런 코드를 그대로 두면 나중에 ..

카테고리 없음 2026.05.07

[트러블슈팅] JWT secret 키 길이 부족으로 인한 WeakKeyException

TROUBLESHOOTINGJWT secret 키 길이 부족으로 인한 WeakKeyException 해결목차1. 구현 배경2. 문제 상황3. 원인4. 해결5. 왜 시작 시점에 터지는가6. 배운 점1. 구현 배경JWT 기반 인증 시스템을 구현했다. JwtProvider에 @PostConstruct로 init() 메서드를 작성해 애플리케이션 시작 시 secret 키를 초기화하도록 했고, application.yml에 jwt.secret 값을 설정했다.JWT 서명에는 secret 키가 사용된다. 이 키는 토큰이 변조되지 않았는지 검증하는 기준이 되기 때문에, 사용하는 알고리즘이 요구하는 최소 길이를 만족해야 한다.2. 문제 상황애플리케이션을 실행하자마자 서버가 시작되지 않았고, jwtProvider 빈 생성 ..

[트러블슈팅] 커뮤니티 좋아요 상태 불일치로 인한 409 오류

TROUBLESHOOTING커뮤니티 좋아요 상태 불일치로 인한 409 오류목차1. 문제 상황2. 원인 분석3. 해결 방법4. 적용 결과5. 배운 점1. 문제 상황커뮤니티 게시글에서 좋아요 버튼을 클릭했을 때 간헐적으로 409 Conflict 오류가 발생했다.처음에는 동시에 같은 요청이 여러 번 발생하는 동시성 문제를 의심했다. 하지만 재현 조건을 확인해보니 특정 상황에서 일관되게 발생하는 문제였다.커뮤니티 댓글창에서 좋아요 버튼을 클릭하는 화면좋아요 요청 이후 화면에서 확인된 409 Conflict 오류브라우저 개발자 도구 Console에서 확인한 좋아요 요청 실패 로그좋아요 요청 자체는 서버로 정상 전송되었지만, 서버 기준으로는 이미 좋아요가 존재하는 상태였기 때문에 중복 요청으로 판단되어 409 오류..

[리팩토링] JPA 인덱스 추가로 조회 성능 개선

REFACTORINGJPA 인덱스 추가로 조회 성능 개선하기목차1. 작업 배경2. 점검 기준3. 인덱스 적용 전 확인4. 적용 내용5. 적용 후 확인6. 참고7. 배운 점1. 작업 배경인덱스는 DB가 데이터를 조회할 때 전체 테이블을 스캔하지 않고, 빠르게 원하는 행을 찾을 수 있도록 도와주는 자료구조다. WHERE 조건으로 자주 사용되는 컬럼에 인덱스가 없으면, 데이터가 많아질수록 조회 성능이 급격히 저하될 수 있다. 리팩토링 단계에서 쿼리 로그를 확인하던 중 자주 조회되는 컬럼에 인덱스가 적용되지 않은 것을 발견했고, 조회 성능 개선을 위해 인덱스를 추가했다.이번 작업의 핵심은 모든 컬럼에 무작정 인덱스를 추가하는 것이 아니라, 실제 조회 조건에 자주 사용되는 컬럼을 기준으로 필요한 인덱스만 선택하는..

[트러블슈팅] H2 예약어 컬럼명으로 인한 테이블 생성 실패 및 InitData 오류

TROUBLESHOOTINGH2 예약어 컬럼명으로 인한 테이블 생성 실패 및 InitData 오류목차1. 발생 배경2. 문제3. 원인 파악 과정4. 해결5. 참고6. 배운 점1. 발생 배경리팩토링 단계에서 로컬 환경 통합 테스트를 위해 InitData를 작성했다. InitData는 애플리케이션 실행 시 테스트용 데이터를 DB에 자동으로 insert해주는 클래스다. H2 인메모리 DB를 사용하는 로컬 환경에서는 애플리케이션을 실행할 때마다 데이터가 초기화된다. 매번 수동으로 테스트 데이터를 넣는 번거로움을 줄이기 위해 InitData를 작성했는데, 이후 애플리케이션 실행 시 monthly_goals 테이블을 찾지 못한다는 오류가 발생했다.처음에는 InitData 실행 시점이 테이블 생성보다 빨라서 생긴 문..

[프로젝트] POSTMAN에서 JWT 토큰 자동 저장 및 요청에 자동 적용하는 방법

PROJECTPostman에서 JWT 토큰 자동 저장 및 적용 설정목차1. 개요2. 배경 지식3. 설정 방법4. Refresh Token 처리5. 참고1. 개요로그인 API 호출 시 응답으로 내려오는 accessToken을 Postman 환경변수에 자동으로 저장하고, 이후 인증이 필요한 모든 API 요청에 자동으로 Bearer Token을 붙이는 설정 방법이다.이 설정을 해두면 매번 로그인 응답에서 토큰을 복사한 뒤, 다른 요청의 Authorization 헤더에 직접 붙여넣는 과정을 반복하지 않아도 된다.2. 배경 지식JWT & AccessToken이란?JWT(JSON Web Token)는 서버가 로그인한 사용자에게 발급하는 인증 토큰이다. 이 중 AccessToken은 실제 API 요청 시 로그인된 사..

[트러블슈팅] 로컬 환경 이메일 발송 스킵 조건 오류 해결

TROUBLESHOOTING로컬 환경에서 이메일 발송 스킵 미적용으로 인한 500 오류목차1. 발생 배경2. 문제3. 원인 파악 과정4. 해결5. 참고6. 배운 점1. 발생 배경이메일 인증 기능을 구현한 뒤 Postman으로 /auth/email/send API를 처음 테스트하는 과정에서 500 오류가 발생했다. 로컬 환경에서는 실제 Gmail SMTP로 이메일을 발송하지 않고, 인증 코드를 콘솔 로그로 확인하도록 처리하려고 했다. 하지만 의도와 달리 로컬 테스트 중 실제 Gmail SMTP 인증이 시도되면서 오류가 발생했다.이번 문제의 핵심은 이메일 발송 로직 자체보다, 현재 실행 중인 Spring Profile과 이메일 발송 스킵 조건이 맞지 않았다는 점이다.2. 문제이메일 인증 코드 발송 API를 ..

728x90