반응형

SQL에서도 집합 이론이 적용됩니다!

두 개 이상의 SELECT 결과를 합치거나 비교할 때 쓰이는 연산자들,

UNION, UNION ALL, INTERSECT, MINUS(또는 EXCEPT)를 실습 예제와 함께 배워봅시다!


🧪 실습용 테이블 만들기

-- 고객 테이블 A
CREATE TABLE customers_domestic (
  cust_id INT,
  cust_name VARCHAR(50)
);

-- 고객 테이블 B
CREATE TABLE customers_foreign (
  cust_id INT,
  cust_name VARCHAR(50)
);

-- 샘플 데이터 삽입
INSERT INTO customers_domestic VALUES
(1, '홍길동'),
(2, '김영희'),
(3, '이철수');

INSERT INTO customers_foreign VALUES
(2, '김영희'),
(3, '이철수'),
(4, '존스미스'),
(5, '마이클');

 

🎯 포인트 요약

  • customers_domestic → 국내 고객 목록
  • customers_foreign → 해외 고객 목록
  • 일부 고객은 두 테이블에 중복으로 존재함

1️⃣  UNION : 중복 제거한 합집합

SELECT cust_id, cust_name FROM customers_domestic
UNION
SELECT cust_id, cust_name FROM customers_foreign;

 

🧠 설명

  • UNION중복을 제거한 합집합을 반환
  • 결과는 자동으로 정렬(O)
  • 홍길동, 김영희, 이철수, 존스미스, 마이클 총 5명 나옴

 

2️⃣  UNION ALL : 중복 포함한 합집합

SELECT cust_id, cust_name FROM customers_domestic
UNION ALL
SELECT cust_id, cust_name FROM customers_foreign;

 

🧠 설명

  • UNION ALL중복을 제거하지 않고 그냥 다 합쳐버림
  • 위 예시 기준으로는 김영희, 이철수2번씩 나옴
  • 성능 면에서도 UNION ALL이 더 빠름 (중복 체크 안 함)

 

3️⃣  INTERSECT : 교집합 (양쪽에 모두 있는 행)

SELECT cust_id, cust_name FROM customers_domestic
INTERSECT
SELECT cust_id, cust_name FROM customers_foreign;

 

🧠 설명

  • 두 테이블 모두에 존재하는 공통 행만 추출
  • 여기선 김영희, 이철수만 나옴
  • 중복은 자동 제거
⚠️ MySQL은 INTERSECT, MINUS를 기본 지원하지 않음
➜ MariaDB, Oracle, PostgreSQL 사용 시 OK
➜ MySQL에서는 JOIN + DISTINCT 으로 대체 가능

 

4️⃣  MINUS : 차집합 (왼쪽엔 있지만 오른쪽엔 없는)

SELECT cust_id, cust_name FROM customers_domestic
MINUS
SELECT cust_id, cust_name FROM customers_foreign;

 

🧠 설명

  • 왼쪽 테이블에는 있지만, 오른쪽 테이블에는 없는 순수 국내 고객만 추출
  • 결과: 홍길동만 나옴

 

5️⃣  EXCEPT : MINUS와 동일 (PostgreSQL 스타일)

SELECT cust_id, cust_name FROM customers_domestic
EXCEPT
SELECT cust_id, cust_name FROM customers_foreign;

 

🧠 설명

  • MINUS 대신 쓰이는 동일 기능의 키워드
  • PostgreSQL에서는 EXCEPT만 지원하고, MINUS는 없음

🧾 한눈에 보는 집합 연산자 비교표

연산자 중복 제거 결과 설명
UNION O 합집합 두 쿼리 결과를 하나로 합치되, 중복은 제거
UNION ALL X 합집합 중복까지 전부 포함하여 합침
INTERSECT O 교집합 양쪽 쿼리에 모두 있는 행만 추출
MINUS O 차집합 왼쪽엔 있지만 오른쪽엔 없는 행만 추출
EXCEPT O 차집합 MINUS와 같지만 PostgreSQL 등에서 사용

💡 실무 TIPS

  • UNION ALL중복 제거 로직이 없어서 빠르다 → 성능이 중요한 경우 사용 고려
  • INTERSECT, MINUS는 MySQL 미지원! JOIN이나 NOT EXISTS로 대체해야 함
  • SELECT 컬럼 수와 타입이 양쪽 쿼리에서 동일해야 집합 연산이 가능
반응형
반응형

서브쿼리는 쿼리 안에 또 다른 SELECT 쿼리가 포함된 구조로,

복잡한 데이터 처리를 간단하고 유연하게 해줍니다.

그 중에서도 자주 쓰이는 3가지 유형, 실습 예제와 함께 마스터해봅시다!


🔧 실습용 테이블 생성

-- 사원 테이블
CREATE TABLE employees (
  emp_id INT PRIMARY KEY,
  emp_name VARCHAR(50),
  dept_id INT,
  salary INT
);

-- 부서 테이블
CREATE TABLE departments (
  dept_id INT PRIMARY KEY,
  dept_name VARCHAR(50)
);

-- 샘플 데이터
INSERT INTO departments VALUES (10, '개발부'), (20, '영업부'), (30, '인사부');

INSERT INTO employees VALUES
(1, '홍길동', 10, 5000),
(2, '김영희', 10, 6000),
(3, '이철수', 20, 5500),
(4, '박민수', 30, 4800),
(5, '최수지', 20, 6200);

1️⃣ 스칼라 서브쿼리 (Scalar Subquery)

하나의 값만 반환하는 서브쿼리를 칼럼처럼 사용하는 방식
SELECT emp_name,
       salary,
       (SELECT AVG(salary) FROM employees) AS avg_salary
FROM employees;

🧠 설명:

각 사원의 급여와 전체 평균 급여를 나란히 출력하는 예시입니다.

서브쿼리는 전체 평균 AVG(salary)를 계산해서 하나의 값(스칼라 값) 으로 반환합니다.


2️⃣ 인라인 뷰 (Inline View)

FROM 절에 사용되는 서브쿼리, 일시적인 테이블처럼 사용 가능
SELECT dept_id, avg_salary
FROM (
    SELECT dept_id, AVG(salary) AS avg_salary
    FROM employees
    GROUP BY dept_id
) AS dept_avg;

🧠 설명:

이 쿼리는 부서별 평균 급여를 계산한 뒤,

해당 결과를 dept_avg라는 가상 테이블처럼 활용하는 구조입니다.

인라인 뷰 = 서브쿼리를 마치 테이블처럼 쓰는 것!


3️⃣ 중첩 서브쿼리 (Nested Subquery)

WHERE 절 안에 서브쿼리가 포함된 구조
SELECT emp_name, salary
FROM employees
WHERE dept_id = (
    SELECT dept_id
    FROM departments
    WHERE dept_name = '개발부'
);

🧠 설명:

개발부 소속 사원만 조회”하는 예시입니다.

부서 이름을 기준으로 dept_id를 찾고, 그 값을 메인 쿼리에 넘겨주는 방식!

한 번에 두 테이블을 JOIN 하지 않고, 단계적으로 필터링할 수 있는 장점이 있죠.

 

🔄 중첩 서브쿼리 – 단일행 vs 다중행

서브쿼리는 WHERE, HAVING, SELECT, FROM 절 등 어디서든 사용할 수 있지만,

그 중 WHERE 절에서 조건으로 쓰일 때, 반환되는 행의 수에 따라 나뉘어요

구분 반환값 비교 연산자 사용 예
단일행 서브쿼리 1행 1열 =, >, <, >=, <=, != 평균보다 높은 사원 찾기
다중행 서브쿼리 여러 행 IN, ANY, ALL, EXISTS 특정 조건의 부서에 속한 사원 찾기

 

🔸 단일행 서브쿼리 예제

전체 평균 급여보다 높은 급여의 사원 조회
SELECT emp_name, salary
FROM employees
WHERE salary > (
  SELECT AVG(salary)
  FROM employees
);

📌 설명:

서브쿼리가 AVG(salary) 하나의 값을 반환 → salary > 단일값 비교 가능

👉 단일행 서브쿼리!

 

🔸 다중행 서브쿼리 예제 - IN

영업부와 인사부에 소속된 사원 조회
SELECT emp_name, dept_id
FROM employees
WHERE dept_id IN (
  SELECT dept_id
  FROM departments
  WHERE dept_name IN ('영업부', '인사부')
);

📌 설명:

서브쿼리가 부서 ID 여러 개 반환IN으로 다중값 비교

👉 다중행 서브쿼리!

 

🔸 다중행 서브쿼리 예제 - ANY / ALL

모든 부서 중 최소 급여보다 높은 사원 찾기
SELECT emp_name, salary
FROM employees
WHERE salary > ALL (
  SELECT MIN(salary)
  FROM employees
  GROUP BY dept_id
);

📌 설명:

employees를 부서별로 MIN(salary) 추출 → 여러 값 반환

> ALL (값1, 값2, 값3) → 그 모든 값보다 커야 참이 됨

👉 다중행 서브쿼리 + ALL 사용!

 

🧠 참고: ANY vs ALL 차이

연산자 의미
> ANY 최소 하나보다 크면 됨 (최소조건 만족)
> ALL 모두보다 커야 함 (최대조건 만족)

 

✅ 정리 요약표

유형 반환 행 수 대표 연산자 사용 위치
단일행 서브쿼리 1행 1열 =, >, < 등 WHERE, SELECT
다중행 서브쿼리 N행 IN, ANY, ALL, EXISTS WHERE, HAVING 등

✅ 마무리 요약

구분 위치 반환값 용도
스칼라 서브쿼리 SELECT절 단일값 칼럼처럼 사용하여 부가 정보 붙일 때 사용
인라인 뷰 FROM절 테이블 형태 서브쿼리 결과를 테이블처럼 가공하고 재사용
중첩 서브쿼리 WHERE절 등 조건식에 사용 조건에 맞는 값을 찾아 필터링

🧪 실습 팁

  • 서브쿼리는 항상 () 괄호로 감쌈
  • 스칼라 쿼리는 반드시 단일 값을 반환해야 에러가 나지 않음
  • 인라인 뷰는 alias 별칭 필수!
  • 중첩 쿼리는 IN, EXISTS, = 등을 함께 자주 사용

🧠 실전 예제 더 보고 싶다면?

“부서 평균 급여보다 많이 받는 사원은?”
SELECT emp_name, salary
FROM employees e
WHERE salary > (
    SELECT AVG(salary)
    FROM employees
    WHERE dept_id = e.dept_id
);
반응형
반응형
"데이터베이스에서 '조인'을 모르면, 데이터를 반쪽만 보는 거예요!"
이제부터 조인을 쉽고 확실하게 배워봅시다! 🚀

🤔 조인이란?

조인은 두 개 이상의 테이블을 연결해서 하나의 결과로 만들어주는 SQL 기능이에요.

📦 테이블 1 (부서 정보)
📦 테이블 2 (직원 정보)
➡️ 이 둘을 조인하면, "직원이 어느 부서에 속해있는지"를 알 수 있게 되죠!


📌 조인이 필요한 이유

하나의 테이블에 모든 데이터가 다 들어있지 않기 때문이에요!

예를 들어, employees 테이블엔 직원 정보가 있지만,
departments 테이블에만 부서명이 있어요.

그래서 이런 데이터를 얻고 싶다면?

"홍길동 사원은 총무부 소속이다."

👉 두 테이블을 연결(JOIN)해야 합니다!


🧱 조인의 종류 (SQLD 시험 핵심)

조인 종류 설명 대표 예시
🔹 INNER JOIN 두 테이블에서 공통되는 값이 있는 경우만 조회 가장 자주 쓰임
🔸 OUTER JOIN 한쪽에는 데이터가 있고, 다른 쪽은 없어도 조회 LEFT / RIGHT / FULL
🔻 SELF JOIN 자기 자신과 조인 계층형 구조에서
🔺 CROSS JOIN 모든 행 조합 (카티션 곱) 잘 안 씀 (주의!)

✅ 1. INNER JOIN (교집합 조인)

두 테이블에서 조건이 일치하는 행만 연결합니다.

SELECT e.emp_name, d.dept_name
FROM employees e
JOIN departments d
  ON e.dept_id = d.dept_id;

🧠 설명:

  • 직원 테이블과 부서 테이블에서 dept_id가 일치하는 행만 조인
  • SQLD 기출 최다 등장 조인!

✅ 2. LEFT OUTER JOIN (왼쪽 기준 조인)

왼쪽 테이블의 모든 행 + 오른쪽 테이블에 일치하는 데이터만 가져옵니다.
→ 오른쪽 테이블에 없으면 NULL

SELECT e.emp_name, d.dept_name
FROM employees e
LEFT JOIN departments d
  ON e.dept_id = d.dept_id;

🧠 설명:

  • 직원은 있는데 부서가 없는 경우도 모두 보고 싶을 때 사용

✅ 3. RIGHT OUTER JOIN (오른쪽 기준 조인)

오른쪽 테이블의 모든 행 + 왼쪽 테이블에 일치하는 데이터만 가져옵니다.

SELECT e.emp_name, d.dept_name
FROM employees e
RIGHT JOIN departments d
  ON e.dept_id = d.dept_id;

🧠 설명:

  • 모든 부서를 보여주되, 직원이 없는 부서도 포함!

✅ 4. FULL OUTER JOIN (전체 기준 조인)

두 테이블의 모든 행을 다 가져옴!
조건이 맞지 않아도 NULL 채워서 보여줌.

SELECT e.emp_name, d.dept_name
FROM employees e
FULL OUTER JOIN departments d
  ON e.dept_id = d.dept_id;

📌 일부 DBMS는 FULL JOIN 지원하지 않음 (예: MySQL)


✅ 5. SELF JOIN (자기 자신과 조인)

테이블 안에서 상사-직원 관계 같은 걸 표현할 때 쓰는 기법

SELECT e.emp_name, m.emp_name AS manager_name
FROM employees e
JOIN employees m
  ON e.manager_id = m.emp_id;

🧠 설명:

  • employees 테이블을 e, m으로 두 번 부른 후,
  • 매니저 ID를 통해 자기 자신과 연결!

📝 SQLD 시험 꿀팁 요약

항목 내용
INNER JOIN 가장 기본! 조건 만족하는 행만
LEFT JOIN 왼쪽이 기준. 오른쪽에 NULL 허용
RIGHT JOIN 오른쪽이 기준
FULL JOIN 양쪽 모두 포함
SELF JOIN 자기 자신과 연결. 별칭 필수
JOIN 순서 FROM → JOIN → ON → WHERE → ORDER BY
반응형
반응형
데이터를 가져올 때, 조건 없이 SELECT를 쓰는 건 양동이로 바닷물 뜨는 거랑 같아요 🌊
그래서 필요한 게 바로 WHERE 절! 🎯

✅ WHERE 절이란?

WHERE 절은 SQL에서 특정 조건에 맞는 행(Row)만 필터링할 때 사용합니다.
SELECT, UPDATE, DELETE, 등 데이터를 건드리는 모든 SQL문에서 함께 사용됩니다.

SELECT * FROM employees
WHERE department_id = 10;
✅ 위 쿼리는 employees 테이블에서 부서 ID가 10인 직원만 조회합니다.

🧩 WHERE 절의 문법 구조

SELECT 컬럼명
FROM 테이블명
WHERE 조건식;

📌 조건식에는 비교연산자, 논리연산자, 함수 등 다양하게 들어갈 수 있어요!


🔍 WHERE 절에서 자주 쓰이는 연산자

📌 1. 비교 연산자

연산자 의미 예시
= 같다 WHERE job_id = 'SA_REP'
!=, <> 같지 않다 WHERE dept_id <> 50
> 초과 WHERE salary > 5000
< 미만 WHERE salary < 3000
>= 이상 WHERE salary >= 10000
<= 이하 WHERE salary <= 5000

 

📌 2. 논리 연산자

연산자 설명 예시
AND 모두 참일 때 WHERE dept_id = 50 AND salary > 3000
OR 하나라도 참이면 WHERE job_id = 'SA_REP' OR job_id = 'IT_PROG'
NOT 조건의 부정 WHERE NOT department_id = 10

 

📌 3. BETWEEN A AND B

  • A 이상 B 이하의 범위를 지정할 때 사용
WHERE salary BETWEEN 3000 AND 5000

 

📌 4. IN (집합)

  • 여러 값 중 일치하는 것이 있으면 참
WHERE department_id IN (10, 20, 30)

 

📌 5. LIKE (패턴 매칭)

  • 문자열 비교 시 와일드카드 문자 사용
와일드카드 의미
% 0개 이상의 문자
_ 정확히 1개 문자
WHERE first_name LIKE 'A%'    -- A로 시작
WHERE email LIKE '%@gmail%'   -- gmail이 포함된 것
WHERE emp_name LIKE '_Kim'    -- 앞에 한 글자 + Kim

 

📌 6. IS NULL / IS NOT NULL

  • NULL 값인지 확인할 때 사용
WHERE manager_id IS NULL
WHERE commission_pct IS NOT NULL

 

🔥 실전 예제

SELECT first_name, salary, department_id
FROM employees
WHERE salary >= 5000 
  AND department_id IN (10, 20)
  AND hire_date BETWEEN TO_DATE('2020-01-01', 'YYYY-MM-DD') AND SYSDATE
ORDER BY salary DESC;

 

📌 해석

  • 급여가 5000 이상이고
  • 부서가 10번이나 20번이며
  • 입사일이 2020년 이후인 직원들을
  • 급여 내림차순으로 조회합니다.

 

⚠️ 시험에서 자주 나오는 WHERE 팁!

유형
WHERE vs HAVING WHERE은 행 필터링, HAVING은 그룹 필터링
NULL 비교 = 대신 반드시 IS NULL 사용
범위 BETWEEN은 포함형 (A ≤ x ≤ B)
LIKE 검색 %, _의 위치에 주의
중첩 조건 괄호로 조건 그룹화 ((A AND B) OR C)

 

✅ 마무리 정리

  • WHERE 절은 데이터 필터링의 중심입니다.
  • 비교 연산자, 논리 연산자, NULL 체크, 패턴 검색을 자유자재로 활용할 수 있어야 해요!
  • SELECT, UPDATE, DELETE에서 다 쓰이므로 기출에서도 출현율 최상위 🎯
반응형
반응형
“SQL을 안다는 건 SELECT 절을 마스터했다는 뜻이다!”

 

안녕하세요! SQLD 시험을 준비하시는 여러분을 위해 오늘은 SQL의 핵심 중의 핵심, SELECT 절에 대해 자세히 정리해드릴게요.

SQL의 시작이자 끝이라 불릴 정도로 중요하니, 이 포스팅 하나로 SELECT 절을 완전 정복해봅시다 💪


✅  SELECT 절이란?

SELECT는 데이터베이스에서 원하는 데이터를 조회할 때 사용하는 명령입니다.

기본 구조는 다음과 같아요

SELECT 컬럼명
FROM 테이블명
WHERE 조건
GROUP BY 그룹컬럼
HAVING 그룹조건
ORDER BY 정렬기준

📌 SELECT 절의 구성 요소와 순서

SQL 작성 순서SQL 실행 순서는 다릅니다.

1. SELECT 1. FROM
2. FROM 2. WHERE
3. WHERE 3. GROUP BY
4. GROUP BY 4. HAVING
5. HAVING 5. SELECT
6. ORDER BY 6. ORDER BY

🧩 각 절의 상세 설명

🟡  SELECT

  • 반환하고자 하는 컬럼을 지정합니다.
  • 컬럼명 또는 계산식, 별칭 사용 가능
SELECT name, salary, salary * 0.1 AS bonus
FROM employees;

🟢  FROM

  • 데이터를 가져올 테이블이나 뷰를 지정합니다.
  • 조인(Join)도 이 절에서 사용돼요.
FROM employees
JOIN departments ON employees.dept_id = departments.dept_id

🔵  WHERE

  • 행(Row) 단위의 조건을 지정합니다.
  • 단일 행 함수 사용 가능, GROUP BY 전에 사용
WHERE salary > 3000 AND department_id = 10

🟣  GROUP BY

  • 그룹 함수(SUM, AVG, COUNT 등)와 함께 사용해 데이터를 그룹화합니다.
SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id
🔥 SELECT에 나오는 컬럼 중, 그룹 함수가 아닌 컬럼은 반드시 GROUP BY에 포함되어야 해요!

🔴  HAVING

  • 그룹화된 결과에 대해 조건을 지정합니다.
  • WHERE과 달리 그룹 함수 사용 가능!
HAVING AVG(salary) > 5000

🟠  ORDER BY

  • 조회 결과를 정렬합니다.
  • 기본은 오름차순(ASC), 내림차순은 DESC
ORDER BY salary DESC

💡 실전 꿀팁: SELECT 자주 나오는 개념

DISTINCT 중복 제거
AS 컬럼 별칭 (가독성 향상)
LIMIT / ROWNUM 결과 행 수 제한 (DBMS 따라 다름)
서브쿼리 SELECT 안에 또 SELECT

 예제: SELECT 절 종합 문제

SELECT d.department_name, COUNT(e.employee_id) AS 인원수, AVG(e.salary) AS 평균급여
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE e.salary > 3000
GROUP BY d.department_name
HAVING AVG(e.salary) >= 5000
ORDER BY 평균급여 DESC;


위 쿼리는 다음을 의미합니다


✅ 급여가 3000 초과인 직원들만
✅ 부서별로 그룹화해서
✅ 평균 급여가 5000 이상인 부서만 추려서
✅ 평균급여 내림차순으로 정렬!

 


📝 자주 나오는 SELECT 문제 유형 (시험 대비)

실행 순서 문제 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
GROUP BY 필수조건 SELECT에 있는 컬럼 중, 그룹 함수 아닌 것들은 반드시 GROUP BY 포함
HAVING vs WHERE HAVING은 그룹함수 필터링, WHERE은 일반 필터링
별칭 사용 주의 ORDER BY에서는 AS 별칭 사용 가능 (ORDER BY 평균급여 DESC)
반응형
반응형

안녕하세요! 😄 SQLD(SQL 개발자 자격증) 시험을 준비하면서 꼭 알아야 하는 SQL 함수들을 정리해보았습니다.

 

SQL 함수는 실제 시험에서 직접 사용 예시나 결과값을 묻는 문제가 자주 나오기 때문에, 정리하고 외우고 실습까지 해야 합니다. SQL 함수들을 체계적으로 정리하도록 하겠습니다 :)

 


📌 SQL 함수란?

 

SQL 함수는 입력값을 받아서 계산된 값을 반환하는 기능입니다.

크게 아래 두 가지로 나뉘어요

✅ 단일 행 함수 한 행마다 1개의 결과를 반환 (문자, 숫자, 날짜 등)
✅ 그룹 함수 여러 행을 묶어 하나의 결과를 반환 (SUM, COUNT 등)

 


🟦 문자열 함수 (Character Function)

문자열 함수는 텍스트 데이터를 다룰 때 사용하는 함수입니다.

 

 LOWER(string)

문자열을 모두 소문자로 변환합니다.
SELECT LOWER('SQLD Exam') FROM DUAL;
-- 결과: 'sqld exam'
  • 대소문자 민감한 조건 비교 전에 LOWER() 또는 UPPER()로 통일해서 비교하는 데 유용합니다.

 

 UPPER(string)

문자열을 모두 대문자로 변환합니다.
SELECT UPPER('sql developer') FROM DUAL;
-- 결과: 'SQL DEVELOPER'

 LENGTH(string)

문자열의 길이(문자 수)를 반환합니다.
SELECT LENGTH('오라클') FROM DUAL;
-- 결과: 3 (한글도 1자씩 계산됨)

 SUBSTR(string, start, length)

문자열의 특정 위치에서 시작하여 일정 길이만큼 잘라냅니다.
SELECT SUBSTR('ORACLEDB', 2, 4) FROM DUAL;
-- 결과: 'RACL'
  • start는 1부터 시작, 음수일 경우 뒤에서부터 시작합니다.
  • length는 생략하면 끝까지 추출됩니다.

 INSTR(string, substring)

특정 문자열이 처음 등장하는 위치를 반환합니다.
SELECT INSTR('DATABASE', 'A') FROM DUAL;
-- 결과: 2 (맨 앞에서부터 찾음)

 TRIM(['char' FROM] string)

문자열 앞뒤의 특정 문자를 제거합니다. 기본은 공백 제거.
SELECT TRIM('  Hello  ') FROM DUAL;
-- 결과: 'Hello'
SELECT TRIM('0' FROM '000123000') FROM DUAL;
-- 결과: '123'

 LPAD(string, total_length, pad_char)

문자열 왼쪽에 특정 문자를 채워 길이를 맞춥니다.
SELECT LPAD('123', 5, '0') FROM DUAL;
-- 결과: '00123'

 RPAD(string, total_length, pad_char)

문자열 오른쪽에 문자를 채워 길이를 맞춥니다.
SELECT RPAD('A', 4, '*') FROM DUAL;
-- 결과: 'A***'

 REPLACE(string, old, new)

문자열에서 특정 문자 또는 단어를 다른 것으로 바꿉니다.
SELECT REPLACE('abcabc', 'a', 'X') FROM DUAL;
-- 결과: 'XbcXbc'

🟨  숫자 함수 (Number/Math Functions)

숫자 데이터를 다룰 때 사용되는 함수입니다.

 

 ABS(n)

절댓값을 반환합니다.
SELECT ABS(-10) FROM DUAL;
-- 결과: 10

 CEIL(n)

소수점이 존재하면 올림합니다.
SELECT CEIL(3.01) FROM DUAL;
-- 결과: 4

 FLOOR(n)

소수점이 존재하면 **버림(내림)**합니다.
SELECT FLOOR(3.99) FROM DUAL;
-- 결과: 3

 ROUND(n, d)

지정한 소수점 자릿수까지 반올림합니다.
SELECT ROUND(123.4567, 2) FROM DUAL;
-- 결과: 123.46

 TRUNC(n, d)

지정한 자릿수까지 버림합니다.
SELECT TRUNC(123.4567, 2) FROM DUAL;
-- 결과: 123.45

 MOD(m, n)

mn으로 나눈 나머지를 반환합니다.
SELECT MOD(10, 3) FROM DUAL;
-- 결과: 1

 POWER(x, y)

x의 y제곱을 반환합니다.
SELECT POWER(2, 3) FROM DUAL;
-- 결과: 8

🟩  날짜 함수 (Date Functions)

날짜와 시간 관련 데이터를 처리하는 데 사용하는 함수입니다.

 

 SYSDATE

현재 시스템의 날짜와 시간 반환
SELECT SYSDATE FROM DUAL;

 ADD_MONTHS(date, n)

지정한 날짜에 n개월을 더한 날짜 반환
SELECT ADD_MONTHS(SYSDATE, 3) FROM DUAL;

 MONTHS_BETWEEN(d1, d2)

두 날짜 간의 개월 수 차이 계산
SELECT MONTHS_BETWEEN('2025-05-01', '2025-01-01') FROM DUAL;
-- 결과: 4

 LAST_DAY(date)

해당 월의 마지막 날짜 반환
SELECT LAST_DAY(SYSDATE) FROM DUAL;

 NEXT_DAY(date, '요일')

해당 요일의 다음 날짜 반환
SELECT NEXT_DAY(SYSDATE, 'MONDAY') FROM DUAL;

 TRUNC(date, 'fmt')

날짜의 특정 단위를 기준으로 자름
SELECT TRUNC(SYSDATE, 'MM') FROM DUAL;
-- 결과: 이번달 1일

🟪  변환 함수 (Conversion Functions)

데이터 타입을 서로 변환할 수 있는 함수입니다.

 

 TO_CHAR(date/number, 'format')

날짜 또는 숫자를 문자로 변환
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM DUAL;

 TO_DATE(string, 'format')

문자열을 날짜로 변환
SELECT TO_DATE('2025-01-01', 'YYYY-MM-DD') FROM DUAL;

 TO_NUMBER(string)

문자열을 숫자로 변환
SELECT TO_NUMBER('1000') + 500 FROM DUAL;
-- 결과: 1500

 CAST(expression AS TYPE)

표현식을 원하는 타입으로 변환
SELECT CAST('123' AS NUMBER) + 10 FROM DUAL;
-- 결과: 133

🟥 조건 함수

 

 DECODE(column, value1, result1, value2, result2, ..., default)

일종의 IF문처럼 작동하며, 조건값과 비교해 결과 반환
SELECT DECODE(GENDER, 'M', '남자', 'F', '여자', '기타') FROM USERS;

 CASE WHEN THEN ELSE END

보다 유연한 조건 분기 처리가 가능한 함수
SELECT 
  CASE 
    WHEN SCORE >= 90 THEN 'A'
    WHEN SCORE >= 80 THEN 'B'
    ELSE 'F'
  END AS GRADE
FROM STUDENT;

🟧 그룹 함수 (집계 함수)

여러 행을 집계하여 하나의 결과를 만듭니다. GROUP BY, HAVING절과 함께 자주 쓰임.
SUM() 총합 계산
AVG() 평균 계산
COUNT() 행 수 계산
MAX() 최댓값
MIN() 최솟값
SELECT DEPT_ID, COUNT(*) AS 인원수
FROM EMPLOYEES
GROUP BY DEPT_ID;

🟧  정리

 

함수 종류 함수명 설명 예시
문자열 LOWER(str) 소문자로 변환 LOWER('ABC') → 'abc'
문자열 UPPER(str) 대문자로 변환 UPPER('abc') → 'ABC'
문자열 LENGTH(str) 문자열 길이 LENGTH('SQLD') → 4
문자열 SUBSTR(str, m, n) 문자 추출 SUBSTR('ORACLE', 2, 3) → 'RAC'
문자열 INSTR(str, find) 문자 위치 INSTR('ORACLE', 'A') → 3
문자열 TRIM(char FROM str) 앞뒤 문자 제거 TRIM('0' FROM '00100') → '1'
문자열 LPAD(str, n, pad) 왼쪽 채움 LPAD('12', 5, '0') → '00012'
문자열 RPAD(str, n, pad) 오른쪽 채움 RPAD('A', 3, '-') → 'A--'
문자열 REPLACE(str, a, b) 문자열 치환 REPLACE('AABB', 'B', 'C') → 'AACC'
숫자 ABS(n) 절댓값 ABS(-3) → 3
숫자 CEIL(n) 올림 CEIL(2.1) → 3
숫자 FLOOR(n) 내림 FLOOR(2.9) → 2
숫자 ROUND(n, d) 반올림 ROUND(3.456, 2) → 3.46
숫자 TRUNC(n, d) 버림 TRUNC(3.456, 2) → 3.45
숫자 MOD(m, n) 나머지 MOD(10, 3) → 1
숫자 POWER(x, y) 제곱 POWER(2, 3) → 8
날짜 SYSDATE 현재 날짜 SYSDATE
날짜 ADD_MONTHS(d, n) n개월 후 ADD_MONTHS(SYSDATE, 1)
날짜 MONTHS_BETWEEN(d1, d2) 개월 차이 MONTHS_BETWEEN('2025-05-01', '2025-01-01')
날짜 LAST_DAY(date) 월 말일 LAST_DAY(SYSDATE)
날짜 NEXT_DAY(date, 요일) 다음 요일 NEXT_DAY(SYSDATE, 'MONDAY')
날짜 TRUNC(date, fmt) 날짜 자르기 TRUNC(SYSDATE, 'MM')
변환 TO_CHAR(date, fmt) 날짜 → 문자 TO_CHAR(SYSDATE, 'YYYY-MM-DD')
변환 TO_DATE(str, fmt) 문자 → 날짜 TO_DATE('2025-01-01', 'YYYY-MM-DD')
변환 TO_NUMBER(str) 문자 → 숫자 TO_NUMBER('100')
변환 CAST(expr AS type) 형 변환 CAST('123' AS NUMBER)
조건 DECODE(col, val, res) 조건 분기 DECODE(GENDER, 'M', '남')
조건 CASE WHEN THEN 조건 분기 CASE WHEN 점수 ≥ 90 THEN 'A'
집계 SUM(expr) 합계 SUM(SALARY)
집계 AVG(expr) 평균 AVG(SALARY)
집계 MAX(expr) 최댓값 MAX(HIRE_DATE)
집계 MIN(expr) 최솟값 MIN(SALARY)
집계 COUNT(*) 행 수 COUNT(*)
반응형
반응형

Spring Security를 이용해 회원 관리나 로그인 기능을 구현할 때, 비밀번호를 평문(plain text)으로 저장하면 보안상 매우 취약합니다. 이번 글에서는 Spring Security에서 제공하는 BCryptPasswordEncoder를 사용하여 안전하게 비밀번호를 암호화하는 방법을 소개하겠습니다.

 

 

1. BCryptPasswordEncoder란?

BCryptPasswordEncoder는 Spring Security에서 제공하는 비밀번호 암호화 도구로, 단방향 해싱(hashing)을 수행합니다. 한번 암호화된 비밀번호는 복호화가 불가능하며, 로그인 시에는 입력된 비밀번호를 다시 암호화하여 데이터베이스에 저장된 암호화된 비밀번호와 비교하여 인증합니다.

주요 특징:

  • 단방향 암호화 방식
  • 안전한 salt 자동 생성 및 관리
  • 비밀번호 강도 조절 가능

 

2. BCryptPasswordEncoder 설정 방법

다음은 Spring 프로젝트에서 BCryptPasswordEncoder를 Bean으로 등록하는 예제입니다.

@Configuration
public class PasswordConfig {

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

위 코드에서 @Configuration 어노테이션은 Spring에게 이 클래스가 설정 클래스임을 알려줍니다. 그리고 @Bean어노테이션을 사용하여 BCryptPasswordEncoder 인스턴스를 Spring의 관리 대상(Bean)으로 등록합니다.

 

3. 회원가입에서 사용 방법

회원가입 시 사용자의 비밀번호를 암호화하여 저장하려면 아래와 같이 작성합니다.

@Autowired
private BCryptPasswordEncoder passwordEncoder;

public void registerUser(User user) {
    String encodedPassword = passwordEncoder.encode(user.getPassword());
    user.setPassword(encodedPassword);
    userRepository.save(user);
}

 

4. 로그인 시 비밀번호 검증 방법

로그인 시 비밀번호를 검증할 때는 사용자가 입력한 비밀번호와 데이터베이스에 저장된 암호화된 비밀번호를 비교합니다.

@Autowired
private BCryptPasswordEncoder passwordEncoder;

public boolean authenticate(String rawPassword, String encodedPassword) {
    return passwordEncoder.matches(rawPassword, encodedPassword);
}

 

5. 주의사항

  • 절대 비밀번호를 평문으로 저장하지 말기!
  • strength 파라미터를 통해 암호화 강도를 조절할 수 있지만, 기본값(10)이 일반적인 환경에서 충분!
  • 성능이 매우 중요한 환경이라면 암호화 강도를 적절히 설정할 것!

마무리

지금까지 Spring Security의 BCryptPasswordEncoder를 활용한 안전한 비밀번호 관리 방법을 알아봤습니다. 이를 통해 애플리케이션 보안을 강화하고 사용자 정보를 안전하게 보호할 수 있습니다.

반응형

'Spring Boot > 스프링부트 예제' 카테고리의 다른 글

답변형 게시판 구현 (3)  (0) 2023.10.27
답변형 게시판 구현 (2)  (1) 2023.10.27
답변형 게시판 만들기 (1)  (1) 2023.10.26
QnA 다양한 검색 게시판 CRUD (1)  (1) 2023.10.24
게시판 페이징 처리  (1) 2023.10.23
반응형

Flutter 레이아웃의 기본, Container 위젯을 이해하자

 

Flutter에서 Container 위젯은 레이아웃을 구성하는 데 가장 기본적이면서도 강력한 도구입니다. 이를 비유하자면, 빈 상자(Box) 또는 캔버스처럼 생각할 수 있습니다. 이 빈 캔버스 위에 원하는 스타일, 정렬, 크기 등을 적용해 다양한 레이아웃을 구성할 수 있습니다.


1. Container란 무엇인가?

 

Container 위젯은 Flutter에서 레이아웃을 꾸미고 배치하는 데 사용되는 다목적 위젯입니다. 주요 기능은 다음과 같습니다:

크기 조절: width, height를 통해 크기를 조정할 수 있습니다.

스타일링: color, decoration을 사용해 배경색, 테두리, 그림자 등을 추가할 수 있습니다.

배치: 내부 여백(padding), 외부 여백(margin), 정렬(alignment) 등을 설정할 수 있습니다.

 

2. Container의 주요 속성

 

Container는 다양한 속성을 제공하며, 이를 통해 위젯을 쉽게 커스터마이징할 수 있습니다.

속성 설명
width / height 컨테이너의 너비와 높이를 설정합니다.
color 컨테이너의 배경색을 지정합니다.
padding 내부 여백을 설정하여 컨테이너 내부의 자식 위젯이 테두리로부터 얼마나 떨어져야 하는지 결정합니다.
margin 외부 여백을 설정하여 컨테이너와 주변 위젯 간의 간격을 조정합니다.
decoration 배경, 테두리, 그림자, 둥근 모서리 등의 복잡한 스타일을 설정할 수 있습니다. color와 함께 사용하지 못하며, 둘 중 하나만 사용 가능합니다.
alignment 자식 위젯의 배치를 컨테이너 내부에서 조정합니다.
constraints 컨테이너의 최소 및 최대 크기를 설정합니다.
child Container 내부에 들어갈 다른 위젯 설정(모든 위젯에 자식 위젯을 지정할 수 있음)

 


3. 실제 예제 코드로 이해하기

 

기본적인 Container

Container(
  width: 100,
  height: 100,
  color: Colors.blue, // 단순 배경색 설정
)

여백과 정렬 추가

Container(
  margin: EdgeInsets.all(20), // 외부 여백
  padding: EdgeInsets.all(10), // 내부 여백
  color: Colors.orange,
  child: Text('Hello Flutter!'), // 자식 위젯
)

스타일링과 둥근 테두리

Container(
  width: 150,
  height: 150,
  decoration: BoxDecoration(
    color: Colors.green,
    borderRadius: BorderRadius.circular(15), // 둥근 모서리
    boxShadow: [
      BoxShadow(
        color: Colors.black.withOpacity(0.2),
        spreadRadius: 2,
        blurRadius: 5,
      ),
    ],
  ),
  child: Center(
    child: Text(
      'Styled Box',
      style: TextStyle(color: Colors.white),
    ),
  ),
)

 

 

4. Container의 한계

 

Container를 지나치게 남용하면 성능에 영향을 미칠 수 있습니다. Flutter는 레이아웃을 효율적으로 구성하기 위해 더 간단한 위젯(예: Padding, SizedBox, Align)을 사용할 수 있습니다. 따라서 Container를 사용할 때 꼭 필요한 경우에만 활용하는 것이 좋습니다.

반응형
반응형

Flutter의 didChangeDependencies 함수란?

Flutter에서 didChangeDependencies 함수StatefulWidget의 상태가 변경되었거나, 위젯이 의존하고 있는 어떤 값이 변경되었을 때 호출되는 함수입니다.
쉽게 말해, "위젯이 외부에서 제공받는 데이터가 변경되었을 때 실행되는 함수"입니다.

 


didChangeDependencies의 주요 특징

  1. 특정 상황에서 호출:
    • 위젯의 의존성이 변경되었을 때 호출됩니다.
    • 예: InheritedWidget의 값이 변경되었을 때.
  2. initState 다음에 호출:
    • 위젯이 처음 생성될 때, initState 이후에 한 번 호출됩니다.
    • 그 이후에는 의존성이 변경될 때마다 호출됩니다.
  3. 데이터 의존성이 있을 때 사용:
    • 위젯이 상위 위젯에서 제공하는 데이터를 사용할 때, 이 데이터를 다시 불러오거나 처리하는 데 유용합니다.

didChangeDependencies 함수의 기본 구조

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  // 의존성 변경 시 수행할 작업
}
  • super.didChangeDependencies(): Flutter의 기본 동작을 유지하려면 항상 호출해야 합니다.

간단한 예제: InheritedWidget과 함께 사용

아래는 InheritedWidget을 사용해 데이터를 전달하고, didChangeDependencies에서 이 데이터를 처리하는 예제입니다.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

// InheritedWidget 정의
class CounterProvider extends InheritedWidget {
  final int counter;

  CounterProvider({
    required this.counter,
    required Widget child,
  }) : super(child: child);

  @override
  bool updateShouldNotify(CounterProvider oldWidget) {
    return oldWidget.counter != counter;
  }

  static CounterProvider? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<CounterProvider>();
  }
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int counter = 0;

  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return CounterProvider(
      counter: counter,
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: Text('didChangeDependencies 예제')),
          body: CounterDisplay(),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            child: Icon(Icons.add),
          ),
        ),
      ),
    );
  }
}

class CounterDisplay extends StatefulWidget {
  @override
  _CounterDisplayState createState() => _CounterDisplayState();
}

class _CounterDisplayState extends State<CounterDisplay> {
  int? counter;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // InheritedWidget에서 데이터를 가져옴
    counter = CounterProvider.of(context)?.counter;
    print('didChangeDependencies 호출됨: counter = $counter');
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        'Counter: $counter',
        style: TextStyle(fontSize: 24),
      ),
    );
  }
}

실행 결과:

  1. 처음 실행하면 Counter: 0이 표시됩니다.
  2. 플러스 버튼을 누르면:
    • counter 값이 증가하고, didChangeDependencies가 호출되어 화면이 업데이트됩니다.
    • 콘솔에 didChangeDependencies 호출됨이 출력됩니다.

언제 didChangeDependencies를 사용해야 할까?

  • InheritedWidget 데이터 의존:
    • 위젯이 상위 위젯에서 데이터를 받을 때, 데이터 변경을 감지하고 싶을 때.
  • 외부 의존성 감지:
    • 예: 테마 변경, 지역화(Localization) 데이터 변경.

didChangeDependencies와 initState의 차이

initState didChangeDependencies
위젯이 처음 생성될 때 한 번 호출됨. 처음 생성될 때 한 번 호출되고, 이후 의존성이 변경될 때마다 호출됨.
내부 상태를 초기화하는 데 사용됨. 외부 데이터(의존성) 변경을 감지하고 처리함.
context를 사용할 수 없음 context를 사용할 수 있음.
반응형
반응형

Flutter의 initState 함수란?

Flutter에서 initState 함수StatefulWidget의 상태를 초기화할 때 사용하는 메서드입니다.
쉽게 말해, "앱이 처음 실행될 때 한 번만 호출되는 준비 작업 함수"라고 생각하면 됩니다.
예를 들어, 데이터를 불러오거나 타이머를 설정하는 등 초기화가 필요한 작업을 initState에서 수행합니다.


initState의 주요 특징

  1. 딱 한 번 호출됨
    • initState는 State 객체가 처음 생성될 때 한 번만 호출됩니다.
    • 이후 상태가 변경되어도 initState는 다시 호출되지 않습니다.
  2. 초기화 작업에 적합
    • 데이터를 불러오거나 리스너를 추가하는 등 초기 설정 작업에 사용됩니다.
  3. super.initState() 호출 필요
    • initState를 오버라이드할 때 super.initState() 를 반드시 호출해야 Flutter의 내부 초기화가 제대로 동작합니다.

initState 함수의 기본 구조

@override
void initState() {
  super.initState(); // 부모 클래스의 초기화 메서드 호출
  // 초기화 작업
}

간단한 예제: 앱 시작 시 타이머 설정

아래는 앱이 실행되면 3초 후에 텍스트를 업데이트하는 예제입니다.

import 'package:flutter/material.dart';
import 'dart:async'; // 타이머를 사용하기 위해 필요

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String message = "안녕하세요!";

  @override
  void initState() {
    super.initState();
    // 3초 후에 메시지 변경
    Timer(Duration(seconds: 3), () {
      setState(() {
        message = "Flutter를 배우고 있어요!";
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('initState 함수 예제')),
        body: Center(
          child: Text(
            message,
            style: TextStyle(fontSize: 24),
          ),
        ),
      ),
    );
  }
}

 


언제 initState를 사용해야 할까?

  • 초기 데이터 로드:
    • 예: API 호출, 데이터베이스에서 데이터 가져오기.
  • 애니메이션 시작:
    • 애니메이션 컨트롤러 초기화.
  • 리스너 추가:
    • 텍스트 입력이나 네트워크 이벤트를 감지하는 리스너 설정.
  • 타이머 설정:
    • 특정 시간 후에 동작을 실행.

 

주의할 점

  1. UI 관련 작업 금지:
    • initState에서 직접 UI를 업데이트하거나 context를 사용해 위젯 트리에 접근하면 오류가 발생할 수 있습니다.
    • 이유: 위젯이 아직 완전히 렌더링되지 않았기 때문입니다.
  2. 반드시 super.initState() 호출:
    • initState를 오버라이드할 때 Flutter의 기본 초기화 작업을 위해 super.initState()를 호출해야 합니다.
  3. dispose와 함께 사용:
    • 리스너나 애니메이션 컨트롤러를 initState에서 추가했다면, dispose 함수에서 반드시 정리(cleanup)해야 메모리 누수를 방지할 수 있습니다.
반응형
반응형

Flutter의 createState 함수란?

Flutter에서 createState 함수StatefulWidget과 함께 사용되며, 화면의 변경 가능한 상태(state)를 관리하는 중요한 역할을 합니다. 쉽게 말해, StatefulWidget을 위한 "상태 관리자"를 만들어주는 함수입니다.


왜 createState가 필요한가?

StatefulWidget은 두 가지 주요 구성 요소로 이루어져 있습니다:

  1. StatefulWidget: 화면에 정적인 부분을 정의합니다.
  2. State: 화면의 변경 가능한 부분(예: 버튼 클릭, 입력 값)을 관리합니다.

createState 함수는 StatefulWidget이 화면의 상태를 관리할 수 있도록 State 객체를 연결합니다.

 

createState 함수의 기본 구조

createState 함수는 StatefulWidget 클래스에서 필수로 구현해야 하며, State 클래스를 반환합니다.

@override
State<MyWidget> createState() => _MyWidgetState();

 

  • MyWidget: StatefulWidget 클래스 이름입니다.
  • _MyWidgetState: State 클래스 이름입니다. 일반적으로 밑줄(_)을 붙여 해당 클래스를 비공개로 만듭니다.

간단한 예제: 버튼을 누르면 숫자가 증가하는 앱

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int counter = 0;

  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('createState 함수 예제'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                '버튼을 누른 횟수:',
                style: TextStyle(fontSize: 20),
              ),
              Text(
                '$counter',
                style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _incrementCounter,
                child: Text('숫자 증가'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

 

 


createState 함수의 동작 과정

  1. State 객체 생성:
    • createState 함수는 State 객체를 생성하고 StatefulWidget과 연결합니다.
  2. State 객체 관리:
    • Flutter는 State 객체를 사용해 StatefulWidget의 상태를 관리합니다.
  3. 상태 변경:
    • 상태가 변경되면 setState 메서드를 호출하여 build 함수를 다시 실행하고 UI를 업데이트합니다.

StatefulWidget에서 createState와 State의 관계

StatefulWidget은 변경 가능한 UI를 처리할 때 항상 State 객체와 함께 작동합니다. 아래 그림으로 쉽게 이해할 수 있습니다:

StatefulWidget -------> createState() -------> State 클래스
       ↑                                          ↓
      UI 정의                              상태 변경 및 UI 업데이트

1. createState 함수는 언제 호출되나요?

  • StatefulWidget이 처음 생성될 때 딱 한 번 호출됩니다.

2. 왜 State 객체를 분리하나요?

  • State 객체를 분리하면 동일한 StatefulWidget을 다른 상태에서 재사용할 수 있어 UI와 상태를 독립적으로 관리할 수 있습니다.

3. State 클래스의 생명주기는 어떻게 되나요?

State 클래스는 아래와 같은 순서로 작동합니다:

  1. createState: State 객체 생성.
  2. initState: State 객체 초기화.
  3. build: UI 렌더링.
  4. setState: 상태 변경 후 UI 업데이트.
반응형
반응형

Flutter의 build 함수란?

Flutter에서 UI를 만드는 핵심 메서드 중 하나가 바로 build 함수입니다. 앱 화면에 표시되는 모든 것은 이 build 함수에서 정의됩니다. 쉽게 말해, build 함수는 화면에 어떤 위젯을 보여줄지 "그리는 설계도"라고 할 수 있습니다.

 


build 함수의 역할

  1. 위젯 트리를 구성:
    • build 함수는 Flutter에게 어떤 위젯을 화면에 보여줄지 알려줍니다.
    • 이 함수 안에서 다양한 위젯을 조합해 "위젯 트리(widget tree)"를 만듭니다.
  2. UI 업데이트 처리:
    • 앱의 상태(state)가 바뀌면, Flutter는 build 함수를 다시 호출해 변경된 UI를 업데이트합니다.

build 함수의 기본 구조

build 함수는 반드시 구현해야 하는 함수로, 모든 Flutter 위젯에서 사용됩니다. 아래는 build 함수의 기본 구조입니다.

@override
Widget build(BuildContext context) {
  return WidgetTree;
}

 

  • context: 현재 위젯의 위치와 관련된 정보를 담고 있습니다.
  • 반환 값: 다른 위젯(또는 위젯 트리)을 반환합니다.

간단한 예제: build 함수에서 텍스트 표시

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Build 함수 예제')),
        body: Center(
          child: Text('안녕하세요! Flutter를 배우고 있어요!'),
        ),
      ),
    );
  }
}

 


StatefulWidget과 build 함수

StatefulWidget에서는 상태가 변경될 때마다 build 함수가 호출되어 UI를 다시 그립니다.

상태에 따라 버튼을 누르면 카운터가 증가하는 예제

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int counter = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('카운터 앱')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('버튼을 누른 횟수: $counter', style: TextStyle(fontSize: 24)),
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    counter++;
                  });
                },
                child: Text('숫자 증가'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}


build 함수의 중요한 특징

  1. 반복 호출:
    • build 함수는 앱 상태가 변경될 때마다 반복적으로 호출됩니다.
    • 하지만 Flutter는 효율적으로 변경된 부분만 업데이트하므로 걱정하지 않아도 됩니다.
  2. 항상 위젯 반환:
    • build 함수는 항상 위젯 또는 위젯 트리를 반환해야 합니다.
  3. UI 선언:
    • build 함수는 "어떤 UI를 보여줄지"만 선언하며, 렌더링이나 UI 업데이트는 Flutter가 자동으로 처리합니다.
반응형

+ Recent posts