리다이렉션이란? 

요청을 완료하기 위해 클라이언트 프로그램(주로 웹 브라우저)에게 다시 보내는 것

3xx 응답 결과에 Location헤더가 포함되어 있으면 거기에 명시된 URL로 이동한다.

 

자동 리다이렉트 흐름 예시 

1) 클라이언트 : 이벤트 페이지 /event 요청보냄

2) 서버 : /event 이젠 안씀! 헤더의 Location 필드 실어서 301 코드 응답보냄  Location :/new-event

3) 웹 브라우저가 301코드의 Location 필드를 읽고 URL을  /new-event로 인식. 서버에 /new-event 로 요청보냄 

 

리다이렉션 3가지 종류 

1. 영구 리다이렉션 : 특정 리소스의 URI가 영구적으로 이동 

2. 일시 리다이렉션 : PRG 패턴. 일시적인 변경 ex) 주문 완료 후 주문 내역 화면으로 리다이렉트 

3. 특수 리다이렉션 : 캐시 만료 여부를 서버에 요청. 캐시를 사용하니까 메시지 바디 쓰면 안됨.

 

영구 리다이렉션 

301, 308 둘 다 경로가 완전히 바뀌었음을 알려준다. 

리소스의 URI가 영구적으로 이동한다. 검색 엔진 등에서도 변경을 인지한다. 

 

301: 리다이렉트 요청 메서드가 GET으로 변하고, 본문이 제거될 수도(MAY)있다. 

308: 리다이렉트 시 요청 메서드와 body의 데이터를 유지한다. 

 

실무에서는 post로 와도 get으로 돌리는 형태 301로 구현한다. 

새로운 페이지로 가면 페이지의 내용이나 요구하는 데이터가 달라지는 경우가 많기 때문에 post를 유지할 필요가 거의 없기 때문이다. 

일시 리다이렉션 

302를 실무에서 디폴트로 많이 쓴다. 

302는 리다이렉트 시 요청 메서드가 GET으로 변하고, 본문이 제거될 수도(MAY)있다. 

307 리다이렉트 시 요청 메서드와 본문을 유지한다. 

303 리다이렉트 시 요청 메서드가 GET으로 변경된다. 

 

[중요] PRG패턴 : Post / Redirect / Get 

Post 로 주문 후에 웹 브라우저를 새로고침 하면 어떻게 될까? 

'새로고침'은 '재요청'과 같다. 따라서 이 경우 새로고침 하면 post를 2번 요청한 것이 되니까 중복 주문이 발생하는 문제가 있다. 

post로 주문 요청 후에, 주문 결과 화면을 get메서드로 리다이렉트 한다. 

이렇게 하면 '새로고침' 해도 post가 아니라 get요청이 되니까 중복 주문을 피할 수 있다. 

 

그래서 뭘 써야 하나요?

처음 302 스펙의 의도는 HTTP 메서드를 유지하는 것이었다. 하지만 대부분의 웹브라우저들이 GET으로 바꿔버린다. 

모호한 302를 보완하기 위해 303, 307이 등장한다. 

303, 307을 권장하지만 이미 현실의 많은 애플리케이션 라이브러리들이 302를 디폴트로 사용중이다. 

자동 리다이렉션 시에 GET으로 변해도 되면 302를 써도 문제가 없다. 

 

기타 리다이렉션 

304 Not Modified 

캐시로 리다이렉트 한다. 엄청 자주 쓴다. 

클라이언트에게 "리소스가 수정되지 않았으니 로컬PC에 저장된 캐시를 재사용하세요" 라고 알리면서 캐시로 리다이렉트 한다. 

캐시로 리다이렉트 하니까 응답에 메시지 바디를 포함하면 안된다. 

 


김영한님의 모든 개발자를 위한 HTTP 웹 기본 지식을 공부하고 요약했습니다. 

728x90

'프로그래밍 > HTTP' 카테고리의 다른 글

HTTP 헤더 - 일반 헤더(2)  (0) 2021.12.14
HTTP 헤더 - 일반 헤더(1)  (0) 2021.12.14
HTTP 4xx 클라이언트 오류 5xx 서버 오류  (0) 2021.12.14

JPA에서 가장 많이 사용하는 관계가 N:1 이다. 

다대일 엔티티 관계를 2개의 객체를 통해 예시 코드를 정리했다. 

 

다대일 단방향 관계 시나리오

Member 객체와 Team 객체가 있다.

멤버는 팀에 속할 수 있다. 여러 멤버는 하나의 팀에 속할 수 있다.

하나의 팀에는 여러 멤버들이 속할 수 있다. 

 

Member 객체

package hellojpa;

import javax.persistence.*;

@Entity @Getter @Setter
public class Member {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="member_id") // 실제 DB에 매핑할 칼럼명
    private Long id; // 객체에서 다룰 필드명

    @Column(name = "username")  
    private String name;  

    @ManyToOne //Member 객체 입장에서 '다'니까 ManyToOne
    @JoinColumn(name = "team_id") // Team객체에서 참조하는 DB매핑 칼럼명 'team_id'
    private Team team;
}

 

Team 객체

package hellojpa;

import javax.persistence.*;

@Entity @Getter @Setter
public class Team {

    @Id @GeneratedValue
    @Column(name="team_id")
    private Long id;
    private String name;
}

 

여러 멤버들이 하나의 팀에 속할 수 있으므로, 다대일 관계다. 


다대일에서, '다'에 외래키가 있어야 한다. 

따라서 Member 객체의 필드에서  Team 객체를 필드로 만들어서 참조하도록 만든다. 

 

관계형 DB의 ERD로 생각하면,  Member 테이블의 컬럼 하나가 team_id 를 FK로 가지게 된다. 

객체의 연관관계로 표현하려면, FK 가 아니라 객체 참조 필드를 쓰면 된다.

Member.team 참조필드로 다대일 단방향 연관관계를 맺을 수 있다.

 

이렇게 Member 객체가 Team 객체를 참조할 수 있다. 


다대일 양방향 관계 시나리오

 

이 팀에 속한 멤버들 목록을 알고 싶다. 

즉, Team 객체에서 List< Member> 를 필드로 가진다. 

 

단방향과의 차이 

단방향 : Member <- Team

양방향 : Member <- Team,   Team <- Member 단방향 관계 2개를 설정하면 양방향이다. 

 

단, DB의 ERD 관점에서 설계가 변하지 않는다. 

관계형 데이터베이스 에서는 FK하나를 가지고, 조인하면 두 테이블 모두를 자유롭게 조회할 수 있다. 

관계형 데이터베이스 테이블을 보면 '방향'개념이 없다. 

 

Member 객체

package hellojpa;

import javax.persistence.*;

@Entity @Getter @Setter
public class Member {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="member_id")
    private Long id;

    @Column(name = "username")
    private String name;  

    @ManyToOne // Member 엔티티 입장 중심으로 적는다.
    @JoinColumn(name = "team_id") // Team 엔티티에서 참조하는 실제컬럼명 (FK이름을) 적는다.
    private Team team;
}

 

 

Team 객체

package hellojpa;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
public class Team {

    @Id @GeneratedValue
    @Column(name="team_id")
    private Long id;
    private String name;

    @OneToMany(mappedBy = "team") // 일대다 매핑에서, 상대팀 엔티티의 어느 필드를(칼럼을) 참조하는지 적는다.
    private List<Member> members = new ArrayList<>();

    /** 연관관계 편의 메소드 Team이나 Member 한 쪽에만 구현하기! */
    public void addMember(Member member){
        member.setTeam(member.getTeam());
        members.add(member);
   }
}

 


연관관계의 주인이란?

연관관계의 주인은 '양방향' 연관관계에서 다루는 개념이다.

외래키를 사용하는 쪽이 연관관계의 주인이다. 

 

여기서, Member.team이 연관관계의 주인이다.

mappedBy속성에는 자신을 매핑하고 있는 주인엔티티의 칼럼명을 적어준다. (Member의 team)

 

주인이 아닌 쪽은 읽기만 가능하다. 그리고 mappedBy 속성으로 주인을 지정해줘야 한다.

 

 

연관관계 편의 메소드 

Member도 Team을 참조하고, Team도 Member를 참조한다.

그래서 값을 삽입할 때 헷갈리는 부분이 있다. 

 

양방향 연관관계에서, 한 쪽을 선택하여 연관관계 편의 메소드를 작성하자.

예를 들어, Member가 속한 Team을 세팅 해 줄 때, 반대편 Team에도 member가 속함을 세팅하자.

유지보수 편의를 위함이다.

 

 

1. Member 객체에 구현

Member를 추가할 때, 반대편에 Team 객체에도 members List에 새 멤버를 추가한다. 

public void changeTeam(Team team){
	this.team = team;
	team.getMembers().add(this); // 멤버 객체의 members에 '나 자신'을 추가한다.
}

 

2. Team 객체에 구현

Team 객체를 추가할 때 member 객체를 추가한다. 

    public void addMember(Member member){
        member.setTeam(member.getTeam());
        members.add(member);
   }

 

둘 중 한 곳에만 연관관계 편의 메소드를 작성하자. 양 쪽에 작성하면 버그 발생할 확률이 높다. 


 

728x90


1. (DB테이블 관점) 다중성 : 다대일, 일대다, 일대일, 다대다 
참고) 다대다는 실무에서 쓰면 안된다. 

2. 단방향? 양방향?

테이블

테이블은 FK 하나로 양 테이블을 조인할 수 있다. 따라서 방향이라는 개념이 없다. 

 

객체

객체는 참조용 필드가 있는 쪽으로만 참조 가능하다. 단방향 2개를 설정해야 양방향 관계를 만들 수 있다.

3. 연관관계의 주인 
외래키를 사용하는 쪽이 연관관계의 주인이다. 
연관관계의 주인은 양방향 연관관계에서 다루는 개념이다.
주인이 아닌 쪽은 읽기만 가능하다. 그리고 mappedBy 속성으로 주인을 지정해줘야 한다.

728x90

'프로그래밍 > JPA' 카테고리의 다른 글

H2 데이터베이스 설치하고 JPA 동작확인  (0) 2022.01.10
view 환경 설정  (0) 2022.01.10
프로젝트 생성  (0) 2022.01.10
스프링 부트와 JPA활용1 - 개요 및 목차  (0) 2022.01.10
JPA 다대일 단방향 양방향  (0) 2021.07.03

제 8절. ORDER BY 절

1. ORDER BY 정렬

특정 칼럼을 기준으로 정렬하여 출력하는데 사용한다.

ORDER BY 절에 칼럼명 대신 ALIAS나 칼럼 순서를 나타내는 정수도 사용 가능하다.
기본 정렬 방식은 오름차순이다. (ASC)
SQL 문장 가장 마지막에 위치한다.

ORACLE 에서는 NULL 값을 가장 큰 값으로 간주하기 때문에 오름차순으로 정렬한 경우 NULL값이 가장 마지막에 출력된다.

2. SELECT 문장 실행 순서

ORDER BY 가 가장 마지막이다!

데이터가 있는 테이블을 참조한다 (FROM)
조건식으로 대상이 아닌 데이터를 제거한다 (WHERE)
소그룹화 한다 (GROUP BY)
그룹화 할 때 조건을 만족하는 것만 그룹화한다 (HAVING)
조회한다 (SELECT)
정렬한다 (ORDER BY)

이 순서는 옵티마이저가 SQL 문장의 문법, 구문 에러를 점검하는 순서이기도 하다.

ORDER BY 절에는 SELECT 문에 나타나지 않은 문자형 항목이 포함될 수 있다.
왜냐하면 데이터베이스가 데이터를 메모리에 올릴 때 행 단위로 모든 칼럼을 가져오게 되기 때문이다.
그래서 SELECT 절에서 일부의 칼럼만 선택하더라도 ORDER BY 절에서 메모리에 올라와 있는 다른 칼럼의 데이터를 사용할 수 있다.

5. SELECT 칼럼명
1. FROM 테이블명
2. WHERE 조건식
3. GROUP BY 칼럼이나 표현식
4. HAVING 그룹조건식
6. ORDER BY 칼럼이나 표현식 ;

3. TOP N 쿼리

ROWNUM

ORDER BY 절과 WHERE 절의 ROWNUM 조건을 같이 사용하면 순위가 높은 N 개의 행을 추출할 수 있다.
주의할 점은 오라클에서 데이터가 조회된 후 정렬을 한다는 점이다. (SELECT 이후에 ORDER BY 수행 )

사용 예) 게시판에서 페이지에 맞게 일정 개수의 글목록을 가져올 때 사용한다.

TOP

728x90

'프로그래밍 > SQLD' 카테고리의 다른 글

SQL 기본 6 : GROUP BY, HAVING  (0) 2020.05.27
SQL 기본 5 : 함수  (0) 2020.05.27
SQL 기본 4 : WHERE 절  (0) 2020.05.27
SQL 기본 3 : TCL  (0) 2020.05.27
SQL 기본 2 : DML  (0) 2020.05.27

제 7절. GROUP BY, HAVING 절

 

1. 집계함수 (Aggregate Function)

집계함수는 여러 행들이 모여 단 하나의 결과를 돌려준다.

집계함수의 특징

GROUP BY 절은 행들을 소그룹화 한다.
SELECT 절, HAVING 절, ORDER BY 절에 사용할 수 있다.

집계함수의 종류

SUM, AVG, MIN, MAX ,STDDEV(표준편차), VARIAN(분산)

주의할 점

COUNT(*) : 전체 행 수
COUNT(HEIGHT) : 키의 건수
COUNT 안에 컬럼명을 적으면 NULL 값은 제외한 건수를 출력한다.

 

2. GROUP BY 절

GROUP BY 절은 데이터를 소그룹화 하여 항목별 통계 정보를 얻을 때 사용한다.

SELECT [DISTINCT] 칼럼명 
FROM 테이블명
[WHERE 조건식]
[GROUP BY 칼럼이나 표현식]
[HAVING 그룹조건식];

GROUP BY 절과 HAVING 절의 특징

  • GROUP BY 절을 통해 소그룹별 기준을 정한 후, SELECT 절에 집계 함수를 사용한다.
  • 집계 함수는 WHERE 절에 올 수 없다.
    (집계 함수를 사용할 수 있는 GROUP BY 보다 WHERE 절이 먼저 수행되기 때문이다. )
  • GROUP BY 절에는 SELECT 절과는 달리 ALIAS 를 사용할 수 없다.
  • GROUP BY 절에서 소그룹별로 집계된 데이터 중에서 HAVING 절에 쓰여진 제한 조건을 만족한 것만 출력한다.
  • 집계 함수의 통계 정보는 NULL 값을 가진 행을 제외하고 수행한다.
  • GROUP BY는 그룹화만 하는 것이지 정렬을 하지 않는다. ORDER BY 절이 데이터 정렬을 해준다.

3. HAVING 절

WHERE 절의 조건에 맞춰 걸러진 행들만 GROUP BY 의 대상이 된다. (그래서 WHERE 절에는 집계함수 사용이 불가하다.)
GROUP BY가 그룹화를 할 때 HAVING 절에서'조건'을 줄 수 있다.

SELECT  POSITION 포지션, ROUND(AVG(HEIGHT), 2) 평균키
FROM PLAYER
GROUP BY POSITION
HAVING AVG(HEIGHT) >= 180;

4개의 포지션 중에 평균키가 180 이 넘는 데이터를 출력한다.

GROUP BY 절과 HAVING 절의 순서를 바꿔도 에러가 없고 결과물도 동일하다. 하지만 GROUP BY 절 뒤에 HAVING 절을 쓰는 것을 권고한다.

가능한 WHERE 절에서 데이터를 많이 필터링 해둬서 GROUP BY의 계산 대상을 줄이는 것이 효율적인 자원 활용 측면에서 바람직하다.

 

4. CASE 표현을 활용한 월별 데이터 집계

IF-THEN-ELSE-END

IF    SAL > 2000
    THEN REVISED_SALARY = SAL
    ELSE REVIED_SALARY = 2000
END-IF

IF-THEN-ELSE

CASE
    SIMPLE_CASE_EXPRESSION 조건
    ELSE 표현절
END

 

5. NULL 관련 함수 (중요)

 

NULL 값의 특징

  • 아직 정의 되지 않은 값이다.
  • 0 또는 공백과는 다르다. ( 0은 숫자이고, 공백은 문자이다.)
  • 연산에 NULL이 포함되면 결과는 NULL이다.

NVL(exp1, exp2) 함수 NVL/ISNULL

  • 결과값을 "NULL이 아닌 다른 값"으로 얻고자 할 때 NVL/ISNULL 함수를 쓴다.
  • NVL(exp1, exp2)
  • exp1 이 NULL이라면 exp2 를 출력한다.
  • exp2는 대체값인 것이다.

NULLIF(exp1, exp2)

  • 특정 값을 null로 대체하는 경우에 주로 사용한다.
  • exp1 과 exp2가 같으면 NULL을 리턴한다. 다르면 exp1을 리턴한다.

COALESCE(exp1, exp2, ...)

  • 인수 중에서 NULL이 아닌 최초의 인수를 리턴한다.
  • 모든 인수가 NULL이라면 NULL을 리턴한다.
  • 인수의 개수가 무한하다.
728x90

'프로그래밍 > SQLD' 카테고리의 다른 글

SQL 기본 7 : ORDER BY  (0) 2020.05.28
SQL 기본 5 : 함수  (0) 2020.05.27
SQL 기본 4 : WHERE 절  (0) 2020.05.27
SQL 기본 3 : TCL  (0) 2020.05.27
SQL 기본 2 : DML  (0) 2020.05.27

제 6절. 함수

1. 내장함수 (Built-In function) 개요

함수를 크게 분류하면 벤더에서 제공하는 내장함수와 사용자가 정의하는 함수가 있다.
입력 값이 단일행 값이 입력되는 단일행 함수와 여러 행의 값이 입력되는 다중행 함수가 있다.

함수는 입력되는 값이 많아도 출력되는 값은 1개다.

함수이름 (칼럼이나 표현식 [, 인수1, 인수2, ...])

단일행 함수의 종류

  • 문자형 함수
  • 숫자형 함수
  • 날짜형 함수 : DATE 타입 값을 연산한다.
  • 변환형 함수
  • NULL 처리 함수

단일행 함수의 특징

  • SELECT, WHERE, ORDER BY 절에 사용 가능하다.
  • 여러 인자를 입력해도 하나의 결과만 리턴한다.
  • 함수의 인자로 함수를 가질 수 있다.

2. 문자형 함수

문자 데이터를 매개 변수로 받아서 문자나 숫자 값의 결과를 돌려준다.

문자형함수 함수 설명
LOWER('SQL Expert') 'sql expert'
UPPER('SQL Expert') 'SQL EXPERT'
ASCII('A') 65
CHAR(65) 'A'
CONCAT('RDBMS', ' SQL') 'RDBMS SQL'
SUBSTR('HELLO', 3, 2) 'LL'
LEN('HELLO') 5
LTRIM('xxxYYZZ', 'x') 'YYZZ'

DUAL 테이블

ORACLE의 DUMMY 테이블이다.
사용자 SYS가 소유하며 모든 사용자가 액세스 가능한 테이블이다.
DUMMY라는 문자열 유형의 칼럼에 'X'라는 값이 들어있는 행을 1건 포함한다.
반면 Sybase나 SQL Server에는 SELECT 절만으로도 SQL문장이 수행되므로 더미 테이블이 필요없다.

3. 숫자형 함수

숫자 데이터를 입력받아 처리하고 숫자를 리턴하는 함수다.

숫자형함수 함수 설명
ABS(-15) 15 절대값을 리턴한다.
SIGN(-20) -1
SIGN(0) 0
SIGN(20) 1
MOD(7, 3) 1
CEIL(38.123) 39
CEILING(-38.123) -38
FLOOR(38.123) 38
ROUND(38.523, 2) 38.52
ROUND(38.523, 0) 38
TRUNC(38.523, 1) 38.5
TRUNC(38.523) 38

4. 날짜형 함수

날짜형 함수 함수 설명
SYSDATE 현재 날짜와 시각을 출력
EXTRACT('YEAR' 'MONTH'
TO_NUMBER(TO_CAHR(D, 'YYYY') 날짜에서 연도만 출력하여 숫자로 변환

5. 변환형 함수

  • 명시적 데이터 유형 변환 : 데이터 변환형 함수 이용

  • 암시적 데이터 유형 변환 : 데이터베이스가 자동으로 데이터유형을 변환하여 계산

  • TO_NUMBER(문자열)

  • TO_CHAR(숫자 | 날짜 [, FORMAT])

  • TO_DATE(문자열 [, FORMAT])

728x90

'프로그래밍 > SQLD' 카테고리의 다른 글

SQL 기본 7 : ORDER BY  (0) 2020.05.28
SQL 기본 6 : GROUP BY, HAVING  (0) 2020.05.27
SQL 기본 4 : WHERE 절  (0) 2020.05.27
SQL 기본 3 : TCL  (0) 2020.05.27
SQL 기본 2 : DML  (0) 2020.05.27

제 5절. WHERE절

1. WHERE 조건절 개요

WHERE 절에는 2개 이상의 테이블에 대한 JOIN 조건을 기술하거나, 결과를 제한하기 위한 조건을 기술한다.

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

2. 연산자의 종류

  • 비교연산자 : = (같다) <>, ^=, != (같지 않다), >, >=, <, <=

  • SQL 연산자 : BETWEEN A AND B, IN(list), IS NULL, LIKE '비교문자열'

  • 논리 연산자 : AND, OR, NOT

  • 부정 비교 연산자 : NOT 칼럼명 = (와 같지 않다), NOT 칼럼명 > (보다 크지 않다)

연산자의 우선순위

  1. 괄호 ()
  2. 부정 연산자 (not)
  3. 비교 연산자 ( <, >, BETWEEN, IN (list)
  4. 논리 연산자 AND OR

3. 비교 연산자

비교 연산자 오른쪽에 문자열을 사용할 경우, 따옴표로 묶어서 처리해야 한다.

SELECT PLAYER_NAME 선수이름
FROM PLAYER
WHERE TEAM_ID = 'K02'

WHERE TEAM_ID = K02 와 같이 쓰면 에러가 난다.
CHAR, VARCHAR 데이터유형일 때 주의해야 한다.

문자 유형마다 '비교'연산이 다르다.

기본적으로 서로 다른 문자가 나올 때 까지 비교한다.

  • CHAR 끼리 비교 : 길이가 다르면 짧은 쪽에 공백을 추가하여 길이를 같게 한 후 비교.
  • 한 쪽이 VARCAHR 인 경우 비교 : 길이가 다르다면, 길이가 긴 쪽을 크다고 판단. 길이가 같고 다른 것이 없다면 같다고 판단.
  • 문자를 상수와 비교 : 상수 쪽을 변수 쪽의 타입으로 바꾸고 비교

4. SQL 연산자

예약어로 된 연산자로서 모든 데이터 타입에 대한 연산이 가능하다.

  • BETWEEN a AND b : a와 b 를 포함하는 범위인지 비교
  • IN (list) : (list) 에 하나라도 속해 있다면 참이다.
  • LIKE '비교문자열' : %와 _을 사용한 와일드카드로 비교문자열을 만든다
  • IS NULL : NULL 값인지 비교한다. NULL 값과 비교하면 FALSE를 리턴한다.
NULL 값의 비교
  • NULL 값은 비교 할 수 없으므로 비교 연산자를 쓰면 FALSE를 리턴한다.
  • 수치 연산자와 연산해도 NULL 값을 리턴한다.
  • NULL 값의 비교연산은 반드시 IS NULL, IS NOT NULL 문구로 연산한다.
와일드 카드의 종류
  • % : 0개 이상의 어떤 문자
  • _ : 1개인 단일 문자
728x90

'프로그래밍 > SQLD' 카테고리의 다른 글

SQL 기본 6 : GROUP BY, HAVING  (0) 2020.05.27
SQL 기본 5 : 함수  (0) 2020.05.27
SQL 기본 3 : TCL  (0) 2020.05.27
SQL 기본 2 : DML  (0) 2020.05.27
SQL 기본 1 : RDB 개요, DDL  (0) 2020.05.27

+ Recent posts