2026년 Looker와 LookML 완벽 가이드: 비즈니스 인텔리전스 및 면접 대비

LookML 시맨틱 레이어, 데이터 모델링, 실전 구현 패턴을 상세히 설명합니다. 2026년 데이터 분석가 면접에서 자주 출제되는 Looker 관련 질문과 답변 예시를 포함한 종합 튜토리얼입니다.

Looker and LookML Business Intelligence Interview Guide

Looker 면접에서는 LookML 모델링, 데이터 탐색 워크플로우, 그리고 시맨틱 레이어가 비즈니스 로직을 재사용 가능한 정의로 변환하는 방식이 주요 평가 항목입니다. 본 튜토리얼에서는 LookML의 핵심 개념, 실전 구현 패턴, 그리고 2026년 Looker 관련 포지션 면접에서 데이터 분석가가 직면하는 구체적인 질문들을 다룹니다.

LookML 핵심 개념

LookML은 데이터 모델링과 데이터 탐색을 분리합니다. 분석가가 모델 레이어에서 디멘션, 메저, 관계를 한 번 정의하면 비즈니스 사용자는 SQL을 작성하지 않고도 데이터를 쿼리할 수 있습니다. 이 설계 패턴은 거의 모든 Looker 기술 면접에서 등장합니다.

LookML 시맨틱 레이어 이해하기

LookML은 원시 데이터베이스 테이블과 비즈니스 친화적인 지표 사이의 변환 레이어로 작동합니다. 복잡한 SQL 조인을 반복적으로 작성하는 대신, 분석가는 모델 파일에서 관계를 정의하고 Looker가 이를 최적화된 쿼리로 컴파일합니다.

시맨틱 레이어는 면접관이 자주 질문하는 세 가지 문제를 해결합니다:

  • 일관성: 모든 사용자가 동일한 지표 정의를 참조할 수 있습니다
  • 재사용성: 디멘션과 메저는 한 번 정의하면 어디서든 참조 가능합니다
  • 거버넌스: 변경 사항이 모든 대시보드에 자동으로 반영됩니다

Google Cloud의 Looker 문서에서는 LookML을 "의존성 인식" 언어로 설명합니다. 하나의 정의가 변경되면 다운스트림 참조가 자동으로 업데이트됩니다. 이 의존성 인식 기능은 엔터프라이즈 규모의 모델을 유지 관리할 때 매우 중요합니다.

LookML View와 Explore: 기본 구성 요소

View는 단일 테이블 또는 파생 테이블에서 사용할 수 있는 컬럼을 정의합니다. Explore는 조인을 통해 View를 결합하고 비즈니스 사용자에게 노출합니다.

lookml
# views/orders.view.lkml
view: orders {
  sql_table_name: `analytics.orders` ;;

  dimension: order_id {
    primary_key: yes
    type: number
    sql: ${TABLE}.order_id ;;
  }

  dimension_group: created {
    type: time
    timeframes: [raw, date, week, month, quarter, year]
    sql: ${TABLE}.created_at ;;
  }

  dimension: status {
    type: string
    sql: ${TABLE}.status ;;
  }

  measure: total_orders {
    type: count
    drill_fields: [order_id, created_date, status]
  }

  measure: total_revenue {
    type: sum
    sql: ${TABLE}.amount ;;
    value_format_name: usd
  }
}

dimension_group 선언은 단일 타임스탬프 컬럼에서 여러 시간 기반 디멘션을 생성합니다. 면접관은 종종 이 패턴이 코드 중복을 줄이고 모델 전체에서 일관된 날짜 처리를 보장하는 이유를 설명하도록 요청합니다.

drill_fields 매개변수는 사용자가 메저 값을 클릭할 때 표시되는 내용을 정의합니다. 이는 분석가가 실제로 Looker와 상호작용하는 방식을 보여주는 UX 세부 사항이며, 이해도를 평가하는 중요한 포인트입니다.

LookML의 조인과 관계

Explore는 View가 SQL 조인을 통해 어떻게 연결되는지 정의합니다. 조인 유형과 관계 선언은 쿼리 성능과 집계 정확도에 직접적인 영향을 미칩니다.

lookml
# models/ecommerce.model.lkml
explore: orders {
  label: "주문 분석"
  description: "주문, 고객, 상품 데이터를 결합한 분석용 Explore"

  join: customers {
    type: left_outer
    relationship: many_to_one
    sql_on: ${orders.customer_id} = ${customers.customer_id} ;;
  }

  join: products {
    type: left_outer
    relationship: many_to_one
    sql_on: ${orders.product_id} = ${products.product_id} ;;
  }

  join: order_items {
    type: left_outer
    relationship: one_to_many
    sql_on: ${orders.order_id} = ${order_items.order_id} ;;
  }
}

relationship 매개변수는 Looker에게 팬아웃 문제를 올바르게 처리하는 방법을 알려줍니다. one_to_many 조인에서 메저를 집계할 때 Looker는 대칭 집계를 적용하여 정확한 결과를 보장합니다.

면접 빈출 질문: 팬아웃 문제

면접관은 정기적으로 팬아웃 문제에 대한 설명을 요청합니다. 주문에 여러 상품이 있는 경우, 단순한 SUM 집계는 각 상품 행에서 주문 합계를 이중으로 계산합니다. Looker의 대칭 집계가 이를 자동으로 처리하지만, 지원자는 기본 SQL 변환을 설명할 수 있어야 합니다.

sql
-- Looker가 생성하는 대칭 집계 SQL
SELECT
  SUM(DISTINCT CONCAT(
    CAST(orders.order_id AS STRING),
    '|',
    CAST(orders.amount AS STRING)
  )) AS total_revenue
FROM orders
JOIN order_items ON orders.order_id = order_items.order_id

파생 테이블과 PDT(영구 파생 테이블)

파생 테이블은 SQL 쿼리 또는 네이티브 LookML에서 동적으로 계산된 테이블을 생성합니다. 영구 파생 테이블(PDT)은 이러한 결과를 데이터베이스에 캐시하여 성능을 향상시킵니다.

lookml
view: daily_order_summary {
  derived_table: {
    sql:
      SELECT
        DATE(created_at) AS order_date,
        COUNT(*) AS order_count,
        SUM(amount) AS daily_revenue
      FROM orders
      GROUP BY 1
    ;;

    datagroup_trigger: orders_datagroup
    indexes: ["order_date"]
  }

  dimension: order_date {
    type: date
    sql: ${TABLE}.order_date ;;
  }

  measure: total_order_count {
    type: sum
    sql: ${TABLE}.order_count ;;
  }

  measure: total_daily_revenue {
    type: sum
    sql: ${TABLE}.daily_revenue ;;
  }
}

datagroup_trigger 매개변수는 PDT가 언제 다시 빌드되는지 제어합니다. 데이터 그룹은 데이터 신선도를 정의하며 여러 PDT에서 재사용할 수 있어 웨어하우스 비용을 줄이면서 일관된 업데이트를 보장합니다.

네이티브 파생 테이블

네이티브 파생 테이블은 원시 SQL 대신 LookML 구문을 사용하여 기존 디멘션과 메저를 활용할 수 있습니다.

lookml
view: customer_lifetime_value {
  derived_table: {
    explore_source: orders {
      column: customer_id { field: customers.customer_id }
      column: total_orders { field: orders.total_orders }
      column: total_revenue { field: orders.total_revenue }
      column: first_order_date { field: orders.created_date }
      column: last_order_date { field: orders.created_date }

      derived_column: customer_tenure_days {
        sql: DATE_DIFF(last_order_date, first_order_date, DAY) ;;
      }
    }

    datagroup_trigger: orders_datagroup
  }

  dimension: customer_id {
    primary_key: yes
    type: number
  }

  dimension: customer_segment {
    type: string
    sql:
      CASE
        WHEN ${total_revenue} >= 10000 THEN 'VIP'
        WHEN ${total_revenue} >= 1000 THEN 'Active'
        ELSE 'Standard'
      END
    ;;
  }
}

Looker 면접 빈출 기술 질문

질문 1: Liquid 템플릿과 LookML

Liquid는 LookML 내에서 매개변수화된 SQL, 동적 필드 가시성, 컨텍스트 의존적 로직을 가능하게 합니다.

lookml
view: orders {
  parameter: date_granularity {
    type: unquoted
    allowed_values: ["day", "week", "month", "quarter", "year"]
    default_value: "month"
  }

  dimension: dynamic_date {
    type: string
    sql:
      {% if date_granularity._parameter_value == 'day' %}
        DATE(${created_raw})
      {% elsif date_granularity._parameter_value == 'week' %}
        DATE_TRUNC(${created_raw}, WEEK)
      {% elsif date_granularity._parameter_value == 'month' %}
        DATE_TRUNC(${created_raw}, MONTH)
      {% elsif date_granularity._parameter_value == 'quarter' %}
        DATE_TRUNC(${created_raw}, QUARTER)
      {% else %}
        DATE_TRUNC(${created_raw}, YEAR)
      {% endif %}
    ;;
  }

  measure: filtered_revenue {
    type: sum
    sql: ${TABLE}.amount ;;
    filters: [status: "completed, shipped"]
  }
}

질문 2: 액세스 필터와 행 수준 보안

면접관은 민감한 데이터를 보호하면서 적절한 접근을 허용하는 방법에 대해 설명하도록 요청합니다.

lookml
explore: orders {
  access_filter: {
    field: orders.region
    user_attribute: allowed_regions
  }

  access_filter: {
    field: customers.customer_segment
    user_attribute: visible_segments
  }
}

액세스 필터는 행 수준 보안을 자동으로 적용합니다. 사용자 속성에 따라 데이터가 자동으로 필터링되며 수동 WHERE 절이 필요하지 않습니다.

질문 3: 캐싱 전략과 데이터 그룹

효율적인 캐싱 전략은 사용자 경험과 데이터베이스 비용 모두에 영향을 미칩니다.

lookml
datagroup: orders_datagroup {
  max_cache_age: "24 hours"
  sql_trigger: SELECT MAX(updated_at) FROM orders ;;
}

datagroup: realtime_datagroup {
  max_cache_age: "5 minutes"
  sql_trigger: SELECT CURRENT_TIMESTAMP() ;;
}

explore: orders {
  persist_with: orders_datagroup
}

explore: realtime_metrics {
  persist_with: realtime_datagroup
}

Data Analytics 면접 준비가 되셨나요?

인터랙티브 시뮬레이터, flashcards, 기술 테스트로 연습하세요.

성능 최적화 기법

집계 인식(Aggregate Awareness)

집계 인식을 통해 Looker는 쿼리 요구 사항에 따라 상세 테이블과 집계 테이블 중 어디서 읽을지 자동으로 선택할 수 있습니다.

lookml
explore: orders {
  aggregate_table: daily_orders_rollup {
    query: {
      dimensions: [created_date, status, region]
      measures: [total_orders, total_revenue]
    }

    materialization: {
      datagroup_trigger: orders_datagroup
    }
  }

  aggregate_table: monthly_orders_rollup {
    query: {
      dimensions: [created_month, status]
      measures: [total_orders, total_revenue, average_order_value]
    }

    materialization: {
      datagroup_trigger: orders_datagroup
    }
  }
}

증분 PDT

대규모 데이터셋의 경우 증분 PDT는 전체 테이블 스캔을 피하고 새로운 레코드만 추가합니다.

lookml
view: incremental_orders {
  derived_table: {
    sql:
      SELECT *
      FROM orders
      WHERE created_at >= COALESCE(
        (SELECT MAX(created_at) FROM ${SQL_TABLE_NAME}),
        '1900-01-01'
      )
    ;;

    datagroup_trigger: hourly_datagroup
    increment_key: "created_at"
    increment_offset: 3
  }
}

Looker API와 시스템 통합

Looker의 API는 자동화, 임베딩, 외부 시스템과의 통합을 가능하게 합니다.

python
import looker_sdk

sdk = looker_sdk.init40()

# 대시보드를 프로그래밍 방식으로 실행
result = sdk.run_look(
    look_id=123,
    result_format="json"
)

# 스케줄을 동적으로 생성
schedule = sdk.create_scheduled_plan(
    body={
        "name": "Daily Revenue Report",
        "look_id": 123,
        "crontab": "0 9 * * *",
        "scheduled_plan_destination": [{
            "type": "email",
            "address": "analytics@company.com",
            "format": "csv"
        }]
    }
)

# 모델 검증 자동화
validation = sdk.validate_project(
    project_id="my_project"
)

if validation.errors:
    for error in validation.errors:
        print(f"Error in {error.file_path}: {error.message}")

면접 성공을 위한 모범 사례

모델 구성

대규모 LookML 프로젝트에서는 명확한 파일 구성이 유지보수성의 핵심입니다.

text
models/
├── ecommerce.model.lkml
├── marketing.model.lkml
└── finance.model.lkml

views/
├── core/
│   ├── orders.view.lkml
│   ├── customers.view.lkml
│   └── products.view.lkml
├── derived/
│   ├── customer_ltv.view.lkml
│   └── daily_metrics.view.lkml
└── extensions/
    └── order_extended.view.lkml

datagroups/
└── datagroups.lkml

명명 규칙

일관된 명명 규칙을 통해 팀 전체에서 코드 가독성이 향상됩니다.

  • 디멘션: 스네이크 케이스로 명사 사용 (예: customer_id, order_status)
  • 메저: 접두사로 집계 유형 표시 (예: total_revenue, count_orders, avg_order_value)
  • Explore: 분석 대상을 명확하게 표현 (예: order_analysis, customer_behavior)

결론

Looker와 LookML은 현대 비즈니스 인텔리전스 스택에서 중요한 역할을 담당합니다. 면접에서는 시맨틱 레이어의 개념적 이해뿐만 아니라 성능 최적화, 보안 구현, 그리고 실제 비즈니스 과제를 해결하기 위한 모델링 역량이 평가됩니다.

본 튜토리얼에서 다룬 LookML 기본 구문, 조인과 관계 설계, 파생 테이블, Liquid 구문, 그리고 캐싱 전략은 데이터 분석가의 Looker 면접에서 가장 빈출되는 주제입니다. 이러한 개념을 실제 프로젝트에 적용하고 실전 경험을 쌓는 것이 면접 성공을 위한 최선의 준비입니다.

태그

#looker
#lookml
#business-intelligence
#data-analytics
#interview

공유

관련 기사