CodeGym /행동 /SQL SELF /JSON 데이터 다룰 때 흔히 하는 실수와 그 예방법

JSON 데이터 다룰 때 흔히 하는 실수와 그 예방법

SQL SELF
레벨 34 , 레슨 4
사용 가능

PostgreSQL에서 JSON 데이터를 다루는 건 진짜 강력한 기능이지만, 아무리 좋은 도구라도 조심해서 써야 해. 작은 실수 하나가 쿼리를 완전 미궁으로 만들 수도 있거든. 오늘은 PostgreSQL에서 JSON이랑 JSONB를 쓸 때 자주 나오는 실수들과, 그걸 어떻게 피할 수 있는지에 집중해볼게.

문제 1: JSON 대신 JSONB를 안 쓰는 경우

많은 초보자들이 JSON 타입이 JSON 데이터를 저장할 때 더 좋다고 착각해서 그냥 쓰는 경우가 많아. 근데 PostgreSQL에서 JSON은 데이터를 텍스트로 저장해서, 검색이나 필터링할 때 성능이 확 떨어질 수 있어.

실수 예시:

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSON
);

INSERT INTO products (details) VALUES ('{"name": "노트북", "price": 1000}');

INSERT INTO products (details) VALUES ('{"name": "노트북", "price": 1000}');

키(price)로 필터링하려고 하면 JSONB에 비해 훨씬 느리게 동작하는 걸 볼 수 있어.

해결 방법: 데이터를 자주 필터링하거나 접근할 계획이면 JSONB를 써!

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSONB
);

문제 2: JSONB에 인덱스가 없는 경우

JSONB는 진짜 강력한 도구지만, 인덱스 없이 쓰면 복잡한 쿼리에서 성능이 확 떨어질 수 있어.

실수 예시: 예를 들어, details 컬럼에 JSON 오브젝트를 잔뜩 저장해놓은 테이블이 있다고 해보자:

SELECT * FROM products WHERE details->>'name' = '노트북';

인덱스가 없으면 서버가 모든 레코드를 다 뒤져야 해서(full table scan), 시간이 훨씬 오래 걸려.

해결 방법: 키 검색을 빠르게 하려면 GIN 인덱스를 만들어줘:

CREATE INDEX idx_details_name ON products USING gin (details jsonb_path_ops);

문제 3: 중첩 데이터 추출 실수

중첩된 오브젝트나 배열에서 데이터를 뽑아낼 때 헷갈릴 수 있는데, 특히 ->->> 연산자의 차이를 모르면 실수하기 쉽지.

실수 예시:

SELECT details->'price' FROM products;

이 쿼리는 값을 JSON 형식으로 반환해. 즉, "1000"이 아니라 1000이 아니라는 거지. 진짜 값이 필요하면 ->>를 써야 해:

SELECT details->>'price' FROM products;

문제 4: 연산자 잘못 쓰는 경우

@> 연산자를 보고 "오, 이거 멋진데? 무조건 써야지!"라고 생각할 수도 있는데, 이게 어떻게 동작하는지 모르면 예상치 못한 결과가 나올 수 있어.

실수 예시:

SELECT * FROM products WHERE details @> '{"price": 1000}';

이 쿼리는 price가 JSON에서 숫자일 때만 동작해. 만약 값이 문자열 "1000"로 저장되어 있으면 결과가 안 나와.

해결 방법: JSON에서 데이터 타입을 꼭 신경 써야 해:

SELECT * FROM products WHERE details->>'price' = '1000';

문제 5: 큰 JSON 오브젝트

최적화 없이 큰 JSON 오브젝트를 저장하면 쿼리 성능이 엄청 느려질 수 있어. 게다가 JSONB 안의 작은 데이터 하나만 바꿔도 전체 오브젝트를 다 읽고 써야 하거든.

해결 방법: 자주 쓰는 키가 있다면, 그건 따로 컬럼으로 빼는 게 좋아. 예를 들어:

ALTER TABLE products ADD COLUMN price NUMERIC;
UPDATE products SET price = (details->>'price')::NUMERIC;

이제 JSONB를 파싱하지 않고도 데이터를 빠르게 필터링하고 정렬할 수 있어.

문제 6: 오브젝트 전체를 다시 만드는 경우

jsonb_set()이나 jsonb_insert() 같은 함수를 쓰면, PostgreSQL이 완전히 새로운 JSONB 오브젝트를 만들어. 이게 성능에 부담이 될 수 있어.

해결 방법: JSONB 업데이트 횟수를 최소화해. 예를 들어, 여러 번 나눠서 업데이트하지 말고 한 번에 처리하는 게 좋아:

UPDATE products
SET details = jsonb_set(details, '{price}', '1500'::jsonb);

문제 7: 배열 구조를 잘못 이해하는 경우

JSONB에서 배열도 신경 써야 해. 예를 들어, 이런 배열이 있다고 해보자:

{
    "tags": ["전자제품", "노트북", "세일"]
}

"노트북" 태그가 있는지 확인하고 싶을 때, @> 연산자를 잘못 쓰면 결과가 안 나올 수 있어. 이 연산자는 문자열이 아니라 배열을 기대하거든.

실수 예시:

SELECT * FROM products WHERE details->'tags' @> '"노트북"';

해결 방법: @> 연산자에 올바른 포맷을 써야 해:

SELECT * FROM products WHERE details->'tags' @> '["노트북"]';

실수 방지 꿀팁

JSONB를 쓸 때 이런 팁들을 기억하면 실수 확 줄일 수 있어:

데이터 타입을 제대로 선택하자. 데이터가 많고 자주 필터링한다면 JSON 대신 JSONB를 꼭 써.

인덱스를 꼭 만들자. 특정 키를 자주 조회한다면, GIN 같은 인덱스를 만들어줘.

데이터를 넣기 전에 꼭 체크하자. 데이터 구조를 확인하려면 validation 함수를 써봐:

DO $$
BEGIN
    IF jsonb_typeof('{"price": 1000}'::jsonb->'price') IS DISTINCT FROM 'number' THEN
        RAISE EXCEPTION '가격은 숫자여야 해';
    END IF;
END $$;

데이터 구조를 최적화하자. 자주 쓰는 키는 따로 컬럼으로 빼는 게 좋아.

연산자랑 함수 공부하기. PostgreSQL 공식 문서를 꼼꼼히 읽고 ->, ->>, @>, ?| 등 함수 차이를 잘 알아두자.

JSON이랑 JSONB는 유연하고 복잡한 데이터를 다룰 때 진짜 든든한 친구가 될 수 있어. 중요한 건 도구를 잘 골라서 흔한 실수를 피하고, 네 코드가 효율적이고 관리하기 쉽게 만드는 거야!

1
설문조사/퀴즈
JSON 오브젝트에서 데이터 업데이트하기, 레벨 34, 레슨 4
사용 불가능
JSON 오브젝트에서 데이터 업데이트하기
JSON 오브젝트에서 데이터 업데이트하기
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION