Firebase 특정 host에 deploy
![]() |
|---|
| 뭔가 빠져있다는 메시지 |
GCP스터디를 진행하다 보니 deploy가 안 된다.
처음에는 단순한 bucket인줄 알았는데.
firebase hosting:sites:create [사이트 ID]
이런 형태로 만들어줘야 하는 것이었다.
물론.. default에 배포한다면 안 해도 되는 것이기는 하다.
![]() |
|---|
| firebase.json |
추가로 firebase.json은 왜 editing이 안 되는 것이냐? console에서 nano로 수정하고 있다.
goLang으로 만들어진 webhook과 gitHub 연결
jekyll을 hugo로 바꾸는 목적이 “절차의 간단함"임으로 push하는 동시에 blog가 생성되도록 하는 방법을 찾아본다.
BigQueryML에서 TRANSFORM
BigQueryML에서 TRANSFORM은 모델 학습 전에 데이터 전처리를 선언적으로 지정할 수 있는 기능입니다. 이를 통해 훈련/예측 시 일관된 전처리 파이프라인을 적용할 수 있으며, 특히 파이프라인 재사용이나 자동 특성 엔지니어링에 유용합니다.
✅ 기본 개념
BigQueryML의 TRANSFORM 구문은 CREATE MODEL 문에서 사용되며, 주로 다음과 같이 구성됩니다:
CREATE MODEL project.dataset.model_name
TRANSFORM (
-- 변환 정의
)
OPTIONS (...) AS
SELECT ...
🔧 예제: 범주형 인코딩 + 스케일링
CREATE OR REPLACE MODEL my_dataset.my_model
TRANSFORM (
one_hot_encoded_country AS
one_hot_encode(country),
scaled_age AS
standard_scaler(age)
)
OPTIONS (
model_type = 'logistic_reg',
input_label_cols = ['label']
) AS
SELECT
country,
age,
label
FROM
my_dataset.training_data;
one_hot_encode(country): 범주형 변수 인코딩standard_scaler(age): 평균 0, 표준편차 1로 정규화TRANSFORM블록에서 정의된 컬럼은 아래SELECT의 컬럼을 전처리하여 학습에 사용됨
🧠 지원되는 주요 변환 함수
| 함수 | 설명 |
|---|---|
one_hot_encode(col) |
범주형 변수 → 원-핫 인코딩 |
log(col) |
로그 변환 |
normalize(col) |
0~1 정규화 |
standard_scaler(col) |
표준화 (Z-score) |
bucketize(col, boundaries) |
수치형 변수 → 구간화 |
clip(col, min, max) |
값 제한 |
cast(col AS TYPE) |
형변환 |
📌 참고 사항
TRANSFORM은 모델 정의 내부에서만 사용 가능합니다.SELECT쿼리에서는 사용 불가합니다.TRANSFORM블록의 출력 컬럼명은 모델이 학습에 사용하는 특성명입니다.SELECT절에서는 원본 컬럼을 제공해야 합니다. (전처리는TRANSFORM안에서 수행됨)
🔍 예제: 날짜 파싱 및 로그 변환
CREATE OR REPLACE MODEL my_dataset.sales_model
TRANSFORM (
log_price AS log(price),
day_of_week AS EXTRACT(DAYOFWEEK FROM DATE(timestamp))
)
OPTIONS (
model_type = 'linear_reg',
input_label_cols = ['sales']
) AS
SELECT
price,
timestamp,
sales
FROM
my_dataset.sales_data;
필요하다면 TRANSFORM 없이도 SQL로 사전 전처리를 해서 CREATE MODEL에 넘길 수 있지만, TRANSFORM을 쓰면 학습-예측 간 일관성이 보장됩니다.
podman 자동 재시작
주) 이렇게 안 해도
Podman + docker-compose (또는 podman-compose) 환경에서 OS 재부팅 후 컨테이너 자동 시작을 설정하려면 Docker처럼 기본적으로 restart: always만으로는 자동 시작되지 않으며, Podman의 systemd 통합을 사용해야 합니다.
✅ 방법 1: podman generate systemd로 systemd 유닛 생성
-
컨테이너를 먼저 실행
podman run -d --name my-app-container my-image
-
systemd 서비스 유닛 파일 생성
podman generate systemd --name my-app-container --files --restart-policy=always
이 명령은 현재 디렉토리에 .service 파일을 생성합니다. 예를 들어:
container-my-app-container.service
-
systemd 디렉토리로 복사
sudo cp container-my-app-container.service /etc/systemd/system/
-
서비스 등록 및 자동 시작 설정
sudo systemctl daemon-reexec
sudo systemctl enable --now container-my-app-container.service
✅ 방법 2: Podman pod을 사용하고 pod 기준으로 systemd 설정
Podman pod을 사용할 경우에도 동일하게 podman generate systemd --name mypod로 유닛을 만들고 등록할 수 있습니다.
Apache Nifi
Nifi를 설치하고
- 기본은 https 접속임 conf/nifi.properties
- 기본은 single user 접속임. 사용자 설정가이드
- 사용자 비번은 12자리 이상이며 설정했으면 한 번 리스타트 해야 적용됨.
gcp web_analytics sample schema
GCP의 Web Analytics 샘플 데이터셋은 BigQuery에서 제공되는 Google Analytics 360 샘플 데이터로, 다음 테이블에 존재합니다:
bigquery-public-data.google_analytics_sample.ga_sessions_*
이 데이터는 Google Analytics의 방문 세션(ga_sessions)을 기준으로 구성되어 있으며, **중첩된 구조 (RECORD)**와 **반복 필드 (REPEATED)**를 포함합니다.
🧩 샘플 스키마 요약 (상위 수준)
✅ 기본 필드
| 필드명 | 타입 | 설명 |
|---|---|---|
fullVisitorId |
STRING | 고유 방문자 ID |
visitId |
INTEGER | 세션 ID |
visitNumber |
INTEGER | 방문 순서 (ex: 첫 방문 = 1) |
visitStartTime |
INTEGER | UNIX timestamp |
date |
STRING | YYYYMMDD 형식 날짜 |
✅ RECORD 필드 (중첩 구조)
trafficSource (RECORD)
| 필드명 | 타입 |
|---|---|
| source | STRING |
| medium | STRING |
| campaign | STRING |
| keyword | STRING |
| adContent | STRING |
device (RECORD)
| 필드명 | 타입 |
|---|---|
| browser | STRING |
| operatingSystem | STRING |
| isMobile | BOOLEAN |
| deviceCategory | STRING |
geoNetwork (RECORD)
| 필드명 | 타입 |
|---|---|
| continent | STRING |
| country | STRING |
| city | STRING |
totals (RECORD)
| 필드명 | 타입 |
|---|---|
| visits | INTEGER |
| hits | INTEGER |
| pageviews | INTEGER |
| bounces | INTEGER |
| transactions | INTEGER |
| transactionRevenue | INTEGER |
✅ hits 필드 (REPEATED RECORD)
1개의 세션 내 여러 행동(페이지뷰, 이벤트 등)이 기록됩니다.
rmse가 낮다는 것은 어떤 의미인가?
RMSE(Root Mean Square Error)가 낮다는 것은 다음과 같은 의미를 갖습니다:
✅ 1. 예측 정확도가 높다
- RMSE는 예측값과 실제값 사이의 평균적인 오차 크기를 나타냅니다.
- 따라서 RMSE가 낮다는 것은:
- 모델의 예측값이 실제값과 더 가깝다는 뜻이고,
- 모델이 정확한 예측을 하고 있다는 것을 의미합니다.
✅ 2. 큰 오차가 적다
- RMSE는 오차를 제곱해서 평균을 내기 때문에, 큰 오차일수록 더 큰 패널티를 받습니다.
- 따라서 RMSE가 낮다는 것은:
- 단순히 평균 오차가 작은 것뿐 아니라,
- **큰 오차(이상치)**가 별로 없다는 의미도 됩니다.
✅ 3. 모델이 과적합(Overfitting)되지 않았을 수 있다
- 훈련 데이터에서 RMSE가 낮고, 검증 데이터에서도 낮다면 → 모델이 잘 일반화되었다는 신호입니다.
❗주의할 점
- RMSE는 단위에 민감하므로, 다른 모델들과 비교할 때는 반드시 같은 단위/데이터 기준에서 비교해야 합니다.
- RMSE만 보고 성능을 판단하는 것은 위험할 수 있으니, MAE, R², 잔차분석 등과 함께 보는 것이 좋습니다.
예시로,
WHERE RAND() < 0.001
WHERE RAND() < 0.001은 SQL에서 **표본 추출 (sampling)**을 할 때 자주 사용하는 패턴입니다. 이 조건의 의미는 다음과 같습니다:
✅ 의미
WHERE RAND() < 0.001
RAND()는 0과 1 사이의 난수를 반환합니다.RAND() < 0.001은 약 0.1% 확률로 TRUE가 됩니다.- 따라서 이 조건을 만족하는 약 0.1%의 행(row) 만 필터링되어 결과에 포함됩니다.
✅ 용도
- 테스트용 샘플 데이터 추출
- 대용량 테이블에서 분석하거나 디버깅할 때 전체 데이터를 쓰지 않고 일부만 뽑기 위함
- 랜덤 서브셋 생성
- 데이터 균형 확인, 속도 향상 등
✅ 예제
SELECT *
FROM big_table
WHERE RAND() < 0.001;
→ big_table에서 무작위로 약 0.1% 행을 추출합니다.
CREATE_MODEL 진행상태 확인
BigQuery에서 create model을 실행 후
This query will process 41.76 MB (ML) when run. Depending on the model type and training data size, the training job can take minutes or even hours.
이런 메시지가 하단에 출력되고는, 이 녀석이 진행중인지 도통 알수가 없는 상태가 되어, 혹시나 하고 진헹상태를 찾아볼수 있는가 싶었지만.
SELECT
job_id,
state,
creation_time,
start_time,
end_time,
error_result
FROM
`region-us`.INFORMATION_SCHEMA.JOBS_BY_USER
WHERE
job_type = 'QUERY'
AND statement_type = 'CREATE_MODEL'
ORDER BY
creation_time DESC
LIMIT 10;
역시나 결과가 안 나온다.
ML.FEATURE_CROSS
좋은 질문입니다!
ML.FEATURE_CROSS()와 CONCAT()는 비슷한 결과를 내지만, 목적과 내부 처리 방식에서 차이가 있습니다.
✅ 공통점
둘 다 **여러 문자열 피처를 결합(cross)**해서 새로운 하나의 피처를 만듭니다.
예:
CONCAT('US', '_', 'mobile') → 'US_mobile'
ML.FEATURE_CROSS(['US', 'mobile']) → 'US_mobile'
❗ 차이점 요약
| 항목 | ML.FEATURE_CROSS() |
CONCAT() |
|---|---|---|
| 목적 | 머신러닝 특화: 교차 피처 생성 | 일반적인 문자열 연결 |
| 자동 최적화 | 내부적으로 범주형 피처로 자동 처리 | 단순한 문자열, 모델에선 수치형 취급될 수도 |
| 입력 타입 제한 | STRING 또는 BYTES만 허용 | 다양한 타입 지원 (숫자, 날짜 등 가능) |
| 모델 의도 표현 | “이건 feature crossing이다"라고 명시적 표현 | 단순 연결 → 모델이 교차 피처인지 모름 |
| 해시 처리 지원 | 내부적으로 가능 (옵션 없음, 향후 지원 가능) | 없음 |
🧠 실전 팁
- 모델에 교차 피처임을 명확히 알리고 싶을 때 →
ML.FEATURE_CROSS()사용 - 그냥 텍스트 가공이나 임시 출력용 →
CONCAT()사용
✅ 예제 비교
-- 교차 피처로 학습 시
ML.FEATURE_CROSS([country, device_category]) AS crossed_feature
-- 단순 문자열 가공 (모델은 수치형으로 오해할 수도 있음)
CONCAT(country, '_', device_category) AS crossed_feature
둘 다 같은 문자열 'US_mobile'을 만들지만, 모델이 인식하는 방식은 다릅니다.

