[SQL 프로그래머스 문제풀이] (JOIN) 'FrontEnd 개발자 찾기'

윤상혁·2025년 11월 4일

1. 문제 소개

*테이블

1.SKILLCODES(NAME,CATEGORY,CODE)
->코드는 2진수로 표현했을 때, 각 bit로 구분될 수 있도록 2의 제곱수로 구성됨.

2.DEVELOPERS(ID,FIRST_NAME,LAST_NAME,EMAIL,SKILL_CODE)
->SKILL_CODE 역시 2의 제곱수로 구성됨.

*문제

1.DEVELOPERS 테이블에서 FRONT END 스킬 가진 개발자 정보 조회.
2.개발자 ID, 이메일, 이름, 성 조회.
3.ID 기준 오름차순 정렬

※예를 들어 어떤 개발자의 SKILL_CODE가 400 (=b'110010000')이라면, 이는 SKILLCODES 테이블에서 CODE가 256 (=b'100000000'), 128 (=b'10000000'), 16 (=b'10000') 에 해당하는 스킬을 가졌다는 것을 의미합니다.
->SUM을 해야하네..이게 관건이네..
->그럼 이거 큰 수부터 SUM 해야할 듯 ㅇㅇ

->이건 뒤에 나오겠지만, 옳은 풀이법은 아닙니다.
처음에 이렇게 생각했다의 의미로 적었습니다.


2. 문제 풀이

2-1. 개발자 ID, 이메일, 이름, 성 조회하기

여기에서 조인이 필요할까? 생각했는데,
다 DEVELOPERS 테이블 속성이므로 필요가 없습니다.

<정답 코드>

SELECT
    ID,
    FIRST_NAME,
    LAST_NAME,
    SKILL_CODE
FROM DEVELOPERS;

결과를 보니, 예시 테이블과 같음을 알 수 있었습니다.

나중에 나오겠지만,
이 부분은 사실 딱히 필요는 없고,
제가 그냥 결과 테이블이 궁금해서 작성한 부분입니다.


2-2. 1번 문제 소개에서 '※' 부분 구현하기

처음에 저는 이렇게 생각했습니다.

어떻게 구현하지..?
집계니깐 HAVING절 같은데.. 근데 GROUP BY는 필요없는 단순 집계만임.

SUM(CODE)를 하는데,
FOR문 같이 돌려서,
HAVING(SUM(CODE).......~~

그래서 CLAUDE에게 '혹시 SQL문도 FOR문이 있는지?' 물어봤습니다.

SQL문은 반복문 없이 한 번에 처리하므로 FOR문이 사용불가능하다고 하네요.

그럼 FOR문 접근 방법은 아닌 거 같습니다.

근데, 제 생각엔 FOR문 밖에 떠오르지 않습니다.

뭔가 다른 문제 풀이법이 있다는 의미입니다.


이 문제의 올바른 문제 풀이법은 바로,
'비트 연산(SQL BITWISE)'입니다.

※개념_1. 비트 연산(SQL_BITWISE)

해당 개념은 '신 영'님의 벨로그를 참고하였습니다.
(출처: https://velog.io/@sobit/%EB%B9%84%ED%8A%B8-%EC%97%B0%EC%82%B0%EC%9E%90bitwise-operator-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%A0%9C%EB%A1%9C-%EC%9D%B4%ED%95%B4%ED%95%B4-%EB%B3%B4%EC%9E%90)

C언어에서도 봤던 익숙한 BIT 계산입니다.

추가 설명 보충을 하자면,
~는 0과 1 부분을 반전시키는 것이고,
왼쪽 시프트 및 오른쪽 시프트 연산 시에 이동하고 채워야하는 부분은 기본적으로 0으로 채웁니다.

CLAUDE는 이 문제는 '&(AND)' 연산을 이용해서 문제를 풀라고 합니다.

근데, 저는 '|(OR)' 연산으로 다 더해서 구해야하는 거 아니냐고 질문을 했습니다.

즉 요약하자면,
우리는 문제에서 요구한대로 'FRONT END'가 들어가있는지만 확인하면 되므로, '&' 연산을 사용합니다.

하지만, 저는 전체 구성은 어떻게 되어 있는지도 파악하기 위해, 문제를 먼저 풀고 후속으로 또 문제를 풀어보도록 할 것입니다.


<최종 정답 코드>

SELECT DISTINCT
    D.ID,
    D.EMAIL,
    D.FIRST_NAME,
    D.LAST_NAME
FROM SKILLCODES S INNER JOIN DEVELOPERS D
ON S.CODE & D.SKILL_CODE > 0
WHERE S.CATEGORY = 'FRONT END'
ORDER BY D.ID ASC

일단 최종 정답 코드부터 공개한 후에
설명을 하도록 하겠습니다.

우리는 SKILLCODES 테이블과 DEVELOPERS 테이블에서 ON 조건에 맞는 공통된(교집합) 부분만 SELECT하면 되므로,
INNER JOIN을 실시합니다.

ON 조건은 S.CODE와 D.SKILL_CODE를 AND 연산하여 S.CODE가 D.SKILL_CODE에 포함되어 있는지를 판단하고,
포함된 것들만(>0) 걸러냅니다.

그리고 WHERE 조건절을 사용하여,
S.CATEGORY가 'FRONT END'만을 고릅니다.

여기서 눈여겨봐야할 건 'DISTINCT'인데,

우리는 위 사진 같이,
조인을 실시하면 FRONT END가 여러 개이면, 중복 행이 발생할 수 있고, 우리는 중복이 아닌 단일 행만을 출력해야하므로, DISTINCT를 통해 중복을 제거해줍니다.


2-3. FRONT END만이 아닌 전체 구성 출력하기

저는 2가지 방법으로 구현하였습니다.

<방법_1>

SELECT 
    D.ID,
    D.FIRST_NAME,
    S.NAME AS SKILL_NAME,
    S.CODE AS SKILL_CODE
FROM DEVELOPERS D
JOIN SKILLCODES S 
ON D.SKILL_CODE & S.CODE > 0
-- WHERE D.ID = 'D001'
ORDER BY D.ID ASC

이 방법은,
사실상 2-2번 최종 정답 코드와 구조는 동일하나,
SELECT문에서 열만 바꾼 것입니다.

이 방법은 그룹화(X) 버전입니다.

<방법_2>

SELECT 
    D.ID,
    D.FIRST_NAME,
    GROUP_CONCAT(S.NAME) AS ALL_SKILLS,
    SUM(S.CODE) AS TOTAL_CODE
FROM DEVELOPERS D
JOIN SKILLCODES S 
ON D.SKILL_CODE & S.CODE > 0
-- WHERE D.ID = 'D001'
GROUP BY D.ID, D.FIRST_NAME
ORDER BY D.ID ASC;

이 방법은,
위 '방법_1'에서 그룹화를 진행한 부분입니다.

GROUP_CONCAT은
'CONCAT'은 이어붙이다라는 개발 용어이고,
GROUP_CONCAT은 위 사진 결과처럼, 그룹화한 행에 한 행에 여러개의 스킬들을 이어붙이게 만드는 효과를 만듭니다.

나머지는 비슷한데,
우리는 여기서 알아야 할 개념 1개가 있습니다.

※개념_2.'ONLY_FULL_GROUP_BY' 개념

왜 우리는 D.ID만으로 GROUP BY를 할 수가 없고,
D.ID + D.FRIST_NAME으로 GROUP BY를 해야할까요?

저는 전에 GROUP BY의 개념을 다시 재정비할 때(이전 게시글에 해당 개념이 있을 겁니다.),
테스트를 했을 때, GROUP BY의 특성상 여러 중복 행을 한 행으로 합치는데, 선택된 행 외의 나머지 행들은 그냥 버려지는 것을 확인했습니다.

위 사진과 같이,
우리가 명시하지 않은 이상 SQL 스스로가 판단하는 것은 불가능합니다. 그래서 D.ID만을 사용했을 때 에러가 나는 이유입니다.

위 사진처럼,
SQL의 판단 기준은 GROUP BY로 선택된 열만이며,
PK 또는 다른 제약조건들은 확인하지 않는다는 것을 알 수 있습니다.


근데 우리는 OR 개념을 사용해서 전체를 출력하려고 했는데, 여기에서도 & 연산을 통해 구현했습니다.

그럼 OR 연산은 어디에 사용하는 것일까요?

위 사진과 같이,
'OR' 연산은 '데이터를 만들 때(삽입할 때)' 사용하고,
'AND' 연산은 '데이터를 파악할 때(조건절)' 사용합니다.


3. 마무리

이렇게 해서 이번에는 새로운 개념인 '비트 연산'에 대해서 배워봤습니다.

신선했고, 난이도는 비트 연산만 알면 무난했다고 판단됩니다.

이렇게 해서 글 작성을 마무리하도록 하겠습니다.
긴 글 읽어주셔서 감사합니다!! :) bb

profile
통합형 개발자. 기획부터 개발, 자동화까지. 문제를 구조적으로 이해하고, AI를 능동적으로 활용해 본질적인 해결책을 제시하는 사람입니다.

0개의 댓글