case when 함수

SELECT CASE WHEN 조건1 THEN 결과값1

                  WHEN 조건2 THEN 결과값2

                  ELSE 결과값3

                  END

FROM 테이블명

함수들 정리

함수 설명
sum
count 행 개수
min 최소값
max 최대값
avg 평균
truncate( , n ) 소수점 n자리까지 표시
round( , n ) 소수점 n 자리 지정 반올림
ceil 올림
floor 내림
abs 절대값
sign 양수는 1, 음수는 -1, 0은 0
length 문자열 길이
trim 앞뒤 공백 제거
upper 모두 대문자로
lower 모두 소문자로
left( , n) 왼쪽 n번째까지
right( , n) 오른쪽 n번째까지
replace 대체
lpad, rpad 특정 글자 반복
substring 문자열 자르기
concat 문자열 붙이기
concat_ws 문자열 사이에 값 넣기
curdate 현재 날짜 반환
curtime 현재 시각 반환
now 현재 날짜와 시각 반환
year 연도 반환
month 월 반환
day 일 반환
last_day 해당 월의 마지막 일 반환
weekday 요일 반환 월~일=0~6으로
dayname 요일 이름 반환
adddate 시간/날짜 덧셈
subdate 시간/날짜 뺄셈
datediff 두 시간/날짜 일 차이
timediff  두 시간/날짜 시간 차이
   

 

 

오름차순 데이터 조회

SELECT *

FROM 테이블명

ORDER BY 컬럼명 (ASC)

 

내림차순 데이터 조회

SELECT *

FROM 테이블명

ORDER BY 컬럼명 DESC

1. 비교연산자

비교연산자 기능
= 같다
!=, <> 다르다
< 보다 작다
<= 같거나 작다
> 크다
>= 같거나 크다
between 두 값 사이에 있다
is null null이다

 

2. 문법

숫자 데이터 필터링

SELECT *

FROM 테이블명

WHERE 컬럼명= 숫자

 

문자 데이터 필터링

SELECT *

FROM 테이블명

WHERE 비교컬럼명= ‘문자’

 

다조건 교집합 필터링

SELECT *

FROM 테이블명

WHERE 조건1 AND 조건2

 

다조건 합집합 필터링

SELECT *

FROM 테이블명

WHERE 조건1 OR 조건2

 

다조건 하나 이상 만족 데이터 필터링

SELECT *

FROM 테이블명

WHERE 비교컬럼명(NOT) IN (조건1, 조건2)

 

정규화 패턴 데이터 필터링

정규화 패턴 설명
'a%' a로 시작
'%z' z로 끝난다
'%def%' def 포함
'_b%' 2번 째 글자가 b
'a%z' a로 시작 z로 끝난다
'a_%_%' a로 시작하고 3글자 이상
SELECT *

FROM 테이블명

WHERE 컬럼명 LIKE 정규화 패턴

 

 

 

 

테이블의 모든 칼럼 조회

SELECT *

FROM 테이블명

 

테이블의 특정 칼럼 조회

SELECT 컬럼명1, 컬럼명2, 컬럼명3

FROM 테이블명

 

중복 제거된 컬럼 조회

SELECT DISTICNT 컬럼명1, 컬럼명2

FROM 테이블명

 

컬럼에 새로운 컬럼명으로 이름 바꿔 조회

SELECT 컬럼명 (AS) 새로운 컬럼명

FROM 테이블명

 

행 개수 제한해서 조회

SELECT 컬럼명

FROM 테이블명

LIMIT N

 

 

 

 

SQL이란?

Structured Query Language, 구조화 질의어

RDBMS의 데이터 관리를 위해 설계된 특수 목적의 프로그래밍 언어

RDBMS 데이터의 검색과 관리, 스키마 생성과 수정, 객체 접근 조정 등의 기능 수행

 

데이터베이스 용어

스키마(schema)

:엑셀의 문서와 같은 개념

테이블(table)

:엑셀의 시트와 같은 개념

로우(row)

:엑셀의 행과 같은 개념

칼럼(column)

:엑셀의 열과 같은 개념

스프링 부트 data jpa를 활용해 게시물 단건 조회 API를 만들던 중 발생한 에러다.

에러 메세지를 살펴보니 무한 재귀 문제임을 알 수 있었다.

양방향 다대다 관계를 일대다 다대일로 찢어서 연관관계 매핑을 한 칼럼이 있었는데 해당 객체를 response로 반환할 시

서로를 참조하며 무한 재귀 함수가 실행되는 문제였다.

 

@ManyToOne 칼럼에 @JsonIgnore 애노테이션을 추가해서 해결했다.

예시 코드는 아래와 같다.

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "board_idx")
    private Board board;

   
    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "stack_idx")
    private TechStack techStack;

 

참고사이트 

https://thalals.tistory.com/227

https://cupeanimus.tistory.com/57

 

계속 널값이 뜬다고 오류가 뜨길래 코드에 문제가 있어서 정보를 못 읽어오는 줄 알고 삽질한 오류이다.

이후에 다시 생각해보니 객체 생성관련 문제인 것 같았다.

 

이전에 jdbc를 사용할 때와 달리 jpa는 객체 단위로 데이터를 처리한다.

해당 DTO 클래스에서 다른 객체의 서비스단,레포지토리단 코드를 활용해 다른 객체의 정보를 가져오는 코드들이 있었다.

생각해보니 다른 객체는 생성이 안된 상태이므로 객체 자체가 null이라 널포인터 에러가 뜨는 것 같았다. 그래서 DTO 클래스에 직접 해당 객체들을 주입해서 디버깅을 하려고 했는데 그러면 더이상 DTO가 아니라 서비스 클래스가 되는 문제가 생겼다.

어떻게 하면 좋을까 생각하다가 문제가 되는 다른 서비스단이나 레포지토리를 사용하는 코드들을 다 서비스단으로 옮겼다.

그리고 서비스에서 해당 코드를 통해 받은 값들을 파라미터에 넣어 DTO 생성자를 통해 값을 넣어줬다.

이 방식을 통해 에러를 디버깅할 수 있었다.

 

관련된 내가 작성한 코드는 아래와 같다.

DTO

package backend.whereIsMyTeam.board.dto;

import backend.whereIsMyTeam.board.domain.*;
import backend.whereIsMyTeam.board.repository.CommentRepository;
import backend.whereIsMyTeam.board.repository.PostLikeCustomRepository;
import backend.whereIsMyTeam.board.repository.PostLikeCustomRepositoryImpl;
import backend.whereIsMyTeam.board.service.PostLikeService;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class GetBoardResponseDto {

    private Long boardIdx;
    private String category; //프로젝트, 스터디, 대회 중 1
   // @JsonFormat
    List<TechStackBoard> stackList= new ArrayList<>();; //모집하는 스택 기술들 리스트
    private String title;
    private postDetailDto detail;
    private String postText;
    private List<BoardStatus> boardStatus=new ArrayList<>(); //게시물 상태(삭제,임시저장,모집중,모집완료)
    private postUserDto writer; //게시물 작성자 정보
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul")
    private LocalDateTime createdAt;
    private Long watch;
    private Long heart; //찜 총 수
    private String isHeart; //해당 유저가 찜 눌렀는지 안눌렀는지
    private List<postCommentDto> commentList= new ArrayList<>();; //댓글 부분 작성자 인덱스와 comment 인덱스도


    public GetBoardResponseDto(Board post,Long heart, String isHeart,List<postCommentDto> c){
        this.boardIdx=post.getBoardIdx();
        this.category=post.getCategory().getCategoryName();
        this.title=post.getTitle();
        this.detail=new postDetailDto(post);
        this.postText=post.getContent();
        this.boardStatus=post.getBoardStatuses();
        this.writer= new postUserDto(post.getWriter()); //userImg 구현중
        this.createdAt=post.getCreateAt();
        this.watch=post.getCnt();
        this.heart=heart;
        this.isHeart=isHeart;
        this.commentList=c;
    }

    public GetBoardResponseDto(Board post,Long heart,List<postCommentDto> c){
        this.boardIdx=post.getBoardIdx();
        this.category=post.getCategory().getCategoryName();
        this.title=post.getTitle();
        this.detail=new postDetailDto(post);
        this.postText=post.getContent();
        this.boardStatus=post.getBoardStatuses();
        this.writer= new postUserDto(post.getWriter()); //userImg 구현중
        this.createdAt=post.getCreateAt();
        this.watch=post.getCnt();
        this.heart=heart;
        this.isHeart="not exist";
        this.commentList=c;
    }


}

 

/**
     * 게시물 단건 조회
     * @return GetBoardResponseDto
     */
    @Transactional
    public GetBoardResponseDto boardDetail(Long boardIdx,Long userIdx) {
        Optional<Board> optional = boardRepository.findByBoardIdx(boardIdx);
        if(optional.isPresent()) {
            Board board = optional.get();
            //방문자 수 1 증가
            board.setHitCnt(board.getHitCnt() + 1);
            boardRepository.save(board);
            //조회 로직 회원,비회원 구분 해야함
            if(userIdx!=0) { //회원
                long heart=postLikeRepository.findPostLikeNum(boardIdx);
                String isHeart=postLikeService.checkPushedLikeString(userIdx,boardIdx);
                List<postCommentDto> commentList=postCommentDto.toDtoList(commentRepository.findAllWithUserAndParentByBoardIdxOrderByParentIdxAscNullsFirstCommentIdxAsc(boardIdx));
                return new GetBoardResponseDto(boardRepository.findByBoardIdx(boardIdx).orElseThrow(BoardNotExistException::new),heart,isHeart,commentList);
            }
            else{ //비회원
                long heart=postLikeRepository.findPostLikeNum(boardIdx);
                List<postCommentDto> commentList=postCommentDto.toDtoList(commentRepository.findAllWithUserAndParentByBoardIdxOrderByParentIdxAscNullsFirstCommentIdxAsc(boardIdx));

                return new GetBoardResponseDto(boardRepository.findByBoardIdx(boardIdx).orElseThrow(BoardNotExistException::new),heart,commentList);
            }

        }
        else {
            throw new NullPointerException();
        }
    }

내일 비대면 알고리즘 대회에 스터디를 같이 하고 있는 동기들과 참가한다.

뒤에 일정이 있어 대회 시간 절반 정도만 참여를 하기 때문에 입상을 노리고 있진 않지만 이 기회에 한 번 정리해보면 좋을 것 같아 포스팅을 하게 됐다.

 

다양한 언어로 코테를 풀면서 느낀게 문제를 읽고 어떤 걸 이용해 어떻게 풀지 로직만 잘 잡혀 있다면 언어는 그 다음 문제라는 것이다. 

 

알고리즘 유형 별로 문제가 어떤 식으로 많이 나오는 지 정리해봤다.

유형 별로 이해대신 외우는 용도가 아니라 저런 문제에 왜 저 알고리즘을 쓰는지 접근하는 방식으로 활용하면 좋을 것 같다.

항상 백프로 일치하진않고 경향성의 문제이며 아직 배워가는 입장이라 잘못된 정보가 있다면 댓글에 적어주세요!

 

완전탐색

입력 값이 100이하로 작은 문제

 

백트래킹

입력 값이 100이하로 작은 문제

순열, 중복 순열, 조합, 중복 조합

 

BFS

출발 값 존재

도착 값 까지 최소/최단 시간/거리/횟수

무가중 그래프

 

DFS

사이클 찾기 문제

한 가지 정점에서 연결된 모든 정점 탐색

그래프 완전 탐색

무가증 그래프

최단 거리는 절대 x

 

DFS+다이나믹 프로그래밍

갈 수 있는 방향이 목표지점까지로만 갈 수 있도록 제한 

사이클 x

경로 수 구하기

유향 그래프

 

BFS+다이나믹 프로그래밍

가중 그래프

메모이제이션을 통해 재방문이 가능한 경우를 정의할 때

 

이분 탐색

최소/최대 값 구하는 문제

결과 값들이 정렬 되어 있는 경우

X라는 조건 만족하는 최대/최소값

 

해시 맵

배열 내 빈도수 구하기

배열 내 중복된 요소 구하기

 

크루스칼

최소 신장 트리(가장 저렴한 방법으로 모두 연결 등)

 

프림 알고리즘

최소 신장 트리(가장 저렴한 방법으로 모두 연결 등)

 

다익스트라

최단 경로 (특정 노드->모든 노드까지)

가중 그래프

간선마다 가중치가 다른지 파악, 같다면 BFS 사용 가능

 

위상 정렬

주어진 수 정렬 할 때 순서가 정해져 있는 요소가 존재

 

우선 순위 큐/힙

실시간으로 정렬이 이루어져야하는 경우

N번째 요소 구하기

중앙 값 구하기

 

그리디

가장 많은 선택을 할 수 있는, 가장 작은/큰 등의 키워드가 있는 문제

 

플로이드-와샬

모든 노드->모든 노드까지 가는데의 최소 비용

 

 

참고 사이트

https://hh-bigdata-career.tistory.com/24

https://skytitan.tistory.com/217

https://mangkyu.tistory.com/181

 

 

 

토비의 스프링 3.1 책을 읽으며 일부분을 정리한 내용입니다. 
개념 이해를 위한 내용들 중 일부분을 정리했으므로 이해를 돕기위한 예시 코드들 및 자세한 전체적인 내용은 책을 통해 확인하시길 바랍니다.
포스팅 내용이 저작권의 문제가 발생할 경우 게시물은 바로 삭제/비공개 처리됩니다.

템플릿/콜백 패턴

전략 패턴의 기본 구조에 익명 내부 클래스를 활용한 방식

템플릿: 전략패턴의 컨텍스트, 고정된 흐름의 코드 재사용

콜백: 익명 내부 클래스로 만들어지는 오브젝트, 템플릿 안에서 호출되는 것을 목적으로 만들어진다.

 

템플릿

어떤 목적을 위해 미리 만들어둔 모양이 있는 틀

콜백

실행을 목적으로 다른 오브젝트의 메소드에 전달되는 오브젝트

파라미터로 전달되지만 값 참조용이 아니라 메소드를 실행시키기 위해 사용

왜냐, 자바에선 메소드 자체를 파리미터로 전달하지 못하기 때문에 메소드가 담긴 오브젝트를 전달

 

템플릿/콜백의 특징

일반적인 DI 방식: 템플릿에 인스턴스 변수 만든  후 수정자 메소드로 의존 오브젝트 받아서 사용

템플릿/콜백 DI 방식: 매번 메소드 단위로 사용할 오브젝트를 새롭게 전달 받는다.

-보통 단일 메소드 인터페이스 사용

-콜백: 단일 메소드 인터페이스를 구현한 익명 내부 클래스로 만들어진다.

-전략 패턴, DI의 장점, 익명 내부 클래스 사용 전략의 결합

 

템플릿/콜백 작업 흐름

책 p.242

클라이언트 역할: 템플릿 안에서 실행될 로직 담은 콜백 오브젝트 만들기, 콜백이 참조할 정보 제공, 만들어진 콜백은 클라이언트가 템플릿의 메소드를 호출할 때 파라미터로 전달(메소드 레벨  DI)

템플릿 역할: 흐름을 따라 작업을 진행하다가 내부에서 생성한 참조정보를 가지고 콜백 오브젝트의 메소드 호출, 콜백이 돌려준 정보를 사용해서 작업을 마저 수행, 경우에 따라 결과 클라이언트에게 반환

 

콜백 역할: 클라이언트 메소드에 있는 정보와 템플릿이 제공한 참조정보를 이용해서 작업을 수행, 그 결과를 템플릿에 반환

 

템플릿/콜백 방식의 단점

DAO메소드에서 매번 익명 내부 클래스를 이용하는데 익명 내부 클래스는 상대적으로 작성/해석에 용이하지 않다.

->복잡한 익명 내부 클래스의 사용을 최소화할 수 없을까?

 

콜백의 분리와 재활용, 템플릿과의 결합

재사용이 가능한 코드를 분리를 해내 익명 내부 클래스 코드를 간결하게 만들면 된다.

재사용 가능한 콜백을 담고 있는 메서드라면 DAO가 공유할 수 있는 템플릿 클래스 안으로 옮겨도 된다.

책 p.247 그림
public class JdbcContext {
...
	public void executeSql(final String query) throws SQLException{
		workWithStatementStrategy(
				new StatementStrategy() {
					public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
						return c.prepareStatement(query);
					}
				}
		);
	}
public void deleteAll() throws SQLException {
	this.jdbcContext.executeSql("delete from users");
}

하나의 목적을 위해 긴밀한 관계를 형성하고 있는 코드들은 응집력이 강하기 때문에 위  JdbcContext 예시처럼 한 곳에 작성하는 게 좋다.

 

템플릿/콜백의 응용법

고정된 로직이 자주 반복되는 코드를 가지고 있다면 이를 분리할 방법을 생각해보자.

중복된 코드는 먼저 메소드로 분리하는 시도

그중 일부 작업이 필요에 따라 바뀐다면 인터페이스를 사이에 두고 분리해서 전략 패턴 적용/DI 의존관계 관리

바뀌는 부분이 한 어플리케이션 안에서 동시에 여러 종류가 만들어질 수 있다면 템플릿/콜백 패턴 적용 고려

 

템플릿과 콜백의 경계를 정하고 템플릿이 콜백에게, 콜백이 템플릿에게 전달하는 정보가 무엇인지 판단하는 게 가장 중요

 

제네릭스를 이용한 콜백 인터페이스

제네릭스를 이용하면 다양한 오브젝트 타입을 지원하는 인터페이스나 메소드 정의 가능

제네릭 타입 파라미터  T

 

 

토비의 스프링 3.1 책을 읽으며 일부분을 정리한 내용입니다. 
개념 이해를 위한 내용들 중 일부분을 정리했으므로 이해를 돕기위한 예시 코드들 및 자세한 전체적인 내용은 책을 통해 확인하시길 바랍니다.
포스팅 내용이 저작권의 문제가 발생할 경우 게시물은 바로 삭제/비공개 처리됩니다.

JDBC try/catch/finally 코드의 문제점

-복잡한 블록이 2중으로 중첩까지 되어 있어 조금이라도 코드에 실수가 있을 시 리소스가 부족한 심각한 문제가 발생할 가능성이  높다.

-풀이 가득차버려(리소스가 부족하여) 잘못된 부분을 찾아나가는 과정에서도 코드의 양의 광범위해 찾기가 쉽지않다.

 

이러한 문제점들 해결하려면?

많은 곳에서 중복되지만 변하지 않는 코드와 로직에 따라 자꾸 확장되고 자주 변하는 코드를 분리해내는 작업 필요

 

분리와 재사용을 위한 디자인 패턴 적용

-메소드 추출 리팩토링

변하는 부분을 메소드로 추출

public void deleteAll() throws SQLException {
		Connection c = null;
		PreparedStatement ps = null;
		
		try {
			c = dataSource.getConnection();
			ps = makeStatement(c);
			ps.execute();
		} catch (Exception e) {
			throw e;
		}finally {
			if(ps != null) { try { ps.close(); } catch (SQLException e) {} }
			if (c != null) { try { c.close(); } catch (SQLException e) {} }
		}
	}
    
	private PreparedStatement makeStatement(Connection c) throws SQLException {
		PreparedStatement ps;
		ps = c.prepareStatement("delete from users");
		return ps;
	}

문제점

보통 분리시킨 메소드를 다른 곳에서 재사용하는데 위와 같은 방식은 재사용이 불가능하다.

변하지 않는 부분을 메소드로 추출하는 것은 try/catch/finally 구조상 쉽지않은 상황

 

-템플릿 메소드 패턴의 적용

템플릿 메소드 패턴

:상속을 통해 기능을 확장해서 사용

변하지 않는 부분은 슈퍼클래스에 변하는 부분은 추상 메소드로 정의 후 서브클래스에서 오버라이드하여 정의 후 사용

 

변하지 않는  try/catch/finally 블록 슈퍼클래스와 상속을 통해 바꿀 수 있는 부분은(위의 예시 PreparedStatement 부분) 서브클래스로 분리

문제점

-다중 상속이 되지 않기 때문에 DAO 로직마다 상속을 통해 새로운 클래스를 만들어야 한다.

-확장구조가 이미 클래스를 설계 시점에서 고정된다.

 

-전략패턴의 적용

오브젝트를 아예 둘로 분리하고 클래스 레벨에서는 인퍼페이스를 통해서만 의존하도록 만드는 패턴

개방 폐쇄 원칙에 잘 부합하고 유연하면서 확장성이 좋다.

확장이 되는 부분이 변화되는 부분으로 별도의 클래스로 만들어 추상화된 인터페이스를 통해 위임

public interface StatementStrategy {
	PreparedStatement makePreparedStatement(Connection c) throws SQLException;
}
public class DeleteAllStatement implements StatementStrategy {
	public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
		PreparedStatement ps = c.prepareStatement("delete from users");
		return ps;
	}
}
	public void deleteAll() throws SQLException {
		Connection c = null;
		PreparedStatement ps = null;
		
		try {
			c = dataSource.getConnection();
			StatementStrategy strategy = new DeleteAllStatement();
			ps = strategy.makePreparedStatement(c);
			ps.execute();
		} catch (Exception e) {
			throw e;
		}finally {
			if(ps != null) { try { ps.close(); } catch (SQLException e) {} }
			if (c != null) { try { c.close(); } catch (SQLException e) {} }
		}
	}

문제점

StatementStrategy strategy = new DeleteAllStatement(); 코드를 보면

인터페이스뿐만 아니라 특정 클래스까지 알고있으므로 부적합

 

-DI 적용을 위한 클라이언트/컨텍스트 분리

어떤 전략을 사용할지 클라이언트에게 결정권을 준다.

클라이언트가 전략 하나를 선택하고 오브젝트로 만들어서 컨텍스트에 전달

컨텍스트는 전달받은 전략 구현 클래스의 오브젝트 사용

 

클라이언트 역할을 할  deleteAll 메소드 예시 코드

public void deleteAll() throws SQLException {
		StatementStrategy st = new DeleteAllStatement();
		jdbcContextWithStatementStrategy(st);
}

DI의 중요한 개념은 제3자의 도움을 통해 두 오즈젝트 사이의 유연한 관계가 설정되는 것!

토비의 스프링 3.1 책을 읽으며 일부분을 정리한 내용입니다. 
개념 이해를 위한 내용들 중 일부분을 정리했으므로 이해를 돕기위한 예시 코드들 및 자세한 전체적인 내용은 책을 통해 확인하시길 바랍니다.
포스팅 내용이 저작권의 문제가 발생할 경우 게시물은 바로 삭제/비공개 처리됩니다.

템플릿 

일정한 패턴으로 유지되는 특성을 가진 부분을 자유롭게 변경되는 성질을 가진 부분으로부터 독립시켜서 효과적으로 활용할 수 있도록 하는 방법

 

예외처리 기능을 갖춘  DAO

중간에 어떤 이유로든 예외가 발생했을 경우 사요하던 리소스를 무조건 반환하여 리소스 부족 문제를 막아야한다.

JDBC 코드에서는 try/catch/finally 구문을 활용해 리소스를 반환하도록 도와준다.

 

try/catch/finally 구문

try 구문

예외가 발생할 가능성이 있는 코드를 묶어준다.

catch 구문

예외가 발생했을 때 부가적인 작업을 해주도록 한다.

finally 구문

try 구문에서의 예외 발생 유무와 상관없이 항상 실행되는 구문이다. 

 

책에 나온 try/catch/finally 구문 사용하여 users 테이블을 다 지우는 예시 코드

public void deleteAll() throws SQLException {
		Connection c = null;
		PreparedStatement ps = null;
		try {
			c = dataSource.getConnection();
			ps = c.prepareStatement("delete from users");
			ps.execute();
		} catch (Exception e) {
			throw e;
		}finally {
			if(ps != null) {
				try {
					ps.close();
				}catch (SQLException e) {
				}
			}
			if (c != null) {
				try {
					c.close();
				} catch (SQLException e) {
				}
			}
		}
	}

close() 메소드 호출 시 오류 발생 시점에 따라 close() 함수 사용여부가 달라지므로 이를 주의해야한다.

 

 

 

토비의 스프링 3.1 책을 읽으며 일부분을 정리한 내용입니다. 
개념 이해를 위한 내용들 중 일부분을 정리했으므로 이해를 돕기위한 예시 코드들 및 자세한 전체적인 내용은 책을 통해 확인하시길 바랍니다.
포스팅 내용이 저작권의 문제가 발생할 경우 게시물은 바로 삭제/비공개 처리됩니다.

학습 테스트(learning test)

자신이 만들지 않은 프레임워크, 제공받은 라이브러리들에 대한 테스트

테스트를 만들려면 해당 기술, 기능에 대한 이해가 바탕이 돼야하므로 내가 제대로 이해하고 있는지 검증 가능

테스트 대상보다는 테스트 코드 자체에 관심을 가지고 만들어야하며 그 과정에서 사용법도 익힐 수 있다.

학습 테스트의 장점 4가지

1. 다양한 조건에 따른 기능을 손쉽게 확인해볼 수 있다.

자동화 : 눈으로 콘솔을 읽을 필요가 없이 성공/실패 여부를 알려줌

자동화된 테스트 코드 활용하기때문에 다양한 조건에 따라 기능이 어떻게 동작하는지 빠르게 확인 가능

2. 학습 테스트 코드를 개발 중에 참고할 수 있다.

테스트로 새로운 기술의 여러 기능들에 대한 사용 코드들을 작성해두면 실제 개발 착수시 샘플 코드로 활용 가능

3. 프레임워크나 제품을 업그레이드할 때 호환성 검증에 용이

적용을 하지 않고도 기존에 사용하던 API 기능에 문제가 없다는 사실을 미리 확인해볼 수 있는 방법

새로운 버전의 프레임워크나 제품을 학습 테스트에만 먼저 적용해봄

업그레이드시 버그가 발생하는지 미리 확인 가능해짐

4. 테스트 작성 좋은 훈련

 

버그 테스트(bug test)

코드에 오류가 있을 때 그 오류를 가장 잘 드러낼 수 잇는 테스트

일단 실패하도록 만든 후 코드를 수정하여 테스트가 성공하면 디버깅 완료

버그 테스트의 장점 3가지

1. 테스트의 완성도를 높여준다.

기존 테스트에서 미처 검증하지 못했던 부분 보완

2. 버그의 내용을 명확하게 분석하게 해준다.

테스트를 만들기 위해 분석하는 과정에서 버그를 좀 더 효과적으로 분석

동등 분할과 경계값 분석 적용해볼 수도

동등분할: 같은 결과 내는 각 범위의 대표 값으로 테스트 해보는 방법

경계값 분석: 동등분할 범위 경계 근처의 값들을 테스트하는 방법

3. 기술적인 문제를 해결하는 데 도움이 된다.

원인이 무엇인지 정확하게 파악하기 힘들 때 동일한 문제가 발생하는 가장 단순한 코드와

그에 대한 버그 테스트를 만들어 볼수도

외부의 도움을 요청할 때도 편함

 

+ Recent posts