필독 개발자 온보딩 가이드을 읽고 정리하는 글이며, 혹시 문제가 되면 삭제하겠습니다.
불변 변수
사용정적 타입 검사기
를 활용해서 버그 줄이기입력값 검사
예외 처리 기법
을 활용하여 장애를 적절하게 처리한다.private final int value;
- 값의 보장
- 스레드 안전성
- 캐시화 용이
- 디버깅 및 테스트 용이
- 함수형 프로그래밍과의 조합
if (inputValue >= 0 && inputValue <= 100) {
// 유효한 범위 내의 입력값 처리
} else {
// 범위를 벗어난 입력값 처리
}
try {
// 입력값 검사
if (inputValue < 0) {
throw new IllegalArgumentException("입력값은 음수일 수 없습니다.");
}
// 유효한 입력값 처리
} catch (IllegalArgumentException e) {
// 예외 처리
System.err.println("에러: " + e.getMessage());
}
String emailRegex = "^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$";
if (inputValue.matches(emailRegex)) {
// 유효한 이메일 주소 형식
} else {
// 잘못된 형식
}
import org.apache.commons.lang3.Validate;
try {
Validate.isTrue(inputValue > 0, "입력값은 양수여야 합니다.");
// 유효한 입력값 처리
} catch (IllegalArgumentException e) {
// 예외 처리
System.err.println("에러: " + e.getMessage());
}
디폴트 값을 제공하고, 코드의 가독성을 향상한다.
interface Shape {
double area();
}
class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double area() {
return Math.PI * radius * radius;
}
}
class NullShape implements Shape {
public double area() {
return 0.0; // 널 객체 역할, 디폴트 값 제공
}
}
import java.util.Arrays;
public class SearchExample {
private static final Person[] EMPTY_PERSON_ARRAY = new Person[0];
public static Person[] searchPersons(String keyword) {
// 원하는 검색 로직 구현
// 예시로 항상 빈 배열을 리턴하도록 함
return EMPTY_PERSON_ARRAY;
}
public static void main(String[] args) {
String searchKeyword = "Alice";
Person[] foundPersons = searchPersons(searchKeyword);
if (foundPersons.length == 0) {
System.out.println("No persons found.");
} else {
System.out.println("Found persons:");
for (Person person : foundPersons) {
System.out.println("Name: " + person.getName() + ", Age: " + person.getAge());
}
}
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
class Option<T> { //Option 클래스는 제너릭 타입을 사용해서 값의 존재 유무를 나타내며
private T value;
private Option(T value) {
this.value = value;
}
public static <T> Option<T> of(T value) {
return new Option<>(value);
}
public T get() {
if (value == null) { // 값이 없는 경우 예외를 던지며
throw new IllegalStateException("No value present");
}
return value; // 값이 있는 경우 실제값 반환
}
}
NotNull
애노테이션 언어 기능 이용import javax.validation.constraints.NotNull;
public class Person {
private String name;
private int age;
public Person(@NotNull String name, @NotNull int age) {
this.name = name;
this.age = age;
}
@NotNull
public String getName() {
return name;
}
public void setName(@NotNull String name) {
this.name = name;
}
@NotNull
public int getAge() {
return age;
}
public void setAge(@NotNull int age) {
this.age = age;
}
public static void main(String[] args) {
// 올바른 사용
Person person = new Person("Alice", 30);
System.out.println("Name: " + person.getName());
System.out.println("Age: " + person.getAge());
// 잠재적인 오류: null 값 전달
Person nullPerson = new Person(null, 25); // 컴파일 오류 발생
System.out.println("Name: " + nullPerson.getName());
System.out.println("Age: " + nullPerson.getAge());
}
}
자바에서는 final, 스칼라에서는 val 러스트는 let
변수가 보관할 수 있는 값을 제한하자. 몇 가지 문자열 값 중 하나만 가질 수 있는 변수는 String보다는
Enum
선언 가능
- Enum은 몇 가지 고정된 값을 나타내는 자료형으로, 한정된 선택지 중 하나만 가질 수 있는 변수
- 가독성 및 안정성의 좋음
- 제한된 선택지
- 코드 유지보수
- 타입 안정성
- 열거형 상수 사용
public enum DayOfWeek {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class Main {
public static void main(String[] args) {
DayOfWeek today = DayOfWeek.WEDNESDAY;
switch (today) {
case MONDAY:
System.out.println("Today is Monday.");
break;
case WEDNESDAY:
System.out.println("Today is Wednesday.");
break;
// ...
}
}
}
def say(something: str) -> str:
return "You said: " + something
타입 힌트는 기존의 코드베이스에 점진적으로 추가 가능하며, 타입 힌트를 이용해서 코드가 실행되기 전에 버그를 찾아되는 정적 타입 검사기 도입 하면 런타임 에러 해결 가능
코드로 전달되는 입력값은 훼손 가능성이 높음. 사전 조건, 체크섬, 데이터 유효성 검사, 보안 관련 권장 기법, 보편적인 에러를 찾아주는 도구 활용
입력 문자열
이 원하는 형식인지 확인하고, 문자열 앞 뒤의 공백도 처리해야 한다는 점유효성 검사란 함수나 메소드의 매개변수에 대한 타입, 범위, 상태 등을 확인하는 과정
AssertionError
예외 발생def divide(a, b):
assert b != 0, "b cannot be zero"
return a / b
AssertionError
예외 발생def calculate_sum(numbers):
result = sum(numbers)
assert result >= 0, "sum should be non-negative"
return result
1. cheackNotNull이라는 메소드
2. @Size(min=0, max=100)
1. 체크섬이란?
import hashlib
def calculate_checksum(data):
# 데이터의 체크섬 값을 계산하는 함수
sha256 = hashlib.sha256()
sha256.update(data.encode())
return sha256.hexdigest()
def save_data_with_checksum(filename, data):
# 데이터와 체크섬 값을 파일에 저장하는 함수
checksum = calculate_checksum(data)
with open(filename, 'w') as file:
file.write(data + '\n')
file.write(checksum)
def verify_checksum(filename):
# 저장된 데이터와 체크섬 값을 확인하는 함수
with open(filename, 'r') as file:
lines = file.readlines()
data = lines[0].strip()
saved_checksum = lines[1].strip()
calculated_checksum = calculate_checksum(data)
if saved_checksum == calculated_checksum:
print("Checksum verification successful. Data is intact.")
else:
print("Checksum verification failed. Data may be corrupted.")
# 예시 데이터를 생성하고 저장
data = "Hello, world!"
filename = "data.txt"
save_data_with_checksum(filename, data)
# 데이터 무결성 검증
verify_checksum(filename)
2. java 예제
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class DataIntegrityExample {
// 입력된 데이터의 체크섬을 계산하는 메서드
public static String calculateChecksum(String data) throws NoSuchAlgorithmException {
// SHA-256 해시 알고리즘을 사용하는 MessageDigest 객체 생성
MessageDigest md = MessageDigest.getInstance("SHA-256");
// 데이터의 해시값 계산
byte[] hash = md.digest(data.getBytes());
StringBuilder hexString = new StringBuilder();
// 해시값을 16진수 문자열로 변환하여 반환
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
public static void main(String[] args) {
try {
// 원본 데이터 설정
String originalData = "Hello, world!";
// 원본 데이터의 체크섬 계산
String checksum = calculateChecksum(originalData);
System.out.println("Original Data: " + originalData);
System.out.println("Calculated Checksum: " + checksum);
// 데이터 변조 시뮬레이션
String corruptedData = "Hacked, world!";
// 변조된 데이터의 체크섬 계산
String corruptedChecksum = calculateChecksum(corruptedData);
System.out.println("Corrupted Data: " + corruptedData);
System.out.println("Corrupted Checksum: " + corruptedChecksum);
// 체크섬 값 비교를 통한 데이터 무결성 검증
if (checksum.equals(corruptedChecksum)) {
System.out.println("Checksum verification failed. Data may be corrupted.");
} else {
System.out.println("Checksum verification successful. Data is intact.");
}
} catch (NoSuchAlgorithmException e) {
System.err.println("Error: " + e.getMessage());
}
}
}
HTML 이스케이프 함수
를 사용하여 사용자 입력 데이터를 안전하게 처리가 필요문자열 복사 함수(strcpy)
를 사용할 때 명시적으로 버퍼의 크기를 설정하거나, 메모리 관리 기능이 강화된 함수(strncpy, memcpy)를 사용하여 버퍼 오버플로를 예방할 수 있다.HTTPS 프로토콜
을 활용하여 데이터의 보안을 강화특정한 리턴값으로 에러를 표현하는 것은 금물이다.
예외는 애플리케이션 로직을 제어하는 용도가 아니라, 실패를 처리할 때만 사용해야 한다. 또한 언어에 내장된 예외 타입이 문제를 구체적으로 표현할 수 있다면 임의로 예외는 정하지 않는다.
if
문 등을 사용하여 명시적인 상태 검증과 처리를 구현해야 한다.public class IncorrectExceptionUsage {
// 잘못된 예외 사용: 애플리케이션 로직으로 예외 활용
public static void processOrder(int orderStatus) throws OrderProcessingException {
try {
if (orderStatus == 0) {
throw new OrderProcessingException("Invalid order status"); // 예외를 상태 검증에 사용
}
// 주문 처리 로직
// ...
} catch (OrderProcessingException ex) {
// 예외를 처리하는 코드
logError(ex.getMessage());
}
}
public static void main(String[] args) {
int orderStatus = 0;
try {
processOrder(orderStatus);
} catch (OrderProcessingException ex) {
logError("Failed to process order: " + ex.getMessage());
}
}
private static void logError(String message) {
System.err.println("Error: " + message);
}
}
개발자가 관련 코드를 신속하게 찾을 수 있도록 에러가 발생한 지점으로부터 최대한 가까운 지점에서 예외를 던진다는 뜻으로 중간에 위치한 계층은 어설프게 에러를 처리하기 보다는 예외를 상위로 계층하는 게 맞다.
예외를 처리할 적절한 위치에 도착할 때까지 계속 호출 스택을 통해 전파시킨다는 뜻이다.
크래시
란 컴퓨터 프로그램이나 시스템이 예기치 않게 중단되거나 동작하지 않는 현상을 의미 다시 말해, 프로그램이나 시스템이 오류로 인해 정상적으로 동작하지 않거나 멈추는 상태
이 경우 예외는 로그에 기록되지도 않고 다시 던져지지도 않으며 다른 어떤 조치도 취해지지 않았다.
장애가 발생해도 아무도 알 수 없으며, 최악의 결과 초래
try{
//..
}
catch(Exception e){
//에러를 처리할 방법이 없으므로 무시
}
예외 처리를 어디서부터 어디까지 해야하는 것을 이 장에서 핵심을 집어주는 것 같다. 이 장은 너무 길어져서 여러 개로 나눠서 정리할 예정이며, 자바와 파이썬의 내장 예외처리에 대해 한 번 정리해야 겠다.