From ffcceba7c1a03dc141be013d61e96b5a7216a57a Mon Sep 17 00:00:00 2001 From: JM Kim <106949557+CSE-Shaco@users.noreply.github.com> Date: Wed, 18 Mar 2026 13:02:44 +0900 Subject: [PATCH] feat: normalize and migrate majors to codes --- .../domain/auth/service/AuthService.java | 4 +- .../domain/game/service/GameUserService.java | 10 +- .../RecruitCoreApplicationService.java | 4 +- .../dto/request/RecruitMemberRequest.java | 5 +- .../member/service/RecruitMemberService.java | 4 +- .../domain/user/service/UserService.java | 4 +- .../gdgoc/global/util/MajorNormalizer.java | 125 +++++++++++ .../V20260318__normalize_major_names.sql | 203 ++++++++++++++++++ 8 files changed, 352 insertions(+), 7 deletions(-) create mode 100644 src/main/java/inha/gdgoc/global/util/MajorNormalizer.java create mode 100644 src/main/resources/db/migration/V20260318__normalize_major_names.sql diff --git a/src/main/java/inha/gdgoc/domain/auth/service/AuthService.java b/src/main/java/inha/gdgoc/domain/auth/service/AuthService.java index a30332dc..e9b68561 100644 --- a/src/main/java/inha/gdgoc/domain/auth/service/AuthService.java +++ b/src/main/java/inha/gdgoc/domain/auth/service/AuthService.java @@ -21,6 +21,7 @@ import inha.gdgoc.global.config.jwt.TokenProvider; import inha.gdgoc.global.config.jwt.TokenProvider.CustomUserDetails; import inha.gdgoc.global.security.AccessGuard; +import inha.gdgoc.global.util.MajorNormalizer; import java.io.IOException; import java.security.GeneralSecurityException; import java.time.Duration; @@ -51,6 +52,7 @@ public class AuthService { private final StringRedisTemplate redisTemplate; private final AccessGuard accessGuard; private final PasswordEncoder passwordEncoder; + private final MajorNormalizer majorNormalizer; @Value("${google.client-id}") private String googleClientId; @@ -112,7 +114,7 @@ public LoginSuccessResponse signup(SignupRequest request) { .email(request.getEmail()) .name(request.getName()) .studentId(request.getStudentId()) - .major(request.getMajor()) + .major(majorNormalizer.normalize(request.getMajor())) .phoneNumber(cleanPhone) .image(request.getImage()) // Role(GUEST), Status(PENDING) 등은 User 엔티티 생성자에서 기본값 처리됨 diff --git a/src/main/java/inha/gdgoc/domain/game/service/GameUserService.java b/src/main/java/inha/gdgoc/domain/game/service/GameUserService.java index 39aceddc..946644b2 100644 --- a/src/main/java/inha/gdgoc/domain/game/service/GameUserService.java +++ b/src/main/java/inha/gdgoc/domain/game/service/GameUserService.java @@ -4,6 +4,7 @@ import inha.gdgoc.domain.game.dto.response.GameUserResponse; import inha.gdgoc.domain.game.entity.GameUser; import inha.gdgoc.domain.game.repository.GameUserRepository; +import inha.gdgoc.global.util.MajorNormalizer; import jakarta.transaction.Transactional; import java.time.LocalDate; import java.time.LocalDateTime; @@ -18,11 +19,18 @@ public class GameUserService { private final GameUserRepository gameUserRepository; + private final MajorNormalizer majorNormalizer; @Transactional public List saveGameResultAndGetRanking(GameUserRequest gameUserRequest) { // 유저 정보 저장 - GameUser gameUser = gameUserRequest.toEntity(); + GameUser gameUser = GameUser.builder() + .name(gameUserRequest.getName()) + .major(majorNormalizer.normalize(gameUserRequest.getMajor())) + .studentId(gameUserRequest.getStudentId()) + .phoneNumber(gameUserRequest.getPhoneNumber()) + .typingSpeed(gameUserRequest.getTypingSpeed()) + .build(); gameUserRepository.save(gameUser); return findUserRankings(); diff --git a/src/main/java/inha/gdgoc/domain/recruit/core/service/RecruitCoreApplicationService.java b/src/main/java/inha/gdgoc/domain/recruit/core/service/RecruitCoreApplicationService.java index 44120dca..16f58237 100644 --- a/src/main/java/inha/gdgoc/domain/recruit/core/service/RecruitCoreApplicationService.java +++ b/src/main/java/inha/gdgoc/domain/recruit/core/service/RecruitCoreApplicationService.java @@ -18,6 +18,7 @@ import inha.gdgoc.domain.user.repository.UserRepository; import inha.gdgoc.global.exception.BusinessException; import inha.gdgoc.global.exception.GlobalErrorCode; +import inha.gdgoc.global.util.MajorNormalizer; import java.time.Instant; import java.util.List; import lombok.RequiredArgsConstructor; @@ -33,6 +34,7 @@ public class RecruitCoreApplicationService { private final RecruitCoreApplicationRepository repository; private final UserRepository userRepository; private final RecruitCoreSessionResolver recruitCoreSessionResolver; + private final MajorNormalizer majorNormalizer; @Transactional(readOnly = true) public RecruitCoreApplicantDetailResponse getApplicantDetail(Long id) { @@ -82,7 +84,7 @@ public RecruitCoreApplicationCreateResponse submit(Long userId, RecruitCoreAppli .name(request.snapshot().name()) .studentId(request.snapshot().studentId()) .phone(cleanPhone) - .major(request.snapshot().major()) + .major(majorNormalizer.normalize(request.snapshot().major())) .email(request.snapshot().email()) .team(request.team()) .motivation(request.motivation()) diff --git a/src/main/java/inha/gdgoc/domain/recruit/member/dto/request/RecruitMemberRequest.java b/src/main/java/inha/gdgoc/domain/recruit/member/dto/request/RecruitMemberRequest.java index b50c0875..43646a8c 100644 --- a/src/main/java/inha/gdgoc/domain/recruit/member/dto/request/RecruitMemberRequest.java +++ b/src/main/java/inha/gdgoc/domain/recruit/member/dto/request/RecruitMemberRequest.java @@ -5,6 +5,7 @@ import inha.gdgoc.domain.recruit.member.enums.AdmissionSemester; import inha.gdgoc.domain.recruit.member.enums.EnrolledClassification; import inha.gdgoc.domain.recruit.member.enums.Gender; +import inha.gdgoc.global.util.MajorNormalizer; import java.time.LocalDate; import lombok.AllArgsConstructor; import lombok.Builder; @@ -27,7 +28,7 @@ public class RecruitMemberRequest { private String major; private Boolean isPayed; - public RecruitMember toEntity(AdmissionSemester admissionSemester) { + public RecruitMember toEntity(AdmissionSemester admissionSemester, MajorNormalizer majorNormalizer) { String cleanPhone = phoneNumber.replaceAll("[^0-9]", ""); return RecruitMember.builder() .name(name) @@ -37,7 +38,7 @@ public RecruitMember toEntity(AdmissionSemester admissionSemester) { .email(email) .gender(Gender.fromType(gender)) .birth(birth) - .major(major) + .major(majorNormalizer.normalize(major)) .isPayed(false) .admissionSemester(admissionSemester) .build(); diff --git a/src/main/java/inha/gdgoc/domain/recruit/member/service/RecruitMemberService.java b/src/main/java/inha/gdgoc/domain/recruit/member/service/RecruitMemberService.java index c3e70283..d895f756 100644 --- a/src/main/java/inha/gdgoc/domain/recruit/member/service/RecruitMemberService.java +++ b/src/main/java/inha/gdgoc/domain/recruit/member/service/RecruitMemberService.java @@ -22,6 +22,7 @@ import inha.gdgoc.domain.recruit.member.repository.RecruitMemberMemoRepository; import inha.gdgoc.domain.recruit.member.repository.RecruitMemberRepository; import inha.gdgoc.global.util.SemesterCalculator; +import inha.gdgoc.global.util.MajorNormalizer; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,6 +42,7 @@ public class RecruitMemberService { private final ObjectMapper objectMapper; private final SemesterCalculator semesterCalculator; private final S3Service s3Service; + private final MajorNormalizer majorNormalizer; @Transactional public void addRecruitMember(Map requestPayload, MultipartFile file) { @@ -63,7 +65,7 @@ public void addRecruitMember(Map requestPayload, MultipartFile f } RecruitMember member = memberRequest - .toEntity(semesterCalculator.currentSemester()); + .toEntity(semesterCalculator.currentSemester(), majorNormalizer); recruitMemberRepository.save(member); List answerEntities = answers.entrySet().stream() diff --git a/src/main/java/inha/gdgoc/domain/user/service/UserService.java b/src/main/java/inha/gdgoc/domain/user/service/UserService.java index 428f0fb1..d9d5781c 100644 --- a/src/main/java/inha/gdgoc/domain/user/service/UserService.java +++ b/src/main/java/inha/gdgoc/domain/user/service/UserService.java @@ -9,6 +9,7 @@ import inha.gdgoc.domain.user.entity.User; import inha.gdgoc.domain.user.exception.UserException; import inha.gdgoc.domain.user.repository.UserRepository; +import inha.gdgoc.global.util.MajorNormalizer; import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -22,6 +23,7 @@ public class UserService { private final UserRepository userRepository; + private final MajorNormalizer majorNormalizer; public CheckDuplicatedEmailResponse isExistsByEmail(CheckDuplicatedEmailRequest request) { return new CheckDuplicatedEmailResponse(userRepository.existsByEmail(request.email())); @@ -35,7 +37,7 @@ public User findUserById(Long userId) { public FindIdResponse findId(FindIdRequest findIdRequest) { Optional user = userRepository.findByNameAndMajorAndPhoneNumber( findIdRequest.getName(), - findIdRequest.getMajor(), + majorNormalizer.normalize(findIdRequest.getMajor()), findIdRequest.getPhoneNumber() ); diff --git a/src/main/java/inha/gdgoc/global/util/MajorNormalizer.java b/src/main/java/inha/gdgoc/global/util/MajorNormalizer.java new file mode 100644 index 00000000..a112e8b9 --- /dev/null +++ b/src/main/java/inha/gdgoc/global/util/MajorNormalizer.java @@ -0,0 +1,125 @@ +package inha.gdgoc.global.util; + +import java.util.Map; +import java.util.Set; +import org.springframework.stereotype.Component; + +@Component +public class MajorNormalizer { + + private static final Map LABEL_TO_CODE = Map.ofEntries( + Map.entry("인공지능공학과", "AIE"), + Map.entry("데이터사이언스학과", "DSE"), + Map.entry("스마트모빌리티공학과", "SME"), + Map.entry("디자인테크놀로지학과", "DTE"), + Map.entry("컴퓨터공학과", "CSE"), + Map.entry("기계공학과", "ME"), + Map.entry("항공우주공학과", "AAE"), + Map.entry("조선해양공학과", "NAE"), + Map.entry("산업경영공학과", "IME"), + Map.entry("화학공학과", "CHE"), + Map.entry("고분자공학과", "PSE"), + Map.entry("신소재공학과", "MSE"), + Map.entry("사회인프라공학과", "CIE"), + Map.entry("환경공학과", "ENVE"), + Map.entry("공간정보공학과", "GIE"), + Map.entry("건축학부(건축공학)", "ACE"), + Map.entry("건축학부(건축학)", "ARCH"), + Map.entry("에너지자원공학과", "ERE"), + Map.entry("융합기술경영학부", "MOT"), + Map.entry("전기전자공학부", "EEE"), + Map.entry("반도체시스템공학과", "SSE"), + Map.entry("이차전지융합학과", "BCE"), + Map.entry("수학과", "MATH"), + Map.entry("통계학과", "STAT"), + Map.entry("물리학과", "PHYS"), + Map.entry("화학과", "CHEM"), + Map.entry("해양과학과", "OCS"), + Map.entry("식품영양학과", "FNS"), + Map.entry("경영학부(경영학과)", "BUS"), + Map.entry("경영학부(파이낸스경영학과)", "FIN"), + Map.entry("아태물류학부", "APL"), + Map.entry("국제통상학과", "ITC"), + Map.entry("조형예술학과", "FINEART"), + Map.entry("디자인융합학과", "ID"), + Map.entry("스포츠과학과", "SPORTS"), + Map.entry("연극영화학과", "TFA"), + Map.entry("의류디자인학과", "FD"), + Map.entry("행정학과", "PAD"), + Map.entry("정치외교학과", "POL"), + Map.entry("미디어커뮤니케이션학과", "MCS"), + Map.entry("경제학과", "ECON"), + Map.entry("소비자학과", "CONS"), + Map.entry("아동심리학과", "CPSY"), + Map.entry("사회복지학과", "SW"), + Map.entry("자유전공융합학부", "ULS"), + Map.entry("공학융합학부", "ECS"), + Map.entry("자연과학융합학부", "NCS"), + Map.entry("경영융합학부", "BCONV"), + Map.entry("사회과학융합학부", "SCS"), + Map.entry("인문융합학부", "HCS"), + Map.entry("한국어문학과", "KLL"), + Map.entry("사학과", "HIST"), + Map.entry("철학과", "PHIL"), + Map.entry("중국학과", "CHIN"), + Map.entry("일본언어문화학과", "JLC"), + Map.entry("영미유럽인문융합학부", "ELH"), + Map.entry("문화콘텐츠문화경영학과", "CCM"), + Map.entry("메카트로닉스공학과", "MTE"), + Map.entry("소프트웨어융합공학과", "SWE"), + Map.entry("산업경영학과", "IMGT"), + Map.entry("금융투자학과", "FI"), + Map.entry("생명공학과", "BIOE"), + Map.entry("바이오제약공학과", "BPE"), + Map.entry("생명과학과", "BIOS"), + Map.entry("첨단바이오의약학과", "ABM"), + Map.entry("바이오식품공학과", "BFE"), + Map.entry("IBT학과", "IBT"), + Map.entry("ISE학과", "ISE"), + Map.entry("KLC학과", "KLC"), + Map.entry("의예과", "PREMED"), + Map.entry("의학과", "MED"), + Map.entry("간호학과", "NURS"), + Map.entry("국어교육과", "KOR_EDU"), + Map.entry("영어교육과", "ENG_EDU"), + Map.entry("사회교육과", "SOC_EDU"), + Map.entry("교육학과", "EDU"), + Map.entry("체육교육과", "PE_EDU"), + Map.entry("수학교육과", "MATH_EDU") + ); + + private static final Map ALIASES = Map.ofEntries( + Map.entry("스마트모빌리티놀학과", "SME"), + Map.entry("건축공학전공", "ACE"), + Map.entry("건축학전공(5년제)", "ARCH"), + Map.entry("경영학과", "BUS"), + Map.entry("파이낸스경영학과", "FIN"), + Map.entry("파이낸스경영학부(경영학과)", "FIN"), + Map.entry("문화콘텐츠문화경영학부(경영학과)", "CCM"), + Map.entry("문화컨텐츠경영학과", "CCM") + ); + + private static final Set KNOWN_CODES = Set.copyOf(LABEL_TO_CODE.values()); + + public String normalize(String major) { + if (major == null) { + return null; + } + + String trimmed = major.trim(); + if (trimmed.isBlank()) { + return trimmed; + } + + if (KNOWN_CODES.contains(trimmed)) { + return trimmed; + } + + String fromLabel = LABEL_TO_CODE.get(trimmed); + if (fromLabel != null) { + return fromLabel; + } + + return ALIASES.getOrDefault(trimmed, trimmed); + } +} diff --git a/src/main/resources/db/migration/V20260318__normalize_major_names.sql b/src/main/resources/db/migration/V20260318__normalize_major_names.sql new file mode 100644 index 00000000..c98ad9ad --- /dev/null +++ b/src/main/resources/db/migration/V20260318__normalize_major_names.sql @@ -0,0 +1,203 @@ +UPDATE users +SET major = mapping.code +FROM ( + VALUES + ('인공지능공학과', 'AIE'), + ('데이터사이언스학과', 'DSE'), + ('스마트모빌리티공학과', 'SME'), + ('스마트모빌리티놀학과', 'SME'), + ('디자인테크놀로지학과', 'DTE'), + ('컴퓨터공학과', 'CSE'), + ('기계공학과', 'ME'), + ('항공우주공학과', 'AAE'), + ('조선해양공학과', 'NAE'), + ('산업경영공학과', 'IME'), + ('화학공학과', 'CHE'), + ('고분자공학과', 'PSE'), + ('신소재공학과', 'MSE'), + ('사회인프라공학과', 'CIE'), + ('환경공학과', 'ENVE'), + ('공간정보공학과', 'GIE'), + ('건축학부(건축공학)', 'ACE'), + ('건축공학전공', 'ACE'), + ('건축학부(건축학)', 'ARCH'), + ('건축학전공(5년제)', 'ARCH'), + ('에너지자원공학과', 'ERE'), + ('융합기술경영학부', 'MOT'), + ('전기전자공학부', 'EEE'), + ('반도체시스템공학과', 'SSE'), + ('이차전지융합학과', 'BCE'), + ('수학과', 'MATH'), + ('통계학과', 'STAT'), + ('물리학과', 'PHYS'), + ('화학과', 'CHEM'), + ('해양과학과', 'OCS'), + ('식품영양학과', 'FNS'), + ('경영학부(경영학과)', 'BUS'), + ('경영학과', 'BUS'), + ('경영학부(파이낸스경영학과)', 'FIN'), + ('파이낸스경영학과', 'FIN'), + ('파이낸스경영학부(경영학과)', 'FIN'), + ('아태물류학부', 'APL'), + ('국제통상학과', 'ITC'), + ('조형예술학과', 'FINEART'), + ('디자인융합학과', 'ID'), + ('스포츠과학과', 'SPORTS'), + ('연극영화학과', 'TFA'), + ('의류디자인학과', 'FD'), + ('행정학과', 'PAD'), + ('정치외교학과', 'POL'), + ('미디어커뮤니케이션학과', 'MCS'), + ('경제학과', 'ECON'), + ('소비자학과', 'CONS'), + ('아동심리학과', 'CPSY'), + ('사회복지학과', 'SW'), + ('자유전공융합학부', 'ULS'), + ('공학융합학부', 'ECS'), + ('자연과학융합학부', 'NCS'), + ('경영융합학부', 'BCONV'), + ('사회과학융합학부', 'SCS'), + ('인문융합학부', 'HCS'), + ('한국어문학과', 'KLL'), + ('사학과', 'HIST'), + ('철학과', 'PHIL'), + ('중국학과', 'CHIN'), + ('일본언어문화학과', 'JLC'), + ('영미유럽인문융합학부', 'ELH'), + ('문화콘텐츠문화경영학과', 'CCM'), + ('문화콘텐츠문화경영학부(경영학과)', 'CCM'), + ('문화컨텐츠경영학과', 'CCM'), + ('메카트로닉스공학과', 'MTE'), + ('소프트웨어융합공학과', 'SWE'), + ('산업경영학과', 'IMGT'), + ('금융투자학과', 'FI'), + ('생명공학과', 'BIOE'), + ('바이오제약공학과', 'BPE'), + ('생명과학과', 'BIOS'), + ('첨단바이오의약학과', 'ABM'), + ('바이오식품공학과', 'BFE'), + ('IBT학과', 'IBT'), + ('ISE학과', 'ISE'), + ('KLC학과', 'KLC'), + ('의예과', 'PREMED'), + ('의학과', 'MED'), + ('간호학과', 'NURS'), + ('국어교육과', 'KOR_EDU'), + ('영어교육과', 'ENG_EDU'), + ('사회교육과', 'SOC_EDU'), + ('교육학과', 'EDU'), + ('체육교육과', 'PE_EDU'), + ('수학교육과', 'MATH_EDU') +) AS mapping(label, code) +WHERE users.major = mapping.label; + +UPDATE recruit_member +SET major = mapping.code +FROM ( + VALUES + ('인공지능공학과', 'AIE'), ('데이터사이언스학과', 'DSE'), ('스마트모빌리티공학과', 'SME'), + ('스마트모빌리티놀학과', 'SME'), ('디자인테크놀로지학과', 'DTE'), ('컴퓨터공학과', 'CSE'), + ('기계공학과', 'ME'), ('항공우주공학과', 'AAE'), ('조선해양공학과', 'NAE'), + ('산업경영공학과', 'IME'), ('화학공학과', 'CHE'), ('고분자공학과', 'PSE'), + ('신소재공학과', 'MSE'), ('사회인프라공학과', 'CIE'), ('환경공학과', 'ENVE'), + ('공간정보공학과', 'GIE'), ('건축학부(건축공학)', 'ACE'), ('건축공학전공', 'ACE'), + ('건축학부(건축학)', 'ARCH'), ('건축학전공(5년제)', 'ARCH'), ('에너지자원공학과', 'ERE'), + ('융합기술경영학부', 'MOT'), ('전기전자공학부', 'EEE'), ('반도체시스템공학과', 'SSE'), + ('이차전지융합학과', 'BCE'), ('수학과', 'MATH'), ('통계학과', 'STAT'), + ('물리학과', 'PHYS'), ('화학과', 'CHEM'), ('해양과학과', 'OCS'), + ('식품영양학과', 'FNS'), ('경영학부(경영학과)', 'BUS'), ('경영학과', 'BUS'), + ('경영학부(파이낸스경영학과)', 'FIN'), ('파이낸스경영학과', 'FIN'), + ('파이낸스경영학부(경영학과)', 'FIN'), ('아태물류학부', 'APL'), ('국제통상학과', 'ITC'), + ('조형예술학과', 'FINEART'), ('디자인융합학과', 'ID'), ('스포츠과학과', 'SPORTS'), + ('연극영화학과', 'TFA'), ('의류디자인학과', 'FD'), ('행정학과', 'PAD'), + ('정치외교학과', 'POL'), ('미디어커뮤니케이션학과', 'MCS'), ('경제학과', 'ECON'), + ('소비자학과', 'CONS'), ('아동심리학과', 'CPSY'), ('사회복지학과', 'SW'), + ('자유전공융합학부', 'ULS'), ('공학융합학부', 'ECS'), ('자연과학융합학부', 'NCS'), + ('경영융합학부', 'BCONV'), ('사회과학융합학부', 'SCS'), ('인문융합학부', 'HCS'), + ('한국어문학과', 'KLL'), ('사학과', 'HIST'), ('철학과', 'PHIL'), + ('중국학과', 'CHIN'), ('일본언어문화학과', 'JLC'), ('영미유럽인문융합학부', 'ELH'), + ('문화콘텐츠문화경영학과', 'CCM'), ('문화콘텐츠문화경영학부(경영학과)', 'CCM'), + ('문화컨텐츠경영학과', 'CCM'), ('메카트로닉스공학과', 'MTE'), + ('소프트웨어융합공학과', 'SWE'), ('산업경영학과', 'IMGT'), ('금융투자학과', 'FI'), + ('생명공학과', 'BIOE'), ('바이오제약공학과', 'BPE'), ('생명과학과', 'BIOS'), + ('첨단바이오의약학과', 'ABM'), ('바이오식품공학과', 'BFE'), ('IBT학과', 'IBT'), + ('ISE학과', 'ISE'), ('KLC학과', 'KLC'), ('의예과', 'PREMED'), ('의학과', 'MED'), + ('간호학과', 'NURS'), ('국어교육과', 'KOR_EDU'), ('영어교육과', 'ENG_EDU'), + ('사회교육과', 'SOC_EDU'), ('교육학과', 'EDU'), ('체육교육과', 'PE_EDU'), + ('수학교육과', 'MATH_EDU') +) AS mapping(label, code) +WHERE recruit_member.major = mapping.label; + +UPDATE core_recruit_applications +SET major = mapping.code +FROM ( + VALUES + ('인공지능공학과', 'AIE'), ('데이터사이언스학과', 'DSE'), ('스마트모빌리티공학과', 'SME'), + ('스마트모빌리티놀학과', 'SME'), ('디자인테크놀로지학과', 'DTE'), ('컴퓨터공학과', 'CSE'), + ('기계공학과', 'ME'), ('항공우주공학과', 'AAE'), ('조선해양공학과', 'NAE'), + ('산업경영공학과', 'IME'), ('화학공학과', 'CHE'), ('고분자공학과', 'PSE'), + ('신소재공학과', 'MSE'), ('사회인프라공학과', 'CIE'), ('환경공학과', 'ENVE'), + ('공간정보공학과', 'GIE'), ('건축학부(건축공학)', 'ACE'), ('건축공학전공', 'ACE'), + ('건축학부(건축학)', 'ARCH'), ('건축학전공(5년제)', 'ARCH'), ('에너지자원공학과', 'ERE'), + ('융합기술경영학부', 'MOT'), ('전기전자공학부', 'EEE'), ('반도체시스템공학과', 'SSE'), + ('이차전지융합학과', 'BCE'), ('수학과', 'MATH'), ('통계학과', 'STAT'), + ('물리학과', 'PHYS'), ('화학과', 'CHEM'), ('해양과학과', 'OCS'), + ('식품영양학과', 'FNS'), ('경영학부(경영학과)', 'BUS'), ('경영학과', 'BUS'), + ('경영학부(파이낸스경영학과)', 'FIN'), ('파이낸스경영학과', 'FIN'), + ('파이낸스경영학부(경영학과)', 'FIN'), ('아태물류학부', 'APL'), ('국제통상학과', 'ITC'), + ('조형예술학과', 'FINEART'), ('디자인융합학과', 'ID'), ('스포츠과학과', 'SPORTS'), + ('연극영화학과', 'TFA'), ('의류디자인학과', 'FD'), ('행정학과', 'PAD'), + ('정치외교학과', 'POL'), ('미디어커뮤니케이션학과', 'MCS'), ('경제학과', 'ECON'), + ('소비자학과', 'CONS'), ('아동심리학과', 'CPSY'), ('사회복지학과', 'SW'), + ('자유전공융합학부', 'ULS'), ('공학융합학부', 'ECS'), ('자연과학융합학부', 'NCS'), + ('경영융합학부', 'BCONV'), ('사회과학융합학부', 'SCS'), ('인문융합학부', 'HCS'), + ('한국어문학과', 'KLL'), ('사학과', 'HIST'), ('철학과', 'PHIL'), + ('중국학과', 'CHIN'), ('일본언어문화학과', 'JLC'), ('영미유럽인문융합학부', 'ELH'), + ('문화콘텐츠문화경영학과', 'CCM'), ('문화콘텐츠문화경영학부(경영학과)', 'CCM'), + ('문화컨텐츠경영학과', 'CCM'), ('메카트로닉스공학과', 'MTE'), + ('소프트웨어융합공학과', 'SWE'), ('산업경영학과', 'IMGT'), ('금융투자학과', 'FI'), + ('생명공학과', 'BIOE'), ('바이오제약공학과', 'BPE'), ('생명과학과', 'BIOS'), + ('첨단바이오의약학과', 'ABM'), ('바이오식품공학과', 'BFE'), ('IBT학과', 'IBT'), + ('ISE학과', 'ISE'), ('KLC학과', 'KLC'), ('의예과', 'PREMED'), ('의학과', 'MED'), + ('간호학과', 'NURS'), ('국어교육과', 'KOR_EDU'), ('영어교육과', 'ENG_EDU'), + ('사회교육과', 'SOC_EDU'), ('교육학과', 'EDU'), ('체육교육과', 'PE_EDU'), + ('수학교육과', 'MATH_EDU') +) AS mapping(label, code) +WHERE core_recruit_applications.major = mapping.label; + +UPDATE game_user +SET major = mapping.code +FROM ( + VALUES + ('인공지능공학과', 'AIE'), ('데이터사이언스학과', 'DSE'), ('스마트모빌리티공학과', 'SME'), + ('스마트모빌리티놀학과', 'SME'), ('디자인테크놀로지학과', 'DTE'), ('컴퓨터공학과', 'CSE'), + ('기계공학과', 'ME'), ('항공우주공학과', 'AAE'), ('조선해양공학과', 'NAE'), + ('산업경영공학과', 'IME'), ('화학공학과', 'CHE'), ('고분자공학과', 'PSE'), + ('신소재공학과', 'MSE'), ('사회인프라공학과', 'CIE'), ('환경공학과', 'ENVE'), + ('공간정보공학과', 'GIE'), ('건축학부(건축공학)', 'ACE'), ('건축공학전공', 'ACE'), + ('건축학부(건축학)', 'ARCH'), ('건축학전공(5년제)', 'ARCH'), ('에너지자원공학과', 'ERE'), + ('융합기술경영학부', 'MOT'), ('전기전자공학부', 'EEE'), ('반도체시스템공학과', 'SSE'), + ('이차전지융합학과', 'BCE'), ('수학과', 'MATH'), ('통계학과', 'STAT'), + ('물리학과', 'PHYS'), ('화학과', 'CHEM'), ('해양과학과', 'OCS'), + ('식품영양학과', 'FNS'), ('경영학부(경영학과)', 'BUS'), ('경영학과', 'BUS'), + ('경영학부(파이낸스경영학과)', 'FIN'), ('파이낸스경영학과', 'FIN'), + ('파이낸스경영학부(경영학과)', 'FIN'), ('아태물류학부', 'APL'), ('국제통상학과', 'ITC'), + ('조형예술학과', 'FINEART'), ('디자인융합학과', 'ID'), ('스포츠과학과', 'SPORTS'), + ('연극영화학과', 'TFA'), ('의류디자인학과', 'FD'), ('행정학과', 'PAD'), + ('정치외교학과', 'POL'), ('미디어커뮤니케이션학과', 'MCS'), ('경제학과', 'ECON'), + ('소비자학과', 'CONS'), ('아동심리학과', 'CPSY'), ('사회복지학과', 'SW'), + ('자유전공융합학부', 'ULS'), ('공학융합학부', 'ECS'), ('자연과학융합학부', 'NCS'), + ('경영융합학부', 'BCONV'), ('사회과학융합학부', 'SCS'), ('인문융합학부', 'HCS'), + ('한국어문학과', 'KLL'), ('사학과', 'HIST'), ('철학과', 'PHIL'), + ('중국학과', 'CHIN'), ('일본언어문화학과', 'JLC'), ('영미유럽인문융합학부', 'ELH'), + ('문화콘텐츠문화경영학과', 'CCM'), ('문화콘텐츠문화경영학부(경영학과)', 'CCM'), + ('문화컨텐츠경영학과', 'CCM'), ('메카트로닉스공학과', 'MTE'), + ('소프트웨어융합공학과', 'SWE'), ('산업경영학과', 'IMGT'), ('금융투자학과', 'FI'), + ('생명공학과', 'BIOE'), ('바이오제약공학과', 'BPE'), ('생명과학과', 'BIOS'), + ('첨단바이오의약학과', 'ABM'), ('바이오식품공학과', 'BFE'), ('IBT학과', 'IBT'), + ('ISE학과', 'ISE'), ('KLC학과', 'KLC'), ('의예과', 'PREMED'), ('의학과', 'MED'), + ('간호학과', 'NURS'), ('국어교육과', 'KOR_EDU'), ('영어교육과', 'ENG_EDU'), + ('사회교육과', 'SOC_EDU'), ('교육학과', 'EDU'), ('체육교육과', 'PE_EDU'), + ('수학교육과', 'MATH_EDU') +) AS mapping(label, code) +WHERE game_user.major = mapping.label;