no image
Tableau - 기본 사용
1. 데이터 불러오기 왼쪽 패널에서 데이터 유형 선택 후 불러오기 프로그램 실행 도중에는 [데이터] - [새 데이터 원본] 주문 시트 추가 시트1 날짜, 문자열은 범주가 되고 숫자(#)는 Value가 된다. 2. 기본 UI - Workbook Name: 문서 이름이 나오는 영역 - 메뉴 표시줄 - Tool bar - Side bar 선택한 그래프 영역에 따라 메뉴가 변경 데이터 탭은 데이터 필드 이름이 표시 측정값: 수치 데이터 차원: 수치 이외 범주로 사용되는 데이터 - 선반과 카드 페이지 카드: 데이터를 애니메이션으로 출력할 때 필터 카드: 데이터를 필터링할 때 마크 카드: 크기, 레이블, 색상 등의 세부정보를 수정하고자 할 때 - 열 및 행 선반(Shelves) 데이터 필드를 드래그 앤 드랍해서 차..
2024.01.31
no image
Tableau - 개요
데이터 분석 및 시각화를 담당하는 Business Intelligence 솔루션 현재는 MS의 POWER BI와 더불어서 가장 많이 사용되는 BI 솔루션 BI: 비즈니스를 운영하면서 얻은 데이터를 수집, 저장, 분석하여 성과를 최적화하는 프로세스와 방법 태블로나 POWER BI는 사람들이 데이터를 보고 이해할 수 있도록 도와주는 애플리케이션 1) 태블로는 인사이트 도출을 위한 필수 도구 - 데이터 시각화와 분석에 특화된 도구 대시보드와 반응형 기술을 활용 대시보드: 여러 개의 컴포넌트를 묶어서 출력 데이터분석 및 해석, 이상치 탐지에 용이 - 엑셀과의 차이 엑셀 태블로 데이터 처리 속도 보통 현저히 빠름 데이터 업데이트 수동 스케쥴 기능으로 자동 시각화 대시보드 없음 대시보드 기능 커뮤니티 함수나 계산식..
2024.01.31
no image
React - CORS
1) 서버 애플리케이션 구동 가상 환경을 사용하는 파이썬 프로젝트를 클론한 경우 수행할 작업 a. 프롬프르트를 디렉토리로 이동 python -m venv myvenv myvenv\Scripts\activate b.패키지 설치 pip install -r requirements.txt c.django 프로젝트의 경우 settings.py에 가서 데이터베이스 접속 정보를 수정 d.django 프로젝트의 경우 데이터베이스 반영 작업 수행 python manage.py makemigrations python manage.py migrate e. 실행 python manage.py runserver 0.0.0.0:80 f. 브라우저에서 확인 http://127.0.0.1/todo?userid=Django g. 데이..
2024.01.31
no image
React
1. React 1) SPA (Single Page Application) 하나의 HTML 파일을 이용해서 애플리케이션의 모든 화면을 출력하는 방식 이전의 애플리케이션들은 여러 개의 HTML 파일을 만들어서 화면 전환을 이용해서 여러 콘텐츠를 출력했는데 -> 화면 전환을 하게 되면 이전 내용을 삭제하고 새로운 내용을 출력해야 하기 때문에 깜빡임이 발생하고 -> 네트워크 에러가 발생하게 되면 화면 전체가 에러 페이지를 출력 -> 모바일의 경우는 에러 페이지를 보는 횟수가 증가 해결 방법으로 로컬에 데이터를 저장해서 네트워크 에러가 발생한 경우 로컬의 데이터를 출력 하나의 화면을 여러 컴포넌트로 분할하고 분할한 컴포넌트 별로 별도로 데이터를 요청해서 출력 SPA를 만들기 위한 프레임워크로 널리 사용되는 것이..
2024.01.30
no image
Day10. REST API
1. 웹 서비스를 구현하는 방식 서버 사이드 랜더링 클라이언트(웹 브라우저)의 요청을 서버가 받아서 처리한 후 서버가 출력하는 코드를 만들어서 클라이언트에게 전송을 하고 클라이언트는 이 코드를 받아서 파싱해서 출력하는 방식 서버 코드 와 클라이언트 코드를 하나의 프로젝트에 전부 작성 서버 코드를 수정할 때 클라이언트 코드가 영향을 받을 수 있고 클라이언트 코드를 수정할 때 서버 코드가 영향을 받을 수 있습니다. 이 방식으로 서비스를 만들려면 템플릿 언어라는 것을 학습을 해야 합니다. 최근에는 이 방식을 선호하지 않습니다. 클라이언트 사이드 랜더링 서버는 클라이언트 요청을 받아서 데이터(XML -> JSON)를 응답으로 전송하고 클라이언트는 응답을 받아서 직접 데이터를 해석해서 출력하는 코드를 만들고 화면..
2024.01.26
no image
Github 2
git 디렉토리 생성 git init 현재 디렉토리에 ,git(숨김) 이라는 디렉토리가 생성 git이라는 디렉토리를 강제로 삭제하면 git 등록이 취소 로컬git과 연결된 상태 git에서 관리할 파일을 등록 git add 파일or디렉토리_이름_나열 git add . # 디렉토리의 모든 파일 과 디렉토리 관리 현재까지 변경 내용을 로컬 git에 반영 git commit -m "메시지" 변경한 내역이 없으면 commit 하지 않음 이메일이나 이름을 등록한 적이 없으면 이메일과 이름을 등록하라는 메시지 출력 이 작업을 수행하고 커밋하면 됨 돌아가려면 commit된 id로 돌아가야 한다. git reset --soft id git reset --hard id soft: 이전 내용을 저장은 해놓지만 코드를 수정하..
2024.01.26
no image
Day9. 웹 서버 만들기
전송 방식 GET: 데이터를 가져올 때 사용하는 방식으로 파라미터가 URL에 노출 POST: 데이터를 삽입할 때 사용하는 방식으로 파라미터가 URL에 노출되지 않음 PUT: 데이터 수정 - 데이터 전체를 수정 PATCH: 데이터 수정 - 데이터의 일부 속성을 수정, 멱등성이 없다고 권장하지 않음 DELETE: 데이터 삭제 상태 코드: 서버가 클라이언트에게 응답을 전송할 때 응답에 대한 상태를 나타내는 코드로 3자리 1XX: 요청이 수신되었으며 프로세스 진행 중 2XX: 성공적으로 처리 됨 3XX: 리다이렉션 중 4XX: 클라이언트 오류, 404 - URL이 잘못됨 5XX: 서버 오류 Python의 Web Framework Flask: 자유도가 높음, 구현해주는 것이 거의 없음, 적은 코드로 웹 서버를 만..
2024.01.24
no image
JOIN
A. 내부 조인 1) 일대다 관계의 이해 (PK-FK 관계) 1명의 회사원이 여러 번의 급여를 받는다. 학생 테이블과 학점테이블도 1명의 학생이 여러 과목의 학점을 받아야 하므로 일대다 관계 2) 내부 조인의 기본 두 테이블에 모두 있는 내용만 조인되는 방식 SELECT FROM INNER JOIN ON [WHERE 검색 조건] USE market_db; SELECT * FROM buy INNER JOIN member ON buy.mem_id = member.mem_id WHERE buy.mem_id = 'GRL'; 3) 별칭 USE market_db; SELECT mem_id --에러! buy.mem_id FROM buy INNER JOIN member ON buy.mem_id = member.mem_..
2024.01.23
SQL

Tableau - 기본 사용

0ㅑ채
|2024. 1. 31. 16:52

 

1. 데이터 불러오기

  • 왼쪽 패널에서 데이터 유형 선택 후 불러오기
  • 프로그램 실행 도중에는 [데이터] - [새 데이터 원본]

 

주문 시트 추가

 

시트1

  • 날짜, 문자열은 범주가 되고
  • 숫자(#)는 Value가 된다.

 

 

2. 기본 UI

- Workbook Name: 문서 이름이 나오는 영역

- 메뉴 표시줄

- Tool bar

- Side bar

  • 선택한 그래프 영역에 따라 메뉴가 변경
  • 데이터 탭은 데이터 필드 이름이 표시
    • 측정값: 수치 데이터
    • 차원: 수치 이외 범주로 사용되는 데이터

- 선반과 카드 

  • 페이지 카드: 데이터를 애니메이션으로 출력할 때
  • 필터 카드: 데이터를 필터링할 때
  • 마크 카드: 크기, 레이블, 색상 등의 세부정보를 수정하고자 할 때

- 열 및 행 선반(Shelves)

  • 데이터 필드를 드래그 앤 드랍해서 차트 생성
  • 범주를 설정하기 위해 1개 이상의 차원 배치
    그래프를 그리기 위해서 1개 이상의 측정 값 배치

- 뷰(View)

  • 그래프 표시 영역

 

 

3. 대분류 별 매출

열: 대분류
행: 매출

 

그래프의 색상 변경

  • 변경하고자 하는 필드를 색상 선반으로 드래그/드랍
  • 다시 색상 버튼 누르면 상세 편집 가능

 

항목 명이나 값 표시

  • 레이블 선반으로 드래그/드랍

 

 

차트 영역의 세부 조정

- 영역을 선택 > 마우스 우클릭 > [서식]

축과 패널

 

 

4. 현재 존재하는 필드를 가지고 새로운 필드 생성해서 필터링 

- 사이드 바 > 마우스 우클릭 > [계산된 필드 만들기]

- 툴바 > [분석] > [계산된 필드 만들기]

수익률: SUM([수익])/SUM([매출])

 

행: 대분류

열: 수익률

 

마크 카드에는 여전히 합계(매출)이기 때문에 레이블은 매출을 표시

 

 

 

5. 매개변수 만들기 

- 여러 항목을 골라서 볼 수 있다.

- 사이드 바의 빈 영역 > 마우스 우클릭 > [매개변수 만들기]

매개변수 이름: 매출 및 수익률
데이터 유형: 문자열
허용 가능한 값: 목록
데이터 필드 이름: 매출, 수익률

- 콤보박스 생성!

선택할 수 있는 목록을 만든 것, 실제 출력하는 항목을 만든 것은 아님

매개변수를 만들면 계산된 필드 만들기를 이용해서 조건식 만들어야 함

  • 계산된 필드 만들기
CASE [매출 및 수익률]                      //매개변수 이름

WHEN '매출' THEN SUM([매출])      //매개변수에서 만든 항목 이름
WHEN '수익률' THEN([수익률])        //THEN 뒤에 있는 내용은 실제 출력할 내용

END

 

  • 생성한 필드를 행 선반, 현재 레이블에 배치 교체
  • 데이터 원본에서 '매출 및 수익률' 매개변수 선택
    마우스 우클릭 > [매개변수 표시]

 

 

 

 

6. 불연속형 필드, 연속형 필드

불연속형 필드

  • 이산적인 값 : 값의 중간에 아무것도 없을 수 있는 데이터, 디지털
  • 문자열은 항상 비연속형 필드지만 날짜나 숫자는 연속형이 될 수도 있다.
  • 불연속형 필드는 행 선반이나 열 선반에 놓이게 되면 머리글이 생성
  • 색상에 사용하면 각각의 값 별로 다른 색상 적용 가능
  • 범주형 (Category) 데이터

 

연속형 필드

  • 날짜나 숫자 데이터에서 처음부터 끝까지 연속적으로 흐르는 값
  • 행이나 열에서 축을 정의

 

날짜 데이터의 경우는 연속형/불연속형 구분을 잘 해야 한다.

연속형 불연속형

 

 

 

 

 

7. 대시보드

대시보드 생성 > 컨테이너 선택 > 시트 드래그

 

'Tableau' 카테고리의 다른 글

Tableau - Tree Map  (0) 2024.02.01
Tableau - 라인 그래프  (0) 2024.02.01
Tableau - 막대 그래프  (2) 2024.02.01
Tableau - 주제에 적합한 시각화 방법  (0) 2024.02.01
Tableau - 개요  (0) 2024.01.31

Tableau - 개요

0ㅑ채
|2024. 1. 31. 14:51

 

 

데이터 분석 및 시각화를 담당하는 Business Intelligence 솔루션

현재는 MS의 POWER BI와 더불어서 가장 많이 사용되는 BI 솔루션

  • BI: 비즈니스를 운영하면서 얻은 데이터를 수집, 저장, 분석하여 성과를 최적화하는 프로세스와 방법

태블로나 POWER BI는 사람들이 데이터를 보고 이해할 수 있도록 도와주는 애플리케이션

 

 

1) 태블로는 인사이트 도출을 위한 필수 도구

- 데이터 시각화와 분석에 특화된 도구

  • 대시보드와 반응형 기술을 활용
    • 대시보드: 여러 개의 컴포넌트를 묶어서 출력
  • 데이터분석 및 해석, 이상치 탐지에 용이

- 엑셀과의 차이

  엑셀 태블로
데이터 처리 속도 보통 현저히 빠름
데이터 업데이트 수동 스케쥴 기능으로 자동
시각화 대시보드 없음 대시보드 기능
커뮤니티 함수나 계산식 활용, 매크로를 위한 코드 시각화에 대한 내용 활성화

 

Taebleau
Excel

 

 

2) 간편한 데이터 연결 및 전처리

태블로는 여러 종류의 데이터 연결을 지원

Tableau Prep Builder를 사용하면 데이터 전처리 작업을 수행하는 것이 가능

 

 

3) 학습하기가 쉬움

 

 

4) 태블로 커뮤니티

해외: https://makeovermonday.co.uk/

 

Makeover Monday

Improving how we visualize and analyze data, one chart at a time.

makeovermonday.co.uk

 

국내: https://tableauwiki.com/

 

Tableau Wiki 태블로위키

국내 최대의 태블로 관련 노하우와 이야기를 접할 수 있는 공동 운영 블로그입니다. 현업에서 태블로를 사용하는 사람들이 함께 운영하고 있습니다.

tableauwiki.com

 

 

5) 제품

- Taebleau Desktop

  • On-Premise 또는 Cloud에 저장된 데이터 원본을 직접 연결해서 분석할 수 있는 환경 제공
    *On-Premise: 기업내부, 인터넷을 이용하지 않는

- Tableau Prep

  • 데이터 처리 플랫폼

- Tableau Public

  • 무료인데 기능 제한이 있음
  • 학생은 학교 이메일을 등록해서 인증을 받으면 Tableau Desktop을 1년 동안 무료로 사용 가능

 

 

6) 활용 가능한 데이터

- 엑셀

- 텍스트 파일 :txt, csv, tsv, json

- 관계형 데이터베이스 대부분

- 공간 파일(Shape File): kml, shp, tab, mif 등       *공간 파일: 위도나 경도 등 지도 파일

- 통계 관련 프로그램: sav, sas7bdat 등

- R의 데이터: rda, rdata

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 여기까지 데이터분석

- OLAP의 데이터 원본 - 데이터베이스  *(On Line Analytical Processing - 온라인 분석 처리))

- Snowflake, Redshift와 같은 클라우드 기반의 데이터 원본

- hyper 파일: tableau의 인메모리 데이터

- tde 파일: 데이터 및 로그 파일을 암호화 한 파일

 

'Tableau' 카테고리의 다른 글

Tableau - Tree Map  (0) 2024.02.01
Tableau - 라인 그래프  (0) 2024.02.01
Tableau - 막대 그래프  (2) 2024.02.01
Tableau - 주제에 적합한 시각화 방법  (0) 2024.02.01
Tableau - 기본 사용  (1) 2024.01.31

React - CORS

0ㅑ채
|2024. 1. 31. 12:11

1) 서버 애플리케이션 구동

 

가상 환경을 사용하는 파이썬 프로젝트를 클론한 경우 수행할 작업

 

a. 프롬프르트를 디렉토리로 이동

python -m venv myvenv
myvenv\Scripts\activate

 

b.패키지 설치

pip install -r requirements.txt

 

c.django 프로젝트의 경우 settings.py에 가서 데이터베이스 접속 정보를 수정

 

d.django 프로젝트의 경우 데이터베이스 반영 작업 수행

python manage.py makemigrations
python manage.py migrate

 

e. 실행

python manage.py runserver 0.0.0.0:80

 

f. 브라우저에서 확인

http://127.0.0.1/todo?userid=Django

 

g. 데이터 입력

desc todoapplication_todo ;

desc todoapplication_todo ;

 

Null 여부를 봤다. 데이터를 넣어야 한다. 

auto_increment가 있으니 id는 안넣어도 된다.

다 입력하고 커밋!

COMMIT;

 

id에 따라 다른정보들이 조회됨

 

 

2) 클라이언트 애플리케이션의 App.js 파일에 데이터를 요청하는 코드 추가

  componentDidMount(){
    //ajax 요청 객체 생성
    let request = new XMLHttpRequest()
    //요청 준비
    request.open('GET', "http://127.0.0.1/todo?userid=Django")
    //요청
    request.send('')
    //응답 처리
    request.addEventListener('load', () => {
      //json 데이터 출력
      console.log(request.responseText)
    })
  }

 

구동 http://localhost:3000/

 

CORS Policy 에러가 출력

  • 서버 애플리케이션은 127.0.0.1:80으로 실행 중이고
    클라이언트 애플리케이션은 localhost(127.0.0.1):3000으로 실행중

 

SOP (동일 출처 정책)

  • ajax나 fetch api는 브라우저의 동일 출처 정책에 따라 자신과 동일한 도메인의 데이터만 받아올 수 있다.
  • 동일 도메인이란 IP주소와 포트번호까지 일치하는 것을 의미한다.
  • 서버 애플리케이션과 클라이언트 애플리케이션을 따로 구현하면 SOP 정책에 따라 ajax나 fetch api를 이용해서는 서버의 데이터를 사용할 수 없다.
  • 서버 애플리케이션에서 요청이 가능한 클라이언트 애플리케이션의 도메인을 등록
  • 서버 애플리케이션을 만들 때 CORS 설정을 확인해두자!

* React의 경우는 react의 설정 파일에 설정을 해도 CORS 설정이 가능하다.

* react가 node.js 플랫폼 위에서 동작하는데 node.js가 C/C++이라서 proxy를 이용해 react에 데이터를 넘겨줄 수 있다.

 

 

3) Django의 CORS 설정

a. cors 관련 패키지 설치

pip install django-cors-headers

 

b. django 프로젝트의 settings.py 파일: 애플리케이션 등록

#애플리케이션 등록
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "todoapplication",
    "corsheaders", #여기
]

 

c. django 프로젝트의 settings.py 파일 : MIDDELWARE 맨 앞에 등록

MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware", #여기
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

 

d. django 프로젝트의 settings.py 파일: 허용할 LIST 등록

CORS_ORIGIN_WHITELIST =['http://127.0.0.1:3000', 'http://localhost:3000']
CORS_ALLOW_CREDENTIALS =True
  • 허용할 도메인 등록 - 지금은 react라서 3000번 등록
  • 실제로는 배포하는 도메인을 등록!

구동 시 CORS Policy 에러 해결

 

클라이언트 App.js를 수정

  componentDidMount(){
    //ajax 요청 객체 생성
    let request = new XMLHttpRequest()
    //요청 준비
    request.open('GET', "http://127.0.0.1/todo?userid=Django")
    //요청
    request.send('')
    //응답 처리
    request.addEventListener('load', () => {
      //json 데이터 출력

      //JSON 문자열을 데이터로 변환
      let data = JSON.parse(request.responseText);
      console.log(data)
      //서버에서 받아온 데이터를 state에 대입해서 화면에 출력
      this.setState({items:data.list})
    })
  }

 

 

 

 

 

 

'JavaScript' 카테고리의 다른 글

React  (1) 2024.01.30

React

0ㅑ채
|2024. 1. 30. 17:49

1. React

 

1) SPA (Single Page Application)

  • 하나의 HTML 파일을 이용해서 애플리케이션의 모든 화면을 출력하는 방식
  • 이전의 애플리케이션들은 여러 개의 HTML 파일을 만들어서 화면 전환을 이용해서 여러 콘텐츠를 출력했는데
    -> 화면 전환을 하게 되면 이전 내용을 삭제하고 새로운 내용을 출력해야 하기 때문에 깜빡임이 발생하고
    -> 네트워크 에러가 발생하게 되면 화면 전체가 에러 페이지를 출력
    -> 모바일의 경우는 에러 페이지를 보는 횟수가 증가
  • 해결 방법으로 로컬에 데이터를 저장해서 네트워크 에러가 발생한 경우 로컬의 데이터를 출력
    하나의 화면을 여러 컴포넌트로 분할하고 분할한 컴포넌트 별로 별도로 데이터를 요청해서 출력
  • SPA를 만들기 위한 프레임워크로 널리 사용되는 것이 angular, react, vue 입니다.
  • angular는 구글이 만든 것으로 공식적으로 더 이상 업데이트를 하지 않는다고 발표를 했습니다.
  • 현재 국내 플랫폼 기업이나 중소 기업은 react를 선호하는데 vue를 사용하는 곳도 있습니다.

 

 

2) React

2013년, Facebook에서 발표한 SPA를 구현하기 위한 오픈소스 자바스크립트 프레임워크

  • 새로운 문법 사용: 가상 DOM과 JSX
  • 출력이 빠름: 게임 엔진의 출력 방식을 이용, 가상의 DOM을 메모리에 배치하기 떄문
  • 컴포넌트 기반
    • 태그
      화면에 보여지는 개체 <div>
    • 컴포넌트
      하나의 영역을 나타내기 위한 태그와 코드의 집합
      자체적으로 데이터를 가질 수 있고, 데이터가 변경되면 자동으로 재출력 (새로고침 필요 X)
      미리 구조를 만들어두고 다시 출력할 때는 변경된 부분만 다시 출력
  • 프레임워크가 제공하는 기능을 그대로 사용
    • 클래스가 충분한 기능을 제공해주기 때문에 클래스를 이용해서 인스턴스를 만들어서 바로 사용
    • ex. 프레임워크가 Template라는 클래스를 제공하면
      template = new Template()
  • 프레임워크가 제공하는 기능을 상속받아서 재정의해서 사용
    • 클래스가 충분한 기능을 제공해주지 않아서 내가 기능을 추가해서 사용
    • 상속을 받으면 상위 클래스의 모든 것을 하위 클래스가 물려받음
  • React에서는 Component라는 클래스가 Component의 기능은 전부 가지고 있는데 화면에 아무것도 출력하지 않는다.
    React.Component로부터 상속을 받고 render라는 메서드를 재정의해서 return 값을 출력하도록 설계

 

 

React-native

- 모바일 앱을 만들 수 있다. 

- 안드로이드와 애플 환경에서 모두 사용할 수 있게 코드를 바꿔준다. 

 

Figma

- 디자인을 리액트 코드로 바꿔준다.

 

 

3) 설치

node.js 설치

- node.js를 자바스크립트로 애플리케이션을 개발하기 위한 플랫폼이다. (프레임워크 아님)

- 설치확인: node --version

 

패키지 관리자: npm과 yarn

- package.json 파일에 의존성을 설정하고 node.modules 디렉토리에 패키지 저장

- git hub에 업로드 할 때 node_modules는 할 필요 없음. package.json만 있으면 빌드를 다시 해서 설치 가능

npm install --location=global yarn

- 설치 확인: yarn --version

 

 

4)React 프로젝트 생성 및 실행

생성

yarn create react-app 앱이름(myapp)

 

실행

#myapp 디렉토리에서
yarn start

yarn 없이 실행: npm start

 

 

 

5) Comonent를 화면에 출력

Component: 화면에 출력되는 독립적인 개체

 

src 디렉토리에 ToDo.jsx 

확장자는 js 도 상관없지만 react 컴포넌트 파일이라는 것을 알려주기 위해서 jsx 로 설정

import React from "react";

//react에서 컴포넌트 클래스를 만들기 위해 Component로부터 상속 받기
class ToDo extends React.Component {
    //화면에 출력할 내용을 리턴하는 메소드
    render(){
        return(
            <div className="ToDo">
                <input type="checkbox" id="todo0" name="todo0" value="todo0"/>
                <label for="todo0">ToDo 컴포넌트 만들기</label> 
            </div>
        )
    }
}
  • id: 자바스크립트에서 태그를 구별해서 가져오기 위한 값 (중복 불가)  document.getElementById
  • class: react에선 className. css에서 동일한 디자인을 적용하기 위한 이름 (중복 가능)  document.getElementByClassName
  • name: 클라이언트가 서버로 전송할 때 이름 (중복 가능. checkbox, select 등)
  • value: 값
  • label: for="id"  글자를 눌러도 체크가 된다. 

메인 페이지의 역할을 수행하는 App.js 수정해서 ToDo 컴포넌트 출력

import './App.css';

import React from "react"
import ToDo from "./ToDo" #파일 이름이라는 것을 강조하기 위해 ./ 사용, 없어도 됨

function App() {
  return (
    <div className="App">
      <ToDo />
    </div>
  );
}

export default App;
  • export default App; 이 없을 경우 에러
    ERROR in ./src/index.js 12:33-36
    export 'default' (imported as 'App') was not found in './App' (module has no exports) 
  • javascript는 기본적으로 private이라서 그렇다.
  •  react는 App.js 파일이 전체 화면을 출력하는 파일
     App.js에 작성한 내용이 출력
     react는 반드시 하나로 묶어서 출력해야 함

성공!

더보기

연습

 

src에 Sample.jsx 생성

import React from "react"

class Sample extends React.Component{
    render(){
        return(
            <div className="Sample">
                <p>안녕하세요</p>
            </div>
        )
    }
}

export default Sample;

 

App.js

import './App.css';
import React from 'react';
import ToDo from './ToDo';
import Sample from './Sample';

function App() {
  return (
    <div className="App">
      <ToDo />
      <Sample/>
    </div>
  );
}

export default App;

 

 

6) 컴포넌트에서 데이터를 사용하는 방법

  • props 속성 : 상위 컴포넌트에서 넘겨주는 데이터
    큰 화면에서 작은 화면으로 넘어갈 때 전달해주는 데이터
    내가 쓸 데이터를 내가 만들어서 준다. 
  • state 상태 : 컴포넌트 내부에서 사용하는 데이터
    react는 props나 state에 변화가 생기면 화면을 다시 출력
  • context : 글로벌·전역변수, 모든 컴포넌트에서 사용할 수 있는 데이터
    ex. 로그인 기능
  • redux : 전역 데이터를 만드는 외부 라이브러리
  • Entry 포인트 : React는 시작점이 App.js

 

 

7) props와 state 사용

ToDo.jsx

import React from "react"

class ToDo extends React.Component{

    //생성자
    constructor(props){
        super(props); //상위 클래스에서 넘겨준 모든 props를 현재 클래스에 저장
        //state 생성 - item이라는 이름으로 props 중에서 item이라는 값을 state로 저장
        //props는 상위 컴포넌트에서 전달한 데이터라서 읽기는 가능하지만
        //수정이나 삭제가 안되므로 수정이나 삭제를 하고자 하는 경우는 
        //state로 변환을 해야 합니다.
        this.state = {item:props.item}
    }

    render(){
        return(
            <div className="ToDo">
                <input type="checkbox" 
                    id={this.state.item.id} 
                    name={this.state.item.id} 
                    value={this.state.item.done}/>
                <label id={this.state.item.id}>{this.state.item.title}</label> 
            </div>
        )
    }
}

export default ToDo;

  • 그런데 현재 상위 컴포넌트가 없는 상태라서 item.id, item.done, item.title을 묶을 수 있는 클래스가 필요하다.

 

App.js 수정 > ToDo.jsx 파일에 props 전달

import './App.css';
import React from 'react';
import ToDo from './ToDo';

class App extends React.Component {
  constructor(props){
    super(props)
    //3개의 객체를 가진 배열을 생성
    //this.state.item = {item:{id:0, "title":"Hello React", "done":true}}
    this.state = {item:{id:0, "title":"Hello React", "done":true}}
  }

  render(){
    return(
      <div>
        {/* Todo에게 item이라는 이름으로 데이터 전달 */}
        <ToDo item={this.state.item} />
      </div>
    )
  }
}

export default App;
  • App.js에 this.state.item이라는 이름으로 데이터 생성
  • props의 데이터를 ToDo에게 전달
  • 상위 클래스: React.Component
    상위 컴포넌트(부모): App
    하위 컴포넌트(자식): Todo
    하위 클래스: App

배열이나 리스트를 순회하면서 작업을 수행하는 경우

map

데이터를 변환해주는 함수

함수를 대입해서 함수에 데이터를 순서대로 대입해서 리턴한 결과를 모아 다시 배열이나 리스트로 리턴해주는 함수

 

filter

데이터를 필터링해주는 함수

boolean을 리턴하는 함수를 대입해서 데이터를 순서대로 대입하고 return 값이 true인 데이터만 모아 다시 배열이나 리스트로 리턴해주는 함수

 

reduce

계산하고 리턴해주는 함수

연산 후 리턴하는 함수를 대입해서 데이터를 순서대로 대입,

return 값을 가지고 다음 함수 호출의 매개변수로 활용해서 결과를 하나의 값으로 리턴해주는 함수

 

 

App.js

import './App.css';
import React from 'react';
import ToDo from './ToDo';
// import Sample from './Sample';

class App extends React.Component {
  constructor(props){
    super(props)
    //this.state.time = {item:{id:0, "title":"Hello React", "done":true}}
    this.state = {items:[ {id:0, "title":"Hello React", "done":true}, 
                          {id:1, "title":"vue", "done":false}, 
                          {id:2, "title":"angular", "done":false}]
                  }
  }

  render(){
    //배열을 순회하면서 출력할 내용을 생성
    //item은 배열을 순회할 때 각각의 데이터이고 idx는 인덱스
    //배열을 순회하면서 출력물을 만들 때는 key를 설정
    //key를 설정하지 않으면 출력에는 문제가 없지만 콘솔에 에러가 출력
    let display = this.state.items.map((item, idx) => ( //(아이템, 인덱스)
        <ToDo item={item} key={item.id} />
    ));
    
    return(
        <div className="App">
            {display}
        </div>
    )
  }
}

export default App;

 

ToDo.jsx

...
render(){
        return(
            <div className="ToDo">
                <input type="checkbox" 
                    checked={this.state.item.done}/>
                <label id={this.state.item.id}>{this.state.item.title}</label> 
            </div>
        )
    }
...

 

 

8 ) material UI를 이용한 디자인 변경

 

도큐먼트 https://mui.com/

  • material design: 구글이 제시한 PWA(모바일 앱과 같은 웹 UI)를 위한 디자인 방식
  • material-UI 패키지: 구글의 material design 적용한 리액트 패키지

 

패키지 설치

npm install --save --legacy-peer-deps @material-ui/core
npm install --save --legacy-peer-deps @material-ui/icons
  • node가 아니라 application에 설치 (node_modules)

ToDo.jsx

import React from "react"

import {
    ListItem,
    ListItemText,
    InputBase,
    Checkbox
}from "@material-ui/core"

class ToDo extends React.Component{
    constructor(props){
        super(props);
        this.state = {item:props.item}
    }

    render(){
        //자주 사용하는 데이터를 짧게 사용하기 위해 다른 변수에 대입
        const item = this.state.item;
        return(
            <ListItem>
                <Checkbox checked={item.done} />
                <ListItemText>
                    <InputBase
                        InputProps={{"aria-label":"naked"}}
                        type="text"
                        id={item.id}
                        name={item.id}
                        value={item.title}
                        multiline={true} //여러줄로 생성
                        fullWidth={true} //화면에 꽉차게
                    />
                </ListItemText>
            </ListItem>
        )
    }
}

export default ToDo;

 

App.js

import './App.css';
import React from 'react';
import {Paper, List} from "@material-ui/core"

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {items:[ {id:0, "title":"Hello React", "done":true}, 
                          {id:1, "title":"vue", "done":false}, 
                          {id:2, "title":"angular", "done":false}]
                  }
  }

  render(){
    var display = this.state.items.length > 0 && (//데이터가 있을 때(True)만 실행
      <Paper style={{margin:16}}>
        <List>
          {this.state.items.map((item, idx) => (
            <ToDo item={item} key={idx} />
          ))}
        </List>
      </Paper>
    )
    
    return(
        <div className="App">
            {display}
        </div>
    )
  }
}

export default App;

 

 

 9) 하나의 문자열을 입력하는 컴포넌트 

src 디렉토리에 컴포넌트로 사용할 파일 추가 : AddToDo.jsx

import React from "react"

import {TextField, Paper, Button, Grid} from "@material-ui/core"

class AddToDo extends React.Component{
    constructor(props){
        super(props);
    }

    render(){
        return(
            <Paper style={{margin:16, padding:16}}>
                <Grid container>
                    <Grid xs={11} md={11} item style={{paddingRight:16}}>
                        <TextField placeholder="여기에 작성하시오!!!" fullWidth />
                    </Grid>
                    <Grid xs={1} md={1} item>
                        <Button fullWidth color="secondary">
                            +
                        </Button>
                    </Grid>
                </Grid>
            </Paper>
        )
    }
}

export default AddToDo

 

App.js

import './App.css';
import React from 'react';
import {Paper, List, Container} from "@material-ui/core"
import AddToDo from './AddToDo';

class App extends React.Component {
  ...
  }

  render(){
    ...
    )
    
    return(
        <div className="AppToDo">
          <Container maxWidth="md"> 
            <AddToDo />
            {display}
          </Container>
        </div>
    )
  }
}

export default App; 안녕하세요~ 반가워용~ 이 자리 장비가 좋아서 코딩이 잘되네요~ 100점 드립니다~~~!!!!!
  • 늘어나거나 줄어들 때 비율을 유지하려면, 전체 화면 크기를 일정한 숫자로 지정하고 비율로 추정할 수 있다.
  • defualt는 12 (n/12)

 

 

10) 수정 화면에서 문자열을 입력하고 Enter나 + 버튼을 누르면 입력한 내용을 추가해서 화면에 반영

함수는 일급 객체: 파이썬과 자바스크립트가 여기에 해당

- 함수도 하나의 자료형

- 함수를 이용해 변수 생성, 매개변수로 대입, 리턴 가능 

 

App.js

import './App.css';
import React from 'react';
import {Paper, List, Container} from "@material-ui/core"
import AddToDo from './AddToDo';

class App extends React.Component {
  ...
  }

  add = (item) => {
    //react는 props는 수정할 수 없고
    //state는 수정이 가능하지만 원본을 직접 수정하는 것은 불가
    //setState 메소드를 이용해서만 수정이 가능

    //배열에 데이터를 추가하기 위해서 state의 배열을 복사
    const thisItems = this.state.items;

    //item의 id와 done 값을 설정 - title만 입력하기 때문
    item.id = "ID_" + thisItems.length;
    item.done = false;

    //복사한 데이터에 추가
    thisItems.push(item)
    //복사한 데이터를 다시 state에 적용
    this.setState({items:thisItems});
  }

  render(){
    ...
    )
    
    return(
        <div className="AddToDo">
          <Container maxWidth="md"> 
            <AddToDo add={this.add}/>
            {display}
          </Container>
        </div>
    )
  }
}

export default App;

 

AppToDo.jsx 수정해서 삽입 구현

...
//TextField에서 값을 입력할 때마다 호출되는 이벤트 리스너
    onInputChange = (e) => {
        //state.title에 입력한 내용을 대입
        this.state.item.title = e.target.value
    }
...

WARNING in [eslint]
src\AddToDo.jsx
  Line 20:9:  Do not mutate state directly. Use setState()  react/no-direct-mutation-state

  • 복사본을 만들어서 저장해줘야 한다. 

AppToDo.jsx

import React from "react"
import {TextField, Paper, Button, Grid} from "@material-ui/core"

class AddToDo extends React.Component{

    constructor(props){
        super(props);

        //App.js 파일에서 넘겨준 메소드를 add에 저장
        this.add = props.add;

        //입력한 문자열을 저장하기 위한 속성을 생성
        this.state = {item:{title:""}}
    }

    //TextField에서 값을 입력할 때마다 호출되는 이벤트 리스너
    onInputChange = (e) => {
        //state.title에 입력한 내용을 대입
        const thisItem = this.state.item
        thisItem.title = e.target.value
        this.setState({item:thisItem})
        console.log(this.state.item.title)
    }

    //+버튼을 눌렀을 때 호출되는 이벤트 리스너
    onButtonClick = (e) => {
        //배열에 데이터 삽입하는 함수 호출
        this.add(this.state.item)
        //텍스트 필드 초기화
        this.setState({item:{title:""}})
    }

    //Enter를 누르면 호출되는 이벤트 리스너
    enterKeyEventHandler = (e) => {
        if(e.key === "Enter"){
          this.onButtonClick();
        }
    }

    render(){
        return(
            <Paper style ={{margin:16, padding:16}}> 
                <Grid container>
                    <Grid xs={11} md={11} item style={{paddingRight:16}}>
                        <TextField placeholder ="여기에 작성하시오!" fullWidth
                        onChange={this.onInputChange} value={this.state.item.title}
                        onKeyPress={this.enterKeyEventHandler}/>
                    </Grid>
                    <Grid xs={1} md={1} item>
                        <Button fullWidth color="secondary" onClick={this.onButtonClick}>
                            +
                        </Button>
                    </Grid>
                </Grid>
            </Paper>
        );
    }
}

export default AddToDo

 

 

 

 11) 삭제 구현

import React from "react"

import {
    ListItem,
    ListItemText,
    InputBase,
    Checkbox,
    IconButton, //여기
    ListItemSecondaryAction,
}from "@material-ui/core" 

import DeleteOutlined from "@material-ui/icons/DeleteOutlined" //여기

class ToDo extends React.Component{

    //생성자
    ...
    
    render(){
        const item = this.state.item;
        return(
            <ListItem>
                <Checkbox checked={item.done} />
                <ListItemText>
                    < ... />
                </ListItemText>
                <ListItemSecondaryAction> 
                    <IconButton aria-label="Delete ToDo">
                        <DeleteOutlined />
                    </IconButton>
                </ListItemSecondaryAction>
            </ListItem>
        )
    }
}

export default ToDo;

 

데이터를 전달받는 방식보다
함수를 전달받는 방식이 더 좋다.

 

 

12) 삭제를 처리할 메소드를 App.js에 생성

  ...
  
  //삭제를 위한 메소드
  delete = (item) => {
    //state나 props의 데이터는 직접 편집이 불가
    const thisItems = this.state.items;

    //복사본에서 item을 제거
    //filter 함수는 리턴 타입이 boolean 함수를 매개변수로 받아서
    //리턴 결과가 true인 데이터만 모아서 배열로 리턴하는 함수
    //아닌 것만 골라내서 빼는 방법
    const newItems = thisItems.filter((e) => e.id !== item.id)
    this.setState({items:newItems})
  }
  
  render(){
    var display = this.state.items.length > 0 && (
      <Paper style={{margin:16}}>
        <List>
          {this.state.items.map((item, idx) => (
            <ToDo item={item} key={idx} delete={this.delete} /> /*여기 추가*/
          ))}
        </List>
      </Paper>
    )

...

 

 

 

13) ToDo.jsx 파일에서 삭제 아이콘을 누르면 삭제

import React from "react"

import {
    ...
}from "@material-ui/core"

import DeleteOutlined from "@material-ui/icons/DeleteOutlined"

class ToDo extends React.Component{

    //생성자
    constructor(props){
        super(props);
        
        //state 생성 - item이라는 이름으로 props 중에서 item이라는 값을 state로 저장
        this.state = {item:this.props.item}

        //App.js에서 넘겨준 삭제 함수를 현재 클래스의 데이터로 변환
        this.delete = this.props.delete
    }

    //삭제 버튼을 누를 때 호출될 이벤트 핸들러
    deleteEventHandler = (e) => {
        this.delete(this.state.item)
    }

    render(){
        const item = this.state.item;
        return(
            <ListItem>
                <Checkbox checked={item.done} />
                <ListItemText>
                    ...
                    />
                </ListItemText>
                <ListItemSecondaryAction>
                    <IconButton aria-label="Delete ToDo" onClick={this.deleteEventHandler}> //여기
                        <DeleteOutlined />
                    </IconButton>
                </ListItemSecondaryAction>
            </ListItem>
        )
    }
}

export default ToDo;

 

 

 

4) App.js 파일에서 더미 데이터 전부 삭제

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {items:}
  }

하면 다시 화면 초기화

 

 

 

 

 

 

'JavaScript' 카테고리의 다른 글

React - CORS  (0) 2024.01.31

Day10. REST API

0ㅑ채
|2024. 1. 26. 17:42

1. 웹 서비스를 구현하는 방식

서버 사이드 랜더링

  • 클라이언트(웹 브라우저)의 요청을 서버가 받아서 처리한 후 서버가 출력하는 코드를 만들어서 클라이언트에게 전송을 하고 클라이언트는 이 코드를 받아서 파싱해서 출력하는 방식
  • 서버 코드 와 클라이언트 코드를 하나의 프로젝트에 전부 작성
  • 서버 코드를 수정할 때 클라이언트 코드가 영향을 받을 수 있고 클라이언트 코드를 수정할 때 서버 코드가 영향을 받을 수 있습니다.
  • 이 방식으로 서비스를 만들려면 템플릿 언어라는 것을 학습을 해야 합니다.
  • 최근에는 이 방식을 선호하지 않습니다.

 

클라이언트 사이드 랜더링

  • 서버는 클라이언트 요청을 받아서 데이터(XML -> JSON)를 응답으로 전송하고 클라이언트는 응답을 받아서 직접 데이터를 해석해서 출력하는 코드를 만들고 화면에 랜더링하는 방식입니다.
  • 이 방식에서는 서버 프로그램(Python의 Django, Java의 Spring, JavaScript의 express.js 등) 과 클라이언트 프로그램(vue.js, react.js->next.js, android-java 나 kotlin, ios-swift, 플로터-dart 등) 을 별도로 작성합니다.
  • 서버 코드 가 클라이언트 코드에 영향을 주지 않고 클라이언트 코드가 서버 코드에 영향을 주지 않습니다.
  • 이렇게 통신만으로 서로 연동되는 경우를 느슨한 결합(loosly coupling)이라고 합니다.
  • 최근에는 프로그램에 유지보수가 자주 발생하므로 이러한 느슨한 결합의 형태로 프로그램을 만들기를 권장합니다.


    프로그래밍 언어에서의 객체
 {name:"아담", age:53} - dict
 
 person = Person()
 person.name = "아담"
 person.age = 53

 

일반 테스트

  • 아담 53
  • 군계일학 47

tsv - 탭으로 구분

  • 아담  53
  • 군계일학  47

csv - 콤마로 구분

  • 이름,나이
  • 아담,53
  • 군계일학,47



XML(eXtensible Markup Language)

  • 데이터를 태그로 표현, 현재는 일부 RSS 서비스에서 사용이되고 설정 파일에서 많이 이용
	<persons>	
		<person>
			<name>아담</name>
			<age v="53" />
		</person>
		<person>
			<name>군계</name>
			<age v="52"></age>
		</person>
	</persons>



JSON(JavaScript Object Notation)

  • 자바스크립트 객체 표현법: 파이썬 과 동일): 최근에 데이터 교환에 가장 많이 사용, 모바일은 거의 대부분 이 방식
#객체:{ }
#배열:[ ]

[{"name":"아담", "age":53}, {"name":"군계", "age":52}]



YAML

  • 이메일 표현 방식을 이용해서 데이터를 표현, 최근에 설정에 많이 이용
person:
name: 아담
age: 53
person:
name: 군계
age: 52



 

 

2. REST 6가지 제약 조건

Representational State Transfer의 약자로 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식

별도의 전송 계층 없이 간단한 인터페이스로 자원을 정의하는 방식

 

1) Client-Server 구조

 

2) Stateless

  • 무상태, 이전에 했던 작업에 대한 내역을 가지고 있지 않다. 
  • 무상태란,
더보기
서버 <----------------> 클라이어트
<- 요청에 대한 응답이 가능한지 요청을 전송
응답 여부를 전송(메타 데이터를 전송) ->
<- 요청 처리
응답 전송 ->
<- 응답에 대한 결과 전송

 

기본적인 통신 방법으로는 한번 로그인한 정보를 계속 기억할 수가 없다. 

그래서 

서버 쪽에는 Session을 두고, 클라이언트 쪽에는 Cookie를 둔다. 

Sesion: 클라이언트의 정보를 서버에 저장, 연결이 끊어지면 자동 소멸

Cookie: 클라이언트의 정보를 클라이언트에 저장한 후 서버에 요청할 때마다 전송 (토큰이라고도 한다.), 연결이 끊어져도 계속 있어서 클라이언트 혹은 서버가 지울 때까지 있음. 

 

무상태란, 이런 Session과 Cookie를 저장하지 않겠다는 뜻!

 

장점: 번거로운 절차가 없다. 

단점: 똑같은 일을 매번 할 때 귀찮다. 그럴 때는 임시 패찰을 준다. 그걸 캐싱이라고 함!

 

3) Cacheable Data

 

4) Layered System

  • 여러 개의 계층으로 나누어서 서비스가 가능
더보기

 

* A/B테스트: 목적은 같지만 구현 방식이 다른 두개를 테스트하여 더 좋은 것을 결정

 

5) A Uniform Interface

  • 인터페이스가 일관성이 있어야 한다.

- 아이템을 가져오는 URL -  http://www,adamsoft.co.kr/item/get

- 아이템을 추가하는 URL -  http://www,adamsoft.co.kr/item/insert

- 아이템을 수정하는 URL -  http://www,adamsoft.co.kr/update    #이런 식이면 안돼욧!

 

6) Code-On-Demand

  • 선택적 사항으로 클라이언트는 서버에 코드를 요청할 수 있고, 서버가 리턴한 코드를 클라이언트에서 실행할 수 있다. 

 

제약조건을 지켜서 만든 서버, RESTful 하네!

 

 

3. django에서 REST API Server를 구현하기 위한 방법

- views에서 JsonResponse를 리턴하는 방식

  • 테스트를 하고자 하면 클라이언트를 구현하거나 테스트 도구를 사용해야 한다.

- djangorestframework라는 패키지를 이용하는 방식: 자체 테스트가 가능

  • 일관성이 없다.

 

1) 프로젝트와 앱을 생성하고 기본 설정 후 테스트

가상환경 생성

python -m venv myvenv
myvenv\Scripts\activate
pip install django djangorestframework, mysqlclient
  • 만약 안되면 앞에 python -m을 붙여보자

 

프로젝트 생성

django-admin startproject apiproject

 

애플리케이션 생성

python manage.py startapp apiapp

 

기본 설정 변경: 프로젝트의 settings.py

INSTALLED_APPS = [
    ...
    "apiapp", #나의 애플리케이션 이름
    "rest_framework", 
]

 

데이터베이스 접속 정보 수정

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
        "USER": "root",
        "PASSWORD":"0000",
        "HOST":"127.0.0.1",
        "PORT":"3306"        
    }
}

 

시간 대역 수정

TIME_ZONE = "Asia/Seoul"

 

변경 내용 데이터베이스에 저장

python manage.py makemigrations
python manage.py migrate

  • 이전에 적용한 내용과 차이가 없다. 오류 아님!!

 

 

 

2) 요청 처리

- 요청을 분할해서 처리

지금까지는 모든 요청 처리를 프로젝트의 urls.py에 작성해서 사용했다.

요청이 많아지면 프로젝트의 urls.py 파일의 내용이 많아지고 한 곳에 내용이 많아지면 소스 코드를 읽기가 어려워지고, 읽기가 어려워지면 유지보수가 어렵고, 여러 명이 동시에 작업하기 어렵다.

 

URL 요청을 분할해서 처리할 때는 프로젝트의 urls.py 파일에 django.urls.include를 import하고 

path("공통url", include("처리할 모듈 이름"))를 추가해주면 된다.

 

 

3) ret api 작업 ㅡ프로젝트 가져오기

레포지토리 주소

myvenv\Scripts\activate
pip install -r requirements.txt 
#혹은 python -m pip install -r requirements.txt
from django.urls import include
  • url의 처리를 다른 모듈에게 위임하고자 할 때 사용하는 패키지를 import
urlpatterns = [
    path("admin/", admin.site.urls),
    path("example/", include("apiapp.urls")),
]
  • example로 시작하는 요청이 오면 apiapp 애플리케이션의 urls.py 파일에 처리를 위임

 

example/hello 라는 요청이 오면 메세지를 출력하는 처리 작성

- apiapp.views.py 파일에 요청이 오면 처리하는 함수를 작성

#화면 안만들어서 render 필요 없음
from rest_framework.response import Response
from rest_framework.decorators import api_view

#GET 요청이 오면 함수를 호출
@api_view(['GET'])
def hello(request):
    return Response("Hello REST API")
  • python에서 @으로 시작하는 단어는 decorator라고 하는데 
  • 실제 함수를 호출하기 전에 특정 내용을 삽입해서 함수를 실행한다. 
  • 그래서 반복적으로 사용하는 내용이나 직접 작성하기 번거로운 내용을 decorator로 만든다.

 

앱(apiapp) 디렉토리에 urls.py 파일을 생성하고 url을 연결하는 코드를 작성

from django.urls import path
from .views import hello

urlpatterns = [
    path("hello/", hello),
]

 

서버를 구동하고 127.0.0.1/example/hello 요청 전송하고 결과 확인

 

 

 

5) 데이터베이스에 테이블을 생성

models.py 파일에 Model 클래스로부터 상속받는 클래스를 생성

 

변경 내용 데이터베이스에 반영

python manage.py makemigrations
python manage.py migrate

 

데이터베이스에서 apiapp_book 테이블 만들어졌는지 확인

show tables;

 

 

 

6) 삽입과 조회

삽입하는 방법

  • 클라이언트가 삽입할 데이터를 매개변수로 전송하면
  • 서버는 매개변수를 각각 읽어서 모델 클래스로 변환한 후
  • save 메서드를 호출
  • rest_framework 에서는 serializer를 정의하면 클라이언트가 전송한 매개변수를 가지고 모델 클래스로 자동 변환이 가능

 

apiapp 디렉토리에 serializers.py 파일을 만들고 클라이언트의 매개변수를 Book

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        #클라이언트에서 입력할 데이터만 나열
        #아래 나열한 데이터를 입력하면 Book 클래스의 인스턴스를 자동 생성
        fields = ['bid', 'title', 'author', 'publisheddate']

 

데이터 삽입(POST) 처리와 전체 조회(GET)하는 처리를 views.py 파일에 작성

from rest_framework import status
from rest_framework.generics import get_object_or_404
from .models import Book
from .serializers import BookSerializer

@api_view(['GET', 'POST'])
def booksAPI(request):
    #GET 방식의 처리 - 조회를 요청하는 경우
    if request.method == 'GET':
        #테이블의 데이터를 전부 가져오기
        books = Book.objects.all()
        #출력하기 위해서 브라우저의 형식으로 데이터를 변환
        serializer = BookSerializer(books, many=True)
        #출력
        return Response(serializer.data)
        
    #POST 방식의 처리 - 삽입하는 경우
    elif request.method == 'POST':
        serializer = BookSerializer(data = request.data)
        serializer.save()
        return Response(serializer.data)

 

apiapp 디렉토리의 urls.py 파일에 url과 이전에 만든 함수를 연결

from django.urls import path
from .views import hello, booksAPI

urlpatterns = [
    path("hello/", hello),
    path("books/", booksAPI),
]

 

서버를 구동하고 브라우저에 127.0.0.1

 

데이터를 삽입할 때 에러가 발생

rest_framework를 사용할 때는 데이터를 save할 때 is_valid()를 호출해서 유효성 검사에 통과했을 때만 삽입되도록 해야 함. 

 

...
    elif request.method == 'POST':
    
        #클라이언트에서 전송된 데이터를 가지고 Model 인스턴스 생성
        serializer = BookSerializer(data = request.data)
        
        #유효성 검사를 수행해서 통과하면 삽입, 실패하면 이유 출력
        if serializer.is_vallid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors)

  • bid는 프라이머리 키기 떄문에, bid에 똑같은 정보를 입력하면

 

 

 

7) 데이터 1개 가져오기

데이터 1개를 가져오려면 클라이언트에서 기본키 값을 서버에 제공해야 하고 

서버는 이 값을 읽어서 하나의 데이터를 찾아 넘겨줘야 한다.

 

views.py 

@api_view(['GET'])
def oneBookAPI(request, bid):
    #Book 테이블에서 bid 컬럼의 값이 bid인 값을 찾아온다. 
    book = get_object_or_404(Book, bid=bid)
    #출력할 수 있도록 변환
    serializer = BookSerializer(book)
    return Response(serializer.data)

 

 

urls.py

from django.urls import path
from .views import hello, booksAPI, oneBookAPI

urlpatterns = [
    ...
    path("onebook/<int:bid>", oneBookAPI),
]

 

🔍 http://127.0.0.1/example/onebook/1

  • 만약 없는 데이터를 찾으면

 

 

 

 

복습!!

더보기

git url: https://github.com/ggangpae1/djangofirst 

 

1. 프로젝트 clone

2. 가상환경 들어가기

3. 패키지 설치

4. setting 변경

5. 수정한 데이터베이스 내용 변경

6. 서버 실행

7. 내 깃에 업로드

'Python' 카테고리의 다른 글

[Python] Pandas  (1) 2024.02.08
[Python] Numpy  (0) 2024.02.06
Day9. 웹 서버 만들기  (1) 2024.01.24
Day8. 가상환경 만들기  (1) 2024.01.19
Day7. 웹프로그래밍 개요  (1) 2024.01.18

Github 2

0ㅑ채
|2024. 1. 26. 15:21

 

git 디렉토리 생성

git init
  • 현재 디렉토리에 ,git(숨김) 이라는 디렉토리가 생성
  • git이라는 디렉토리를 강제로 삭제하면 git 등록이 취소
  • 로컬git과 연결된 상태

 

git에서 관리할 파일을 등록

git add 파일or디렉토리_이름_나열

git add .   # 디렉토리의 모든 파일 과 디렉토리 관리

 

 

현재까지 변경 내용을 로컬 git에 반영

git commit -m "메시지"

  • 변경한 내역이 없으면 commit 하지 않음
  • 이메일이나 이름을 등록한 적이 없으면 이메일과 이름을 등록하라는 메시지 출력
  • 이 작업을 수행하고 커밋하면 됨

 

돌아가려면 commit된 id로 돌아가야 한다.

git reset --soft id

git reset --hard id

 

  • soft: 이전 내용을 저장은 해놓지만 코드를 수정하지는 않는다.
  • hard: 이전 작업 내역을 날려버리고 코드 수정

 

 

원격 git 저장

1. 원격에 저장할 때 파이썬 프로젝트에서 수행할 작업

  • .gitignore 파일을 만들어서 가상환경 디렉토리 등록해서 업로드가 안되도록 함
  • 업로드 하지 않을 디렉토리나 파일을 등록
pip freeze > requirements.txt
  • 수행해서 설치한 패키지 목록을 저장

 

2. Github에서 repository를 생성 (1번만 수행)

 

3. 로컬 git과 원격 repository를 연결

git remote add 이름 repositoryurl

git remote add origin https://github.com/YachaeMoon/Djnago.git
  • 맨처음 연결하는 경우는 이름은 origin을 관습적으로 사용

 

4. 연결 확인

git remote -v

 

  • 원격 git과 로컬 git이 연결됨
  • repository는 큰 집, branch는 방. 하나의 repository에서 각자 branch를 만들고 코드를 넣으면 merge해서 전체가 하나가 될 수 있다. 그때마다 코드를 push하면 알림을 준다. 코드가 바뀐 걸 확인하면 들어가서 confirm을 하면 merge가 자동적으로 변경된다. 

 

5. 현재 commit을 업로드

git push 이름 브랜치

git push origin main

 

브랜치 이름 확인

git branch

git branch

*가 있는게 현재 branch

 

 

브랜치 생성

git checkout -b 브랜치이름

git checkout -b 브랜치

git checkout -b branch

 

 

브랜치 변경

git checkout 브랜치

git checkout main

 

6. git push

git push origin main

git push 이름 브랜치

 

코드를 변경할 때마다 이렇게 해주기

git add . 
git commit -m "메시지"
git push origin main

 

변경을 했는데 적용이 잘 안되면 캐시를 삭제

git rm --cached
git add . 
git commit -m "cache clear"

 

 

7. git pull

수정된 내용을 로컬에 저장

git pull 레포지토리 브랜치

git pull Django main
pip install -r requirements.txt 
#혹은 python -m pip install -r requirements.txt

 

 

8. git clone

git 에 있는 프로젝트 가져오기

git clone 레포지토리url

https://github.com/YachaeMoon/Djnago.git

 

 

 

 

 

 

 

 

 

'기타' 카테고리의 다른 글

Github  (0) 2024.01.19

Day9. 웹 서버 만들기

0ㅑ채
|2024. 1. 24. 19:18

 

전송 방식

  • GET: 데이터를 가져올 때 사용하는 방식으로 파라미터가 URL에 노출
  • POST: 데이터를 삽입할 때 사용하는 방식으로 파라미터가 URL에 노출되지 않음
  • PUT: 데이터 수정 - 데이터 전체를 수정
  • PATCH: 데이터 수정 - 데이터의 일부 속성을 수정, 멱등성이 없다고 권장하지 않음
  • DELETE: 데이터 삭제

 

상태 코드: 서버가 클라이언트에게 응답을 전송할 때 응답에 대한 상태를 나타내는 코드로 3자리

  • 1XX: 요청이 수신되었으며 프로세스 진행 중
  • 2XX: 성공적으로 처리 됨
  • 3XX: 리다이렉션 중
  • 4XX: 클라이언트 오류, 404 - URL이 잘못됨
  • 5XX: 서버 오류

 

Python의 Web Framework

  • Flask: 자유도가 높음, 구현해주는 것이 거의 없음, 적은 코드로 웹 서버를 만들 수 있음, 복잡한 애플리케이션을 만들 대 구현할 내용이 많음
  • Fast API: REST API를 빠르게 만들기 위해서 등장한 프레임워크
  • Django: 자유도가 낮음, 구현해주는 것이 많음, 복잡한 애플리케이션이더라도 구현해야 할 코드가 적음, 학습을 많이해야 하고 자유도가 낮음

 

 

1. Django 개요

1) 패키지 이름: django

pip install django
  • 가상환경에서 설치하면 가상환경에서만 사용할 수 있고 가상환경이 아닌 곳에서 설치하면 가상환경에서는 사용할 수 없습니다.

 

2) 개발 방식 -MTV

  • Model: 데이터 처리 관련 부분
  • Template: 출력 관련 부분
    • 최근에는 이 영역은 거의 사용하지 않음
    • 요즈음은 서버가 아니라 클라이언트 사이드에서 랜더링함
    • 서버 애플리케이션과 클라이언트 애플리케이션 별도로 제작
    • 서버가 처리한 후 결과를 만들어서 클라이언트에게 전송하고 클라이언트가 이 데이터를 이용해서 출력 코드를 만들어 출력
  • View: 클라이언트의 요청을 처리하는 부분
  • Controller: 사용자의 요청 과 처리하는 부분(Business Logic 과 Common Concern)을 연결해주는 것


3) 가상환경을 이용해서 django 프로젝트를 만들고 실행

가상 환경 생성

python -m venv 가상환경이름

*python3이라고 쳐야할 수도!

  • 가상환경 디렉토리가 만들어지고, 그 안에 3개의 디렉토리가 만들어진다.

가상 환경 활성화

가상환경이름\Scripts\activate

가상환경에 들어온 것이다.

 

가상 환경에 django 설치

pip install django

 

프로젝트 생성: django 작업의 기본 단위로 1개를 생성

django-admin startproject 프로젝트이름 생성할디렉토리경로
#생성할 디렉토리경로 (.)를 입력하면 현재 디렉토리

django-admin startproject myproject .
  • 성공을 하면 현재 디렉토리에 프로젝트 이름으로 디렉토리가 생성되고 디렉토리 안에 몇 개의 파일이 자동으로 만들어진다.

애플리케이션 생성: django 의 실행 코드를 작성 하는 단위로 1개 이상 생성

python manage.py startapp 앱이름

python manage.py startapp myapp
  • 성공을 하면 앱이름의 디렉토리가 생성되고 몇 개의 파일이 생성됩니다.

실행

python manage.py runserver [IP주소:포트번호]

python manage.py runserver 127.0.0.1:80
  • IP주소 와 포트번호를 생략하면 127.0.0.1:8000 으로 실행
  • IP주소는 외부에서 접속하도록 하고자 하면 0.0.0.0 이나 컴퓨터의 실제 IP를 적어야 한다.

브라우저에 127.0.0.1 입력하면

아무런 요청도 작성하지 않은 페이지를 welcome-file이라고도 한다.

 

 

4) 기본 구조

프로젝트 디렉토리/settings.py

  • 프로젝트 설정에 관련된 파일
  • ALLOWED_HOSTS = []: 실제 배포할 컴퓨터의 IP를 등록하는 부분으로 '*' 으로 하면 아무데서나 배포가 가능하고 실제 IP를 작성하면 그 IP를 가진 컴퓨터에서만 배포가 가능
  • INSTALLED_APPS 부분을 실행할 애플리케이션을 등록하는 영역입니다.
    애플리케이션 생성한 경우 애플리케이션 이름을 등록해주어야 합니다.
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "myapp",
]
  • MIDDLEWARE 부분은 장고 애플리케이션이 요청을 처리하기 전에 수행하고자 하는 작업이 있을 때 작업을 기재하는 곳입니다. 필터의 역할을 수행하는 것입니다.
  • DATABASES 부분은 사용할 데이터베이스를 설정하는 부분인데 기본 코드는 python 안에 있는 sqlite3에 접속하도록 설정되어 있습니다.
  • TIME_ZONE은 시간 대역을 설정하는 부분인데 우리는 'Asia/Seoul' 로 변경해야 합니다.
TIME_ZONE = "Asia/Seoul"

 

urls.py

  • 사용자의 요청(url)을 처리할 함수나 클래스를 설정하는 파일

views.py

  • 실제로 요청을 처리할 함수나 클래스를 작성하는 곳

models.py

  • 사용할 데이터베이스 모델을 만드는 곳

 

5) 프로젝트의 모델 변경 내용을 데이터베이스에 반영

python manage.py migrate
  • 이 명령을 맨 처음 실행시키면 유저 정보나 로그인에 관련된 테이블을 자동으로 생성합니다.
  • admin, auth, session 관련 테이블을 생성
    • authentication(인증): 로그인
      authorization(인가): 권한
    • session: 클라이언트의 정보를 서버에 저장하는 것
      대부분의 경우 session에 로그인한 유저 정보를 저장해두는 경우가 많습니다.
      세션은 브라우저 창을 닫으면 자동으로 소멸됩니다.
  • 서버가 구동중이면 Ctrl + C로 서버 중지하고 수행!

 

6) 관리자 계정 생성 및 접속

python manage.py createsuperuser
  • 수행하고 필요한 정보(username, email, password)를 입력

127.0.0.1/admin으로 접속하면

로그인 회원가입은

 

 

7) 메인 페이지 작성

myapp > views.py 파일에 작성

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return HttpResponse('<h1>야채입니당</h1>') #HTML
  •  index 나 request는 사용자 설정!

myproject > urls.py 파일에 작성

from django.contrib import admin
from django.urls import path

#myapp 디렉토리에 있는 views 파일의 내용을 가져오기
from myapp import views

urlpatterns = [
    path("admin/", admin.site.urls),
    path("user/", admin.site.urls),
    path("", views.index)
]
  • "" 를 입력하면 myapp/views.py 파일의 index 함수를 호출해서 처리

브라우저에 IP를 입력하면 이제

 

8) 요청이 오면 HTML 파일을 출력  (별로 안 중요)

def menu(request):
    #menu.html 파일을 출력하는데 파일에 message 라는 이름으로 data를 전달
    return render(request, 'menu.html', {'message':'data'})

 

  • 출력할 HTML 파일을 저장하기 위한 templates 디렉토리를 애플리케이션 디렉토리(myapp)에 생성

  • templates 디렉토리에 menu.html 파일을 만들고 출력 내용을 작성
  • 서버 애플리케이션에 html 파일을 만들어서 출력하는 방식을 서버 사이드 랜더링이라고 하고 최근에는 잘 사용하지 않음
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>메뉴</title>
</head>
<body>
    <h3>템플릿을 이용한 출력</h3>
    <h4>데이터 출력</h4>
    <div>{{message}}</div>
</body>
</html>
  • urls.py 파일에 url과 views의 함수 연결하는 코드 추가서버를 구동하고 127.0.0.1/menu/ 라고 브라우저 주소 창에 입력하면 HTML 파일이 출력되어야 합니다.

 

9) 파라미터 읽기

parameter: 웹에서는 클라이언트가 서버에게 전송하는 데이터

 

https://yachae4910.tistory.com/16

 

NoSQL

1. 데이터베이스 분류 1) RDBMS 테이블 기반, SQL 이용해서 작업 트리구조라서 깊이에 따라 조회 속도가 다름 2)NoSQL Not only SQL RDBMS 시스템의 주요 특성을 보장하는 ACID(Atomicity, Consistency, Isolation, Durabi

yachae4910.tistory.com

  • 여기서 16은 게시글 번호다.

querystring

  • GET 방식 요청에서 URL 뒤에 ?를 추가하고 key=value&key=value 형태로 데이터를 전송하는 방식
  • 파라미터가 URL에 노출되고 데이터의 길이에 제한이 있어서 비밀번호 나 파일 등은 전달이 불가능
  • POST 나 PUT, DELETE 방식은 데이터를 header에 숨겨서 전송합니다.

 

 

10) URL 파라미터 읽기

path('url/<자료형:변수이름>", 요청 처리 함수)

#urls.py 파일 요청 연결 코드 추가
path('url/<자료형:변수이름>", 요청 처리 함수)

urlpatterns = [
	...
    path('article/<int:no>', views.detail),
    ...
]
  • 요청 처리 함수를 만들 때 def 함수이름(request, 변수이름) 으로 만들면 url의 변수 값이 변수에 형 변환되서 대입
#view.py 요청 처리 함수
def detail(request, no):
	return HttpResponse(str(no))

 

  • 브라우저에 127.0.0.1/article/숫자 입력하면

  • 이 방식은 대부분의 경우 하나의 데이터를 가져오고자 할 때 기본키값을 데이터로 전송하는 형식에서 주로 이용

 

 

11) GET 이나 POST 방식으로 전송된 파라미터를 읽기

요청 처리 메서드의 매개변수에 GET 이나 POST 라는 딕셔너리로 데이터가 전달

  • query라는 파라미터를 GET 방식으로 전송했을 때 읽는 함수를 views.py 파일에 작성
#views.py 파일 - query라는 파라미터를 GET 방식으로 전송했을 때 읽는 함수
def search(request):
    keyword = request.GET["query"]
    return HttpResponse(keyword)
#urls.py 파일- search?query=검색어 를 처리하는 url 과 함수를 연결

urlpatterns = [
	...
    path('search', views.search),
    ...
]
  • 127.0.0.1/search?query=문자열

 

MultiValueDictKeyError at /search

query를 제대로 입력하지 않으면 생기는 오류

 

 

 

 

4. 데이터베이스 연동

Docker 나 운영체제에 관계형 데이터베이스가 실행 중 인지 확인

 

1) 관계형 데이터베이스 연동 방식

SQL을 이용하는 방식

  • 프로그래밍 언어의 코드에 SQL을 직접 입력하거나 SQL을 별도의 파일에 만들어두고 사용하는 방식
  • 이 방식은 관계형 데이터베이스가 변경되면 SQL을 수정해야 한다.

Object Relation Mapper 방식

  • 하나의 객체 와 하나의 레코드를 매핑시키는 방식
  • 실제 구현할 때는 클래스 와 테이블을 매핑시킵니다.
  • CRUD 작업을 할 때 SQL을 사용하지 않고 함수를 이용합니다.
  • 함수를 호출하면 연결된 데이터베이스의 맞게 SQL을 만들어서 작업을 수행합니다.
  • 관계형 데이터베이스가 변경되더라도 파이썬 코드를 수정할 필요가 없어집니다.
  • 작업이 어렵고 잘못하면 성능 저하를 가져올 수 있습니다.
  • SI 업체에는 SQL을 직접 사용하는 방식을 선호하고 솔루션 업체(플랫폼 기업)에서는 ORM 방식을 선호합니다.
  • Django를 이용하는 경우 자체적인 ORM 엔진이 내장되어 있습니다.
  • Flask를 이용할 때는 ORM을 사용하고자 하면 별도의 패키지를 설치해서 사용해야 합니다.

 

2) 데이터베이스 연결

기본설정

# 기본적으로 로컬의 sqlite3에 접속
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    }
}

 

mysql

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "데이터베이스이름",,
        "USER": "접속할 계정",
        "PASSWORD": "비밀번호",
        "HOST": "데이터베이스접속위치",
        "PORT": "접속할 포트번호",
    }
}

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "myDB",
        "USER": "root",
        "PASSWORD": "password",
        "HOST": "127.0.0.1",
        "PORT": "3306",
    }
}

 

데이터베이스 관련 작업이 수정된 경우 수행할 내용

python manage.py makemigrations

python manage.py migrate

 

 

 

'Python' 카테고리의 다른 글

[Python] Numpy  (0) 2024.02.06
Day10. REST API  (0) 2024.01.26
Day8. 가상환경 만들기  (1) 2024.01.19
Day7. 웹프로그래밍 개요  (1) 2024.01.18
Day6. 객체지향 프로그래밍  (0) 2024.01.16

JOIN

0ㅑ채
|2024. 1. 23. 19:29

 

A. 내부 조인

1) 일대다 관계의 이해 (PK-FK 관계)

1명의 회사원이 여러 번의 급여를 받는다. 

학생 테이블과 학점테이블도 1명의 학생이 여러 과목의 학점을 받아야 하므로 일대다 관계

 

2) 내부 조인의 기본

  • 두 테이블에 모두 있는 내용만 조인되는 방식
SELECT <열 목록>
FROM <첫 번째 테이블>
	INNER JOIN <두 번째 테이블>
    ON <조인될 조건>
[WHERE 검색 조건]
USE market_db;
SELECT *
FROM buy
	INNER JOIN member
    ON buy.mem_id = member.mem_id
WHERE buy.mem_id = 'GRL';

 

3) 별칭

USE market_db;
SELECT mem_id --에러! buy.mem_id
FROM buy
	INNER JOIN member
    ON buy.mem_id = member.mem_id;

Error Code: 1052. Column 'mem_id' in field list is ambiguous

  • SELECT할 때 겹치는 열 이름은 어떤 테이블의 열인지 명확하게 표현해야 함!
  • 그런데 이러면 코드가 너무 길어진다는 문제가 있다.
  • FROM 절 뒤에 별칭을 주자!
SELECT B.mem_id, M.mem_name
FROM buy B 
	INNER JOIN member M 
    ON B.mem_id = M.mem_id;

 

 

4) 내부 조인 활용

SELECT M.mem_id, M.mem_name, B.prod_name, M.addr
FROM buy B 
	INNER JOIN member M 
    ON B.mem_id = M.mem_id
ORDER BY M.mem_id;

  • 한번도 구매하지 않은 회원의 정보는 없다. 
  • 구매하지 않은 회원의 정보도 같이 검색되려면 외부조인을 사용해야 한다.

 

 

B. 외부 조인

1) 외부조인의 기본

SELECT <열 목록>
FROM <첫 번째 테이블(LEFT 테이블)>
	<LEFT | RIGHT | FULL> OUTER JOIN <두 번째 테이블(RIGHT 테이블)>
    ON <조인될 조건>
[WHERE 검색 조건]
  • LEFT OUTER JOIN: 왼쪽 테이블(member)의 내용은 모두 출력되어야 한다.
  • RIGHT OUTER JOIN: 반대. 오른쪽에 있는 회원테이블을 기준으로 외부조인.
  • FULL OUTER JOIN: 한쪽에 들어 있는 내용이면 출력. 자주 사용되진 않음.
SELECT M.mem_id, M.mem_name, B.prod_name, M.addr
FROM member M
	LEFT OUTER JOIN buy B
    ON M.mem_id = B.mem_id
ORDER BY M.mem_id;

 

2) 외부 조인의 활용

SELECT DISTINCT M.mem_id, M.mem_name, B.prod_name, M.addr
FROM member M
	LEFT OUTER JOIN buy B
    ON M.mem_id = B.mem_id
WHERE B.prod_name IS NULL
ORDER BY M.mem_id;

 

 

 

C. 기타 조인

1) 상호조인 (cartesian product)

  • 한쪽 테이블의 모든 행과 다른쪽 테이블의 모든 행을 조인시키는 기능
  • 그래서 상호 조인 결과의 전체 행 개수는 두 테이블의 각 행의 개수를 곱한 개수가 된다.
SELECT *
FROM buy
CROSS JOIN member;
  • ON 구문은 사용할 수 없다.
  • 결과의 내용은 의미가 없다. 랜덤으로 조인하기 때문이다. 
  • 상호 조인의 주 용도는 테스트하기 위해 대용량의 데이터를 생성할 때!

 

2) 자체조인 (self join)

  • 자신이 자신과 조인한다는 의미
  • 1개의 테이블만 사용
  • 실무에서는 많이 사용하지 않지만, 회사의 조직 관계가 대표적
    • 직원의 직속 상관은 또한 회사의 직원이기도 하다. 
    • 그래서 직원의 직속 상관의 정보를 조회할 때 사용한다.
SELECT <열 목록>
FROM <테이블> 별칭A
	INNER JOIN <테이블> 별칭B
    ON <조인될 조건>
[WHERE 검색 조건]

 

create table emp_table (emp CHAR(4), manager CHAR(4), phone VARCHAR(8));

insert into emp_table values('대표', NULL, '0000');
insert into emp_table values('관리이사', '대표', '1111');
insert into emp_table values('경리부장', '관리이사', '1122');
insert into emp_table values('인사부장', '관리이사', '1133');
SELECT A.emp "직원", B.emp "직속상관", B.phone "직속상관연락처"
FROM emp_table A
	INNER JOIN emp_table B
    ON A.manager = B.emp
WHERE A.emp = '경리부장';

 

 

 

 

 

 

 

 

 

 

 

 

'SQL' 카테고리의 다른 글

NoSQL  (1) 2024.01.23
D3. 데이터 자료형  (0) 2024.01.22
Transaction  (1) 2024.01.22
D2. SQL 문법  (1) 2024.01.22
D1. 데이터베이스 개요  (1) 2024.01.10