DB 정적 데이터, Enum 타입을 활용하여 SQL 질의 간소화하기
사이드 프로젝트를 진행하면서 Enum 타입을 통해 데이터베이스 질의를 줄여 성능을 최적화한 이야기를 해보자 합니다.
현재 원티드 채용 플랫폼에서 최신 Job Description(JD) 정보를 스크래핑하고, 각 JD에서 개발자에게 요구하는 기술 스택 목록을 추출 및 인기있는 기술을 분석하여 해당 기술스택에 대한 맞춤형 강의영상을 제공하는 주제의 사이드 프로젝트를 진행 중입니다.
일관된 데이터를 저장하기 위한 데이터베이스 설계
데이터베이스에 각 원티드 JD의 정보, 기술 스택, 그리고 JD와 기술 스택을 연결하는 매핑 정보를 저장하기 위해 다음과 같은 ERD 설계를 수행했습니다.
(기술스택 테이블에 서비스에서 사용될 기술스택을 사전에 저장했습니다.)
- 추출한 JD의 상세정보는 원티드JD 테이블에 저장
- 추출한 JD와 기술 스택(사전에 정의)을 연결하는 매핑 정보는 원티드 JD 기술스택 테이블에 저장
- 추출한 JD 상세 정보에서 가져온 모든 기술스택은 기술스택 히스토리테이블에 저장
원티드 JD에서 추출된 기술 스택이 skill 테이블에 존재한다면 해당 키워드 레코드의 기본 키(PK)를 사용하고, 그렇지 않다면 ‘기타’ 키워드가 있는 레코드의 PK를 사용하도록 설계하였고 서비스에서는 skill 테이블의 통일된 기술 스택 데이터를 관리할 수 있었습니다.
- JD에서 가져온 기술 스택이 skill 테이블에 매핑되어 있으면 해당 기술 스택에 대한 PK를 사용하여 일관성 있게 데이터를 관리
- JD에서 가져온 기술 스택이 skill 테이블에 매핑되어 있지 않다면 "기타"로 처리하여 데이터 유실을 방지
skill_history 테이블에는 각 JD에서 추출된 모든 기술 스택이 기록됩니다.
skill 테이블과 skill_history 테이블을 조인하여 '기타'로 표시된 기술 스택이 어떤 것인지 확인할 수 있고 정기적으로 skill_history 테이블을 검토하여 '기타'로 분류된 기술 스택 중 빈도가 높은 것을 식별할 수 있었습니다.
또한 '기타'로 분류되었지만 실제로는 인기 있는 기술 스택으로 판단되는 항목을 조회할 수 있도록 설계하였습니다.
이를 통해 데이터의 일관성을 유지하면서도 놓치지 않고 유용한 통계 정보를 추출할 수 있게 되었습니다
저장된 데이터 예시보기
DB 정적 데이터, Enum 타입을 활용한 SQL 질의 간소화 및 성능 최적화 | Notion
저장된 데이터 예시 보기
olivine-wash-f6d.notion.site
기술스택 존재유무를 확인해야하는 SQL로 인한 성능 저하 발생
각 JD에서 추출한 기술 스택을 처리할 때마다, 해당 기술 스택이 skill 테이블에 존재하는지 확인하고, 존재한다면 그대로 사용, 존재하지 않다면 '기타'로 처리함에 따라 매번 데이터베이스를 조회해야하는 하는 문제가 발생했습니다.
특히, 소량의 JD를 스크래핑 하더라도 추출하는 기술스택이 많다면 비즈니스 로직 처리 속도 지연되었습니다.
따라서 정적으로 정의된 기술 스택은 데이터베이스를 조회하지않고 서버 내 메모리에서 처리할 수 있도록 Enum 클래스 도입을 고려하게 되었습니다.
Enum 클래스로 서버에서 존재유무 확인으로 문제 해결
Enum 타입을 사용하여 기술 스택을 서버 내 메모리에서 관리하면서 데이터베이스 조회를 최소화하게된 방법은 다음과 같습니다.
Enum 클래스 정의
public interface SkillType {
String getKeyword();
static String getOrderKeyword() {
return "기타";
}
}
@AllArgsConstructor
public enum BackendSkillType implements SkillType {
AWS("AWS"),
GIT("Git"),
PYTHON("Python"),
// ...
private String keyword;
@Override
public String getKeyword() {
return keyword;
}
}
- 데이터베이스 레코드와 동일하게 설정.
JD 처리 시 Enum 사용
// Enum 클래스에 포함되어있는지 확인
boolean isSkillInJobPosition = Arrays.stream(BackendSkillType.values())
.anyMatch(skillType -> skillType.getKeyword().equalsIgnoreCase(BackendSkillType.values()));
// 포함되어있다면
if (isSkillInJobPosition) {
BackendSkillType matchedSkillType = Arrays.stream(BackendSkillType.values())
.filter(skillType -> skillType.getKeyword().equalsIgnoreCase(skillKeyword))
.findFirst()
.get();
// 포함되어있는 기술스택 keyword
String keyword = matchedSkillType.getKeyword();
}
→ JD의 기술스택을 처리할 때, Enum 클래스 사용하여 서버 내에서 기술 스택을 조회하고 처리하기 때문에 DB를 조회하지 않아 성능 향상
Enum과 데이터베이스 동기화
데이터베이스에 존재하는지를 Enum 클래스로 확인하기 위해서는 Enum의 상수와 skill 테이블의 데이터를 동일하게 설정 합니다.
이를 통해 정적으로 정의된 기술 스택은 메모리에서 빠르게 사용할 수 있었습니다.
후기
이번 사례에서는 최대한 기존의 설계에서 변경없이 성능을 최적화하고자 Enum 클래스를 도입하였습니다.
이전에는 Enum 클래스를 비즈니스 로직에서의 상태표현 정도로만 사용했었는데 이번 경험을 통해서 Enum으로 정적인 데이터를 관리하여 성능을 최적화하거나 설정 값을 관리하는 등 다양한 상황에서 활용할 수 있는 강력한 도구임을 알 수 있었습니다.
앞으로 상황에따라 Enum 타입을 적용함으로써 코드의 가독성, 안정성, 유지보수성을 향상시킬 수 있을 것으로 기대됩니다.