전체 글

프로젝트

[부끄북극] 단일 테이블 전략의 문제와 엔티티 객체의 SRP

💡 발단 기능 소개 사이드 프로젝트에서 퀴즈 기능 구현을 맡게 되었습니다. 환경을 지키자는 의미에서 환경에 관련된 퀴즈들을 조회하고 맞춰보는 기능입니다. 퀴즈에는 OX 퀴즈와 객관식 퀴즈 두 가지가 있습니다. OX 퀴즈와 객관식 퀴즈의 차이는 선택지 필드의 유무입니다. OX 퀴즈는 문항이 O,X 두 개로 고정되지만 객관식 퀴즈는 여러 개의 선택지를 가지는 형태입니다. 🤔 엔티티 설계 과정 제가 1차적으로 어려움을 겪은 부분은 엔티티 객체 설계 과정입니다. 처음에는 Quiz 엔티티 하나만 만들 생각이었습니다. 퀴즈에 대한 타입을 두고 nullable한 필드들을 두어서 여러 종류의 퀴즈 정보를 담을 수 있도록 한 것입니다. @Getter @Entity @NoArgsConstructor(access = Acc..

Back-end/Spring Boot

[Spring Boot] 연관관계 생성 메서드 삽질

💡 발단 엔티티 생성자에서 정말 기본적인걸 놓치고 있었다. 1:N (일대다) 관계의 두 엔티티가 있었고, 나는 자식쪽에서 부모 엔티티만 연결해주고 있었다. 마치 레코드를 INSERT할 때 FK만 넣어서 참고하는 것처럼 말이다. 기존의 코드: 객관식 문제(Quiz)와 그 선택지(Choice)이다. 중요한 부분 외엔 생략, 단순화시켰다. // 문제쪽의 생성자 @Builder public Quiz(String properties, List choiceList) { this.properties = properties this.choiceList = choiceList; } // ... // 선택지쪽의 생성자 @Builder public Choice(String properties, Quiz quiz) { thi..

Back-end/Spring Boot

[Spring JPA] 실시간으로 적재되는 데이터와 부모 엔티티 묶어서 가져오기

💡 발단 프로젝트에서 맞닥뜨린 요구사항은 이렇다. 엔티티로는 로케이션이 있고, 각 로케이션에 대해서 서울시 인구 혼잡도 API로부터 5분마다 혼잡도 데이터를 적재한다. ex. 홍대입구역(id=3)에 대한 9시의 인구혼잡도가 2레벨(기획상 1~3으로 나뉜다)이라면 congestion(location_id=3, congestion_level=2, observed_at=2023-08-05 18:35:43.769817) 으로 저장된다. 나는 각 location별로 가장 최근의 혼잡도 (congestion)을 조회해야 했다. 아래 사진은 와이어프레임인데, 각 카드 하단의 '여유', '복쟉', '보통'이 각 로케이션의 가장 최근 혼잡도 레벨이다. '지하철'은 location_category에 해당. 💦 삽질 과정 ..

Back-end/Spring Boot

[Spring Boot] 스웨거 springdoc-openapi 적용 (webmvc-ui)

스웨거를 도입하게 된 이유 기존의 프로젝트에서는 노션으로 API 명세를 하고 있었다. API 내용을 일일이 쓰는게 꽤 오래걸리긴 하지만, 그만큼 상세하게 설명할 수 있어서 좋았다. 개발 전에는 프론트엔드와 크로스체킹까지 해서 누락되거나 기획상 틀린 정보가 거의 없었다. 문제는 개발을 하는중에 생겼는데, API 명세서와 다르게 응답값을 설정하는 일이 빈번하게 생겼던 것. 그래서 프론트엔드 팀원께서 많은 불편을 겪었다. 그래서 결국 스웨거를 적용하게 됐다. 해당 프로젝트의 Spring Boot 버전은 3.0이고 springfox가 아닌 springdoc-openapi를 의존한다. 생각보다 springdoc-openapi, 특히 webmvc-ui 버전을 적용하고 정리해놓은 블로그가 많이 없었다. 공식 문서까지..

Back-end/Spring Boot

[Spring Boot] 예외처리 야무지게 하기

🔍예외의 종류 예외처리를 알아보기 전에 예외의 종류부터 살펴보자. Unchecked Exception (RunTimeException) Exception Class의 서브 클래스 RuntimeException Class를 상속 Transaction으로 Rollback이 진행 됨 반드시 예외를 체크하지 않아도 되는 경우 사용합니다. 이처럼 명시적인 예외처리를 강제하지 않기 때문에 언체크 예외라고 부릅니다. 언체크 예외는 런타임 예외라고도 부릅니다. 체크 예외와는 달리 따로 처리하지 않아도 컴파일 에러가 발생하지 않습니다. 예외를 피할 수 있지만 개발자가 부주의해서 발생할 수 있는 경우를 위해 만든 예외입니다. 즉, 주로 프로그램 자체의 오류가 있을 때 발생하도록 의도됩니다. 대표적으로 NullPointer..

CS/자료구조 & 알고리즘

[Algorithm] DP

DP 란? DP는 특정한 알고리즘이라기보다 문제해결 패러다임으로 볼 수 있다. 큰 문제를 잘게 나눠서 결과를 저장해가며 그 답을 저장해두고 재활용한다. DP는 사실… 이론적으로는 별거 없다. 결국 풀이 경험이 중요하다…! 왜 쓸까? 피보나치 수열로 배워보자 일반적인 재귀를 사용할 때, 하나의 큰 문제를 풀기 위해 작은 문제들을 여러번 반복하기 때문에 비효율적일 때가 많다. 아래는 재귀호출 버전 피보나치의 호출 과정인데, 반복되는 호출이 꽤 많다. O(2^n)으로, n이 커질수록 기하급수적으로 커진다. def fibo(x): if x == 1 or x == 2: return 1 return fibo(x - 1) + fibo(x - 2) Top Down 방식 : 위의 항부터 큰 항부터 쪼개서 작은 문제로 나..

Back-end/DevOps

[DevOps] CI/CD 도입 전과 후 (깃허브 액션 + 도커)

잠깐, CI란? CI(Continuous Integration) : 지속적인 통합 (= 빌드, 테스트 자동화) CI가 필요한 환경 : 다수의 개발자가 형상관리 툴(git)을 사용해 공유 레포지토리에서 작업하는 환경 비정상적인 코드가 통합되는 것을 예방할 수 있다. 여러 명의 개발자가 동시에 관련된 코드 작업을 할 경우 발생하는 충돌 문제를 해결할 수 있다. 사실 충돌 문제 해결은 깃허브에서 자동으로 실행해주는 기능이다. (공포의 붉은색 conflict 문장) 내가 적용한건 주로 빌드 자동화이다. ✅ PR 생성시 빌드 테스트 자동화 PR을 생성한 뒤에 github에서 자동으로 빌드 테스트를 하도록 만들었다. 그리고 빌드 실패시엔 merge가 불가능하도록 설정했다. "All checks have passed..

CS/네트워크

[CS 네트워크] JWT와 클라이언트-서버 통신 흐름

❓ 왜 필요한데? 보안 문제그래서 유저를 식별할 수 있는 중요한 데이터를 토큰화시켜 주고받게 된다. 만약 서버와 클라이언트가 서로 유저 정보를 순수 JSON으로 보내게 되면, 이게 유효한 정보인지 확인할 방법이 없다. 만약 악의를 가진 공격자가 유저 ID를 바꿔서 요청을 했을 경우, 서버에선 무슨 일이 일어난 건지 알 방법이 없다. HTTP의 특징매번 사용자가 로그인을 하기는 너무 불편하고, 그렇다고 브라우저 스토리지에 아이디와 비밀번호 (인증 정보)를 넣자니 너무 위험하기 때문에, ‘인증 되었음’을 나타내기 위한 정보인 세션과 토큰이 등장했다. 기본적으로 HTTP 통신은 무상태(Stateless)이다. ❓ 세션에 비해 장점이 뭐지? : 세션 방식의 경우, 서버의 메모리에 저장된다는 것이 단점의 주 원인..

zorbathegeek
쓰기 전에 생각하자