| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- Entity
- 개발자취업부트캠프
- 국비지원교육
- Spring
- 패스트캠퍼스
- array
- group study
- tomcat
- Algorism study
- 클래스 상속
- 게시판 만들기
- MegabyteSchool
- github
- Sts
- MVC 패턴
- 게시판 리뷰 만들기
- 클래스 class
- View
- 메가바이트스쿨
- AWS
- crud
- Interface
- GIT
- Java
- MVC
- #javaStudy
- 내일배움카드
- side project
- #패스트캠퍼스 #국비지원교육 #메가바이트스쿨 #MegabyteSchool #개발자취업부트캠프 #내일배움카드
- spring boot
- Today
- Total
tuter77
2023.01.11 TIL 본문
<목차>
<공부계획표>
13:00 ~ 14:00 그룹스터디
현재까지 진행한 내용 피드백
14:00 ~ 18:00 (3시간) 온라인강의 시청.
14:00 ~ 15:00 그룹스터디 추가적으로 더 진행하기(페이징처리 및 저장)
15:00 ~ 16:00 Java 강의 시청.
17:00 ~ 18:00 Java 강의 시청.
18:00 ~ 19:00 식사시간
19:00 ~ 22:00 Java 실시간 강의 시청.
19:00 ~ 20:00 Java 강의 시청.
20:00 ~ 21:00 Java 강의 시청.
21:00 ~ 22:00 Java 강의 시청.
22:00 ~ 23:00 블로그 작성 및 프로그래머스 문제 풀기.
<Java 실시간 강의>
● 예외처리
▷Exception
- 자바에서는 컴파일 에러와 런타임 에러가 발생한다.
- 컴파일 에러는 컴파일 시 발생하는 에러이며, 런타임 에러는 java 애플리케이션이 실행할 때 발생하는 에러이다.
- Exception은 프로그램 실행시 예상치 못한 일로 발생할 수 있는 에러를 의미하며, 비정상적인 상태이다.- 예시) 존재하지 않는 파일을 Open할 경우, 네트워크 접속에 장애가 날 경우, 클래스 로딩시 오류가 발생할 경우, 0으로 나눌경우
- java에서 의미적제약(semantic constraint)을 위반했을 때 위의 예처럼 JVM은 프로그램에게 Exception이라는 에러가 발생했다고 알린다.어떤 언어는 예외 프로그래밍시에 흔히 발생할 수 있는 일로 이러한 일이 발생했을 때 프로그래머가 원하는 방향으로 움직이도록 만드는 일을 예외처리라고 하고, 애플리케이션의 정상적인 흐름을 유지할 수 있도록 오류를 처리하는 강력한 매커니즘이다.
- 자바는 예외가 발생할 경우, JVM에서 예외를 던지고(Throw), 예외가 발생한 지점에서 프로그래머가 지정해 놓은 위치로 제어의 비지역이동이 발생한다. > 비지역이동(non-local jump)은 제어의 흐름을 주어진 무맥의 외부로 이동시키고, 미리 선언된 지점에서 이어서 수행된다.
-예외는 발생한 지점에서 던진다고 하고 제어가 이행된 위치에서 잡는다(catch)라고 한다.
예시)

▷Exception 처리 키워드
- try 예외가 발생할 것으로 예상되는 코드를 블럭으로 지정하는데 사용되며, try 블록 다음에는 catch 또는 finally가 와야한다.
- catch 예외를 처리하는데 사용된다.
- finally 예외 발생과 상관없이 프로그램의 필요한 코드를 무조건 실행하는데 사용된다.
- throw 예외를 발생시키는데 사용된다.
- throws 예외를 선언하는데 사용되며, 메서드를 호출한 곳으로 전가(전가된 곳에서 예외를 처리하거나 다시 throws할 수 있다.)하며, 메서드 선언시 함께 사용된다.
- 예외 처리 용도 : 예외 발생시 정상 종료/ 예외 내용 보고 / 무시하고 계속 실행 / 대안적인 결과값을 대입
▷ try-catch 문
- 예외가 발생할 것으로 예상되는 코드 블록을 try로 감싼다.
- catch 문에서는 발생할 것으로 예상되는 예외 클래스를 선언한다. Exception 클래스로 선언하기 보다는 throw될 것으로 예상되는 예외를 선언하는 것이 좋다. 여러 catch 블록을 선언할 수 있다.
- finally 블록은 항상 실행되는 코드 블럭이며, catch문에 잡히지 않는 예외가 발생하더라도 강제적으로 처리해야하는 코드를 기술한다.
- try 블록에서 예외가 걸리면 그 안의 다른 구문이 실행되지 않기때문에 예외와 상관없는 코드는 블록 밖에 두어야한다.
- JVM은 먼저 예외가 처리되었는지 여부를 확인하고, 처리되지 않으면 JVM은 예외에 대한 정보, StackTrace(스택 추적: 예외가 발생한 메서드의 계층구조)를 출력하고, 프로그램을 종료시킨다.
일반적으로 stack trace는 로깅처리를 통해 로그 파일에 기록되며, 모니터링 툴에서는 로그파일에 기록된 예외를 별도로 수집하여 확인할 수 있는 기능들을 제공한다.
이 로그들이 잘 쌓여있어야, 후에 data dog과 같은 클라우드 모니터링 툴로 그동안의 에러들을 분석해서 알 수 있다.
(비용이 비싸긴하다고 함.)
▷ throws 절
자신을 호출한 곳으로 예외를 처리하지 않고, 되돌릴때 사용하는 키워드이다.
예외를 처리할 다른 메서드로 throw한다.
▷ throw는 강제적으로 예외를 만들어서 던지는 것.
예를들어 비즈니스 적으로 조건을 불만족 하는경우 강제로 발생시키는 것이다.
예시) a메서드에서 세금계산한 값을 b메서드에 전달한 경우, 계산이 잘못된 경우 b메서드에서 계산을 잘못한 a메서드의 위치에 throw한다.
b는 throws로 기능이 선언되어있고, 그 안에 taxException 을 throw로 지정해서 발생할경우 a메서드에 throw한다.
(해당 예외가 발생할 것을 예측하고 있어야 가능)
- 런타임 시점이 아닌 컴파일 시점에 오류를 확인할 수 있다.
- throw하면 Exceoption객체를 만들어서 조건을 건다.
예시)
package ch12;
import java.io.*;
public class TestThrowChk {
public static void method() throws FileNotFoundException{
FileReader file = new FileReader("abc.txt");
BufferedReader fileInput = new BufferedReader(file);
throw new FileNotFoundException();
}
public static void main(String[] args){
try {
method();
}catch (FileNotFoundException e){
e.printStackTrace();
}
System.out.println("나머지 코드...");
}
}
존재하지 않는 파일을 filereader에 대입하고 해당 코드를 실행하면, 아래와 같은 결과창이 나온다.

미리 FileNotFoundaException(IOException의 하위클래스)을 예상해서 try catch문을 적용하면 위와 같은 결과창이 나오고, try catch문 없이 코드를 실행하면,

이 처럼 보고되지않은 예외라는 결과가 나온다. 내용을 보면, throw타입으로 선언해야한다고 한다.
▷Call Stack Mechanism
- 만약 예외가 발생한 메소드에서 처리를 하지 않으면, 메서드를 호출한 곳으로 throw된다.- main method에서 예외를 처리하지 않으면, 프로그램은 비정상적으로 종료된다.
예시)
▷Exception 클래스

예외처리가 가능한 Exceoption type class 들과 발생하면 복구할 수 없는 심각한 오류인 Error type 클래스 두가지가 있다.
이 계층에 의해서 만약 상위클래스에서 ructimeException을 throw 한다면, 상속받은 하위클래스에선 더 높은 Exception등의 예외클래스를 throw할 수 없다.
이외에도 클래스 명에 Exception을 붙여 사용자가 직접 예외 클래스를 정의할 수 있다.
예시)
public class ServerTimedOutException extends Throwable {
private int port;
public ServerTimedOutException(String message, int port) {
// Exception 클래스에 예외 메시지 전달을 위해 super를 이용하여 상위 생성자 호출
super(message);
this.port = port;
}
public int getPort() {
return port;
}
}
exception 클래스를 상속한 사용자 지정 예외클래스이다.
public class ExceptionUserDefined {
public void connect(String serverName) throws ServerTimedOutException {
boolean success;
int port = 80;
success = open(serverName, port);
if(!success) {
throw new ServerTimedOutException("연결할 수 없습니다", port);
}
}
public boolean open(String serverName, int port){
// method body
return false;
}
public void findServer(){
try {
connect("ProductServer");
} catch (ServerTimedOutException se) {
System.out.println("서버 접속시간 초과, 대채 서버 시도");
try {
connect("AlterProductServer");
} catch (ServerTimedOutException rse) {
System.out.println("Error : " + rse.getMessage() +
"포트에 연결 " + rse.getPort());
}
}
}
public static void main(String args[]){
ExceptionUserDefined e = new ExceptionUserDefined();
e.findServer();
}
}
findServer 메서드에서 서버에 연결하는 connect 메서드를 호출하려니 해당 메서드는 사용자가 지정한 예외클래스에 throws가 되어있는것을 볼 수 있다.
때문에 try-catch문으로 예외상황을 처리해준다.
main메서드에서 findServer를 실행 해보면 예외가 catch문에 해당이 되어 예외 출력문을 출력하고 그 안의 try-catch문으로 대체할 서버를 제공해 connect를 다시 시도한다.
(이는 중첩 try-catch가 가능하다는 것을 말해준다.)
결과는 서버 연결에 두번 다 실패한다.
- catch 블럭에서 전달 받은 예외 객체에서 자주 사용하는 메서드는 아래와 같다.
printStachTrace() 예외 발생 시점의 호출 스택(call stack)의 호출 흐름과 예외가 발생한 원인과 메시지를 콘솔에 출력한다.
getMessange() 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.
예외는 위에서 보았듯 두 가지 유형이 있다.
- Checked Exception
컴파일 타임에 체크되는 에외로 적절하게 처리되지 않은 예외의 수를 줄일 수 있도록 설계되었다.
RuntimeException과 Error를 제외한 예외들이 해당된다.(IOEXception, SQLException)
컴파일 단계에서 무조건 try-catch문으로 잡게끔 되어있다.
-UnChecked Exception
컴파일러가 체크하지 않는 예외로 런타임에만 확인할 수 있다.
RuntimeException 클래스와 그 하위클래스, Error클래스와 그 하위클래스의 예외들이 해당된다.
▷ 다중 catch 블럭
- 자바 7버전 부터지원되는 기능으로 아래와 같이 쓸 수 있다.
catch (a | b | c)
▷ 실습과제.
학생의 점수가 범위 내에 있는지를 판단하는 예외처리 클래스 과제이다.
package ch12.Ch12HomeworkSongYoungJin;
class PointException extends Throwable {
public PointException(String message) {
super(message);
}
}
public class ExceptionUserDefined {
public static void main(String args[]){
try {
calc(100);
} catch (PointException se) {
se.fillInStackTrace();
System.out.println(se.getMessage());
} finally {
System.out.println("Hello try~catch~finally!");
}
}
public static void calc(int point) throws PointException{
if(point>100 | point<0) {
throw new PointException("점수 오류입니다.");
}
else{
System.out.println("학생의 점수는 " + point + "점 입니다.");
}
}
}
먼저 Throwable클래스를 상속하는 PointException이라는 예외처리 클래스를 만들고 해당 클래스에서는 메세지를 반환하도록 했다.
그리고 과제 클래스(ExceptionUserDefined)맨 아래에 calc라는 메서드를 만들어 매개변수로 입력받는 점수가 예외상황인지를 구분하는 기능을 구현했다. 해당 메서드 내에서 예외상황일 경우 점수오류라는 메세지를 앞서만든 예외 클래스로 throws해준다.
main메서드 내에서 try-catch-finally라는 구문을 사용하여 calc메서드를 이용해 점수를 입력했고, 점수가 범위를 벗어난경우 catch문에 잡혀 예외 클래스의 변수 se를 생성해 메세지를 가져온다.
finally는 예외와 상관없이 괄호안의 내용을 출력한다.
<Group Study>
● html 파일 완성 및 read, save 기능 구현.
▷ html
먼저 html 파일 2개를 어제 완성했는데 오늘 피드백 받아보니 몇군데 수정사항이 있었다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>헬스장 정보 리스트 페이지</title>
</head>
<style>
.layout {
width: 500px;
margin: 0 auto;
margin-top: 40px;
}
</style>
<body>
<table>
<thead>
<tr>
<h1>제목</h1>
</tr>
</thead>
<tbody>
<tr th:each = "healthInfo:${list}">
<td th:text="${healthInfo.id}"></td>
<td th:text="${healthInfo.brand_name}"></td>
<td th:text="${healthInfo.land_number}"></td>
<td th:text="${healthInfo.road_number}"></td>
<td th:text="${healthInfo.category}"></td>
</tr>
</tbody>
</table>
</body>
</html>
home.html 로 기본 페이지가 되는 형태이다. 아래에 타임리프문을 적용한 반복문의 healthInfo 부분을 수정했고, 브랜드 넘버로 되어있던것을 브랜드 네임으로 수정했다.
위 구분은 홈서비스에서 리스트로 저장되는 값들을 반복문이 돌아가면서 페이지에 보여주는 형태이다.
결과물)

이와 같이 /home을 url에 요청해주면, 웹브라우저에 리스트의 형태로 데이터가 잘 표현되는 것을 볼 수 있었다.(갓 팀장님..)
이제 read는 했으니 저장을 만들 차례이다.
기본 골조는 저장버튼을 누르면, 저장하는 페이지로 넘어가고 해당 페이지에서 데이터를 입력한 뒤 저장하는 형태로 만드려고한다.
저장 기능을 구현하기 전에 보기에 너무 어지러워서 상세페이지 작업을 먼저했다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>헬스장 정보 리스트 페이지</title>
</head>
<body>
<table>
<thead>
<tr>
<h1>Homepage</h1>
<button type="submit" onclick="location.href='home/post'">데이터 입력</button>
</tr>
</thead>
<tbody>
<tr th:each = "healthInfo:${list}">
<td th:text="${healthInfo.id}"></td>
<td>
<a th:text="${healthInfo.brand_name}"
th:href="@{/home/view(id=${healthInfo.id})}">
</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>
기존 home.html페이지에서는 id와 brand_name만 볼 수 있게하고 다른 내용들은 해당 brand_name을 클릭하면 상세페이지로 넘어가 볼 수 있게 했다.
여기서 반복문을 사용해 모든 값들을 다 찾아오는 것은 동일하나 brand_name에 a태그를 붙여 상세페이지로 넘어가게 작업했다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>상세페이지</title>
</head>
<body>
<h1 th:text="${healthInfo.brand_name}"></h1>
<p th:text="${healthInfo.land_number}"></p>
<p th:text="${healthInfo.road_number}"></p>
<p th:text="${healthInfo.category}"></p>
<button type="submit" onclick="location.href='/home'">뒤로</button>
</body>
</html>
위는 상세페이지로 앞서 만들었던 모든 값을 다 가져오는 형태와 유사하지만, a태그 brand_name을 누르면 해당 id값을 통해 다른 내용들을 불러올 수 있게 만들었다.
여기서 id값이 조회되지않아 한참을 헤맸는데 팀장님이 컨트롤러와 서비스에 빈등록 및 생성자 어노테이션을 빼먹어서 발생한 오류라는 내용으로 겨우 해결할 수 있었다.
@RequiredArgsConstructor
@Controller
@Slf4j
public class HomeController {
private final HealthRepository healthRepository;
private final HomeService homeService;
//기본형태
@GetMapping("/home") //url localhost:8080/home
public String home(Model model) {
model.addAttribute("list", healthRepository.findAll());
return "home";
}
@GetMapping("/home/view")
public String healthView(Model model,@RequestParam Long id){
model.addAttribute("healthInfo", homeService.healthView(id));
return "healthview";
}
}
메인 컨트롤러에는 @Controller로 빈등록을 하고, private final로 선언된 생성자 호출을 하기위해선@RequiredArgsConstructor 어노테이션이 필요했다.
이 과정이 없었기 때문에 각 값들이 null로 계속 표기되어있었던 것이다.
여하튼 아래의 healthView 메서드를 보면, 파라미터로 id값을 받아 서비스의 healthView라는 메서드로 값들을 찾아오게 되어있다.
반환 값은 앞에서 살펴본 상세페이지 html파일이다.
@Service
@RequiredArgsConstructor
public class HomeServiceImpl implements HomeService {
private final HealthRepository healthRepository;
@Override
public void write(HealthInfo healthInfo) {
healthRepository.save(healthInfo);
}
@Override
public List<HealthInfo> HealthList() {
List<HealthInfo>list=healthRepository.findAll();
return list;
}
@Override
public HealthInfo healthView(Long id) {
System.out.println(id);
return healthRepository.findById(id).orElseThrow(IllegalArgumentException::new);
}
}
이는 Service 인터페이스의 구현체로 healthView가 findById메서드로 나머지 값들을 레포지토리에서 조회해하는 것을 볼 수 있다. 혹여나 null값 오류가 발생할 것을 대비해 null값 오류라는 예외처리구문을 출력하는 orElseThrow메서드도 사용했다.
id값 조회에서 null오류가 계속 발생해 몇시간을 날려버린 자신에게 너무 화가나는 과정이었다.
빈등록 어노테이션과
'TIL' 카테고리의 다른 글
| 2023.01.13 (0) | 2023.01.13 |
|---|---|
| 2023.01.12 TIL (0) | 2023.01.12 |
| 2023.01.10 TIL (0) | 2023.01.10 |
| 2023.01.09 TIL (0) | 2023.01.09 |
| 2023.01.06 TIL (0) | 2023.01.06 |