Java 시작하기 | JDK 설치부터 Hello World까지
이 글의 핵심
Java 시작하기: JDK 설치부터 Hello World까지. JDK 설치·Hello World.
시리즈 안내
#01 | 📋 전체 목차 | 다음: #02 변수와 타입
들어가며
”한 번 작성하면 어디서나 실행”
Java는 1995년 Sun Microsystems(현 Oracle)가 내놓은 객체지향(데이터와 동작을 객체로 묶어 설계하는 방식) 언어입니다. Write Once, Run Anywhere(WORA)는 같은 바이트코드를 JVM(자바 바이트코드를 실행하는 가상 머신)이 있는 환경에서 실행한다는 뜻입니다. 클래스는 객체의 설계도, 인스턴스는 그 설계도로 만든 실체라는 관점이 이후 글 전체와 연결됩니다. Java의 핵심 특징:
- ✅ 플랫폼 독립적: JVM(Java Virtual Machine)에서 실행
- ✅ 객체지향: 모든 것이 객체 (클래스 기반)
- ✅ 가비지 컬렉션: 자동 메모리 관리
- ✅ 강력한 타입: 정적 타입 언어 (컴파일 타임 체크)
- ✅ 풍부한 라이브러리: 방대한 표준 라이브러리와 생태계
- ✅ 멀티스레딩: 내장 스레드 지원
- ✅ 보안: 샌드박스 모델 Java가 사용되는 곳:
- 🏢 엔터프라이즈: Spring Framework, 대규모 서버
- 📱 Android: Android 앱 개발
- 🌐 웹: JSP, Servlet, Spring Boot
- 📊 빅데이터: Hadoop, Spark
- 🎮 게임: Minecraft
실전 경험에서 배운 교훈
이 기술을 실무 프로젝트에 처음 도입했을 때, 공식 문서만으로는 알 수 없었던 많은 함정들이 있었습니다. 특히 프로덕션 환경에서 발생하는 엣지 케이스들은 로컬 개발 환경에서는 재현조차 되지 않았죠.
가장 어려웠던 점은 성능 최적화였습니다. 처음엔 “동작만 하면 되겠지”라고 생각했지만, 실제 사용자 트래픽이 몰리면서 병목 지점들이 하나씩 드러났습니다. 특히 데이터베이스 쿼리 최적화, 캐싱 전략, 에러 핸들링 구조 등은 여러 번의 장애를 겪으면서 개선해 나갔습니다.
이 글에서는 그런 시행착오를 통해 얻은 실전 노하우와, “이렇게 하면 안 된다”는 교훈들을 함께 정리했습니다. 특히 트러블슈팅 섹션은 실제 장애 대응 경험을 바탕으로 작성했으니, 비슷한 문제를 마주했을 때 참고하시면 도움이 될 것입니다.
1. JDK 설치
JDK vs JRE vs JVM
| 구분 | 설명 | 포함 |
|---|---|---|
| JVM | Java Virtual Machine (실행 엔진) | 바이트코드 실행 |
| JRE | Java Runtime Environment (실행 환경) | JVM + 라이브러리 |
| JDK | Java Development Kit (개발 도구) | JRE + 컴파일러(javac) + 디버거 |
| 개발자는 JDK 설치 필수! |
Windows 설치
1. JDK 다운로드:
- Oracle JDK (상용 라이선스)
- OpenJDK (무료, 권장) 2. 설치:
# 다운로드한 설치 프로그램 실행
# 설치 경로: C:\Program Files\Java\jdk-21
# 환경 변수 자동 설정 (또는 수동)
JAVA_HOME=C:\Program Files\Java\jdk-21
PATH=%JAVA_HOME%\bin;%PATH%
3. 설치 확인:
java -version
# 출력:
# openjdk version "21.0.1" 2023-10-17
# OpenJDK Runtime Environment (build 21.0.1+12-29)
# OpenJDK 64-Bit Server VM (build 21.0.1+12-29, mixed mode, sharing)
javac -version
# 출력:
# javac 21.0.1
macOS 설치
# Homebrew 사용
brew install openjdk@21
# 심볼릭 링크 생성
sudo ln -sfn /opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk \
/Library/Java/JavaVirtualMachines/openjdk-21.jdk
# 확인
java -version
Linux 설치
# Ubuntu/Debian
sudo apt update
sudo apt install openjdk-21-jdk
# CentOS/RHEL
sudo yum install java-21-openjdk-devel
# 확인
java -version
javac -version
2. Hello World
HelloWorld.java 작성
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
}
코드 설명:
public class HelloWorld: 공개 클래스 선언 (파일명과 동일해야 함)public static void main(String[] args): 프로그램 진입점public: 어디서나 접근 가능static: 객체 생성 없이 호출 가능void: 반환값 없음String[] args: 명령줄 인자
System.out.println(): 콘솔 출력
컴파일 및 실행
# 1. 컴파일 (javac)
javac HelloWorld.java
# → HelloWorld.class 생성 (바이트코드)
# 2. 실행 (java)
java HelloWorld
# 출력: Hello, Java!
동작 원리:
HelloWorld.java (소스 코드)
↓ javac (컴파일)
HelloWorld.class (바이트코드)
↓ java (실행)
JVM (플랫폼별 실행)
↓
출력: Hello, Java!
명령줄 인자
public class Args {
public static void main(String[] args) {
System.out.println("인자 개수: " + args.length);
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "]: " + args[i]);
}
}
}
javac Args.java
java Args 안녕 자바 123
# 출력:
# 인자 개수: 3
# args[0]: 안녕
# args[1]: 자바
# args[2]: 123
3. IDE 설정
IntelliJ IDEA (권장)
1. 다운로드:
- IntelliJ IDEA Community (무료) 2. 프로젝트 생성:
File → New → Project
- Name: MyFirstJavaProject
- Language: Java
- Build System: IntelliJ
- JDK: 21
3. 실행:
- 단축키:
Shift + F10(Run) - 디버그:
Shift + F9
Eclipse
1. 다운로드:
- Eclipse IDE for Java Developers 2. 프로젝트 생성:
File → New → Java Project
- Project name: MyFirstJavaProject
- JRE: Use default JRE
VS Code
1. 확장 설치:
- Extension Pack for Java 2. 프로젝트 생성:
# 명령 팔레트 (Ctrl+Shift+P)
Java: Create Java Project
4. 기본 문법
변수와 타입
public class Variables {
public static void main(String[] args) {
// 기본 타입 (Primitive Types)
byte b = 127; // 8비트 (-128 ~ 127)
short s = 32767; // 16비트
int age = 25; // 32비트 (기본)
long population = 7800000000L; // 64비트 (L 접미사)
float pi = 3.14f; // 32비트 (f 접미사)
double price = 19.99; // 64비트 (기본)
boolean isActive = true; // true/false
char grade = 'A'; // 16비트 유니코드
// 참조 타입 (Reference Types)
String name = "홍길동";
String message = "안녕하세요!";
// 출력
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("가격: " + price);
}
}
상수
// 실행 예제
public class Constants {
public static void main(String[] args) {
// final: 변경 불가
final int MAX_SIZE = 100;
final double PI = 3.14159;
final String APP_NAME = "MyApp";
// MAX_SIZE = 200; // 컴파일 에러!
System.out.println("최대 크기: " + MAX_SIZE);
}
}
연산자
// 실행 예제
public class Operators {
public static void main(String[] args) {
// 산술 연산자
int a = 10, b = 3;
System.out.println("더하기: " + (a + b)); // 13
System.out.println("빼기: " + (a - b)); // 7
System.out.println("곱하기: " + (a * b)); // 30
System.out.println("나누기: " + (a / b)); // 3 (정수 나눗셈)
System.out.println("나머지: " + (a % b)); // 1
// 비교 연산자
System.out.println(a > b); // true
System.out.println(a == b); // false
System.out.println(a != b); // true
// 논리 연산자
boolean x = true, y = false;
System.out.println(x && y); // false (AND)
System.out.println(x || y); // true (OR)
System.out.println(!x); // false (NOT)
// 증감 연산자
int count = 0;
count++; // count = count + 1
System.out.println(count); // 1
count--; // count = count - 1
System.out.println(count); // 0
}
}
조건문
// 실행 예제
public class Conditionals {
public static void main(String[] args) {
int score = 85;
// if-else
if (score >= 90) {
System.out.println("A");
} else if (score >= 80) {
System.out.println("B");
} else if (score >= 70) {
System.out.println("C");
} else {
System.out.println("F");
}
// switch
String day = "월요일";
switch (day) {
case "월요일":
System.out.println("월요일입니다.");
break;
case "금요일":
System.out.println("금요일입니다!");
break;
default:
System.out.println("평일입니다.");
}
// 삼항 연산자
String result = (score >= 60) ? "합격" : "불합격";
System.out.println(result);
}
}
반복문
public class Loops {
public static void main(String[] args) {
// for 문
for (int i = 0; i < 5; i++) {
System.out.println("i = " + i);
}
// while 문
int count = 0;
while (count < 3) {
System.out.println("count = " + count);
count++;
}
// do-while 문
int num = 0;
do {
System.out.println("num = " + num);
num++;
} while (num < 3);
// 배열 순회
int[] numbers = {1, 2, 3, 4, 5};
for (int n : numbers) {
System.out.println(n);
}
}
}
5. 함수 (메서드)
메서드 정의
public class Calculator {
// 반환값 있는 메서드
public static int add(int a, int b) {
return a + b;
}
// 반환값 없는 메서드
public static void printSum(int a, int b) {
System.out.println("합계: " + (a + b));
}
// 오버로딩 (같은 이름, 다른 매개변수)
public static int add(int a, int b, int c) {
return a + b + c;
}
public static double add(double a, double b) {
return a + b;
}
public static void main(String[] args) {
int result1 = add(10, 20);
System.out.println("결과1: " + result1); // 30
int result2 = add(10, 20, 30);
System.out.println("결과2: " + result2); // 60
double result3 = add(10.5, 20.3);
System.out.println("결과3: " + result3); // 30.8
printSum(5, 7); // 합계: 12
}
}
가변 인자
public class VarArgs {
public static int sum(int....numbers) {
int total = 0;
for (int n : numbers) {
total += n;
}
return total;
}
public static void main(String[] args) {
System.out.println(sum(1, 2, 3)); // 6
System.out.println(sum(1, 2, 3, 4, 5)); // 15
System.out.println(sum(10)); // 10
}
}
6. 클래스와 객체
클래스 정의
public class Person {
// 필드 (멤버 변수)
private String name;
private int age;
// 생성자
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 기본 생성자
public Person() {
this("이름없음", 0);
}
// 메서드
public void introduce() {
System.out.println("안녕하세요, " + name + "입니다.");
System.out.println("나이는 " + age + "세입니다.");
}
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0) {
this.age = age;
}
}
}
객체 생성 및 사용
public class Main {
public static void main(String[] args) {
// 객체 생성
Person person1 = new Person("홍길동", 25);
Person person2 = new Person("김철수", 30);
Person person3 = new Person();
// 메서드 호출
person1.introduce();
// 출력:
// 안녕하세요, 홍길동입니다.
// 나이는 25세입니다.
person2.introduce();
// Getter/Setter 사용
System.out.println("이름: " + person1.getName());
person1.setAge(26);
System.out.println("새 나이: " + person1.getAge());
}
}
7. 배열
배열 선언 및 초기화
public class Arrays {
public static void main(String[] args) {
// 배열 선언 방법 1
int[] numbers1 = new int[5];
numbers1[0] = 10;
numbers1[1] = 20;
// 배열 선언 방법 2
int[] numbers2 = {1, 2, 3, 4, 5};
// 배열 선언 방법 3
int[] numbers3 = new int[]{10, 20, 30};
// 배열 길이
System.out.println("길이: " + numbers2.length); // 5
// 배열 순회
for (int i = 0; i < numbers2.length; i++) {
System.out.println("numbers2[" + i + "] = " + numbers2[i]);
}
// 향상된 for 문
for (int num : numbers2) {
System.out.println(num);
}
// 2차원 배열
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
System.out.println(matrix[1][2]); // 6
}
}
8. 실전 예제
예제 1: 계산기
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("첫 번째 숫자: ");
double num1 = scanner.nextDouble();
System.out.print("연산자 (+, -, *, /): ");
String operator = scanner.next();
System.out.print("두 번째 숫자: ");
double num2 = scanner.nextDouble();
double result = 0;
switch (operator) {
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "*":
result = num1 * num2;
break;
case "/":
if (num2 != 0) {
result = num1 / num2;
} else {
System.out.println("0으로 나눌 수 없습니다.");
return;
}
break;
default:
System.out.println("잘못된 연산자입니다.");
return;
}
System.out.println("결과: " + result);
scanner.close();
}
}
예제 2: 학생 관리
public class Student {
private String name;
private int studentId;
private double gpa;
public Student(String name, int studentId, double gpa) {
this.name = name;
this.studentId = studentId;
this.gpa = gpa;
}
public void printInfo() {
System.out.println("=== 학생 정보 ===");
System.out.println("이름: " + name);
System.out.println("학번: " + studentId);
System.out.println("학점: " + gpa);
}
public String getGrade() {
if (gpa >= 4.0) return "A";
else if (gpa >= 3.0) return "B";
else if (gpa >= 2.0) return "C";
else return "F";
}
public static void main(String[] args) {
Student student1 = new Student("홍길동", 20240001, 3.8);
Student student2 = new Student("김철수", 20240002, 4.2);
student1.printInfo();
System.out.println("등급: " + student1.getGrade());
System.out.println();
student2.printInfo();
System.out.println("등급: " + student2.getGrade());
}
}
예제 3: 은행 계좌
public class BankAccount {
private String accountNumber;
private String owner;
private double balance;
public BankAccount(String accountNumber, String owner) {
this.accountNumber = accountNumber;
this.owner = owner;
this.balance = 0.0;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println(amount + "원 입금 완료");
System.out.println("잔액: " + balance + "원");
} else {
System.out.println("입금액은 0보다 커야 합니다.");
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println(amount + "원 출금 완료");
System.out.println("잔액: " + balance + "원");
} else {
System.out.println("출금 불가 (잔액 부족 또는 잘못된 금액)");
}
}
public void printInfo() {
System.out.println("=== 계좌 정보 ===");
System.out.println("계좌번호: " + accountNumber);
System.out.println("예금주: " + owner);
System.out.println("잔액: " + balance + "원");
}
public static void main(String[] args) {
BankAccount account = new BankAccount("123-456-789", "홍길동");
account.printInfo();
account.deposit(10000);
account.deposit(5000);
account.withdraw(3000);
account.withdraw(20000); // 잔액 부족
account.printInfo();
}
}
9. 자주 발생하는 문제
1. 클래스명과 파일명 불일치
문제:
// HelloWorld.java 파일
public class Hello { // 클래스명이 다름
public static void main(String[] args) {
System.out.println("Hello");
}
}
에러:
error: class Hello is public, should be declared in a file named Hello.java
해결: 파일명을 Hello.java로 변경하거나 클래스명을 HelloWorld로 변경
2. main 메서드 시그니처 오류
문제:
public class Test {
public void main(String[] args) { // static 누락
System.out.println("Test");
}
}
에러:
Error: Main method not found in class Test
해결: public static void main(String[] args) 정확히 작성
3. 세미콜론 누락
문제:
System.out.println("Hello") // 세미콜론 누락
에러:
error: ';' expected
해결: 모든 문장 끝에 ; 추가
4. 대소문자 구분
문제:
String name = "홍길동";
system.out.println(name); // System이 아닌 system
에러:
error: cannot find symbol
symbol: variable system
해결: Java는 대소문자를 구분합니다. System 정확히 작성
10. Java 컴파일과 실행 과정
컴파일 과정
1. 소스 코드 작성
HelloWorld.java
2. 컴파일 (javac)
javac HelloWorld.java
→ HelloWorld.class (바이트코드)
3. 실행 (java)
java HelloWorld
→ JVM이 바이트코드 해석 및 실행
4. 출력
Hello, Java!
JVM 동작 원리
HelloWorld.class (바이트코드)
↓
Class Loader (클래스 로딩)
↓
Bytecode Verifier (검증)
↓
JIT Compiler (Just-In-Time 컴파일)
↓
Native Code (기계어)
↓
실행
플랫폼 독립성:
Windows: HelloWorld.class → Windows JVM → 실행
macOS: HelloWorld.class → macOS JVM → 실행
Linux: HelloWorld.class → Linux JVM → 실행
동일한 .class 파일이 모든 플랫폼에서 실행!
11. 실전 팁
1. 코딩 컨벤션
// ✅ 좋은 코드
public class MyClass { // 클래스: PascalCase
private static final int MAX_SIZE = 100; // 상수: UPPER_SNAKE_CASE
private String userName; // 변수: camelCase
public void getUserName() { // 메서드: camelCase
return userName;
}
}
// ❌ 나쁜 코드
public class myclass { // 소문자
private int MaxSize = 100; // PascalCase
private String user_name; // snake_case
}
2. 주석
// 한 줄 주석
/*
* 여러 줄 주석
* 설명...
*/
/**
* JavaDoc 주석
* @param name 사용자 이름
* @return 인사 메시지
*/
public String greet(String name) {
return "안녕하세요, " + name + "님!";
}
3. 패키지
// com/example/myapp/Main.java
// 패키지 선언
package com.example.myapp;
import java.util.Scanner;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 코드...
}
}
4. 디버깅
public class Debug {
public static void main(String[] args) {
int a = 10;
int b = 0;
// 중단점 설정 (IDE에서)
int result = a / b; // ArithmeticException
System.out.println(result);
}
}
IntelliJ 디버깅:
- 중단점 설정: 줄 번호 왼쪽 클릭
- 디버그 실행:
Shift + F9 - 단계 실행:
F8(Step Over),F7(Step Into)
12. Java 버전
주요 버전 변화
| 버전 | 출시 | 주요 기능 |
|---|---|---|
| Java 8 | 2014 | Lambda, Stream API, Optional |
| Java 11 | 2018 | var, HTTP Client, String 메서드 |
| Java 17 | 2021 | Sealed Classes, Pattern Matching (LTS) |
| Java 21 | 2023 | Virtual Threads, Pattern Matching (LTS) |
| LTS (Long-Term Support): 장기 지원 버전 (8, 11, 17, 21) |
최신 기능 맛보기
// Java 10: var (타입 추론)
var name = "홍길동"; // String
var age = 25; // int
var list = new ArrayList<String>();
// Java 14: Switch Expression
String result = switch (day) {
case "월", "화", "수", "목", "금" -> "평일";
case "토", "일" -> "주말";
default -> "알 수 없음";
};
// Java 16: Record (불변 데이터 클래스)
record Person(String name, int age) {}
Person person = new Person("홍길동", 25);
System.out.println(person.name()); // 홍길동
정리
핵심 요약
- Java: 플랫폼 독립적, 객체지향 언어
- JDK: Java 개발 도구 키트 (컴파일러 포함)
- JVM: Java 가상 머신 (바이트코드 실행)
- 컴파일:
javac HelloWorld.java→.class - 실행:
java HelloWorld - 클래스: 모든 코드는 클래스 안에
- main 메서드: 프로그램 진입점
- 객체지향: 클래스와 객체로 프로그래밍
Java 기본 구조
// 패키지 선언 (선택)
package com.example;
// import 문 (선택)
import java.util.Scanner;
// 클래스 선언 (필수)
public class MyClass {
// 필드 (멤버 변수)
private int value;
// 생성자
public MyClass(int value) {
this.value = value;
}
// 메서드
public void printValue() {
System.out.println(value);
}
// main 메서드 (진입점)
public static void main(String[] args) {
MyClass obj = new MyClass(10);
obj.printValue();
}
}
실전 팁
- IDE 사용: IntelliJ IDEA 또는 Eclipse 권장
- 코딩 컨벤션: 클래스는 PascalCase, 변수/메서드는 camelCase
- 패키지 구조:
com.회사명.프로젝트명.기능 - 주석: JavaDoc 형식으로 문서화
- 예외 처리: try-catch로 에러 처리
- 디버깅: 중단점과 단계 실행 활용
- 버전 선택: LTS 버전 사용 (17 또는 21)
- 빌드 도구: Maven 또는 Gradle 사용
다음 단계
관련 글
- C++ 초보자가 자주 하는 실수 Top 15 | 컴파일 에러부터 런타임 크래시까지
- HTML/CSS 시작하기 | 웹 개발 첫걸음
- Java 변수와 타입 | 기본 타입, 참조 타입, 형변환
- Java 클래스와 객체 | OOP, 상속, 인터페이스
- Java 컬렉션 | ArrayList, HashMap, Set
심화 부록: 구현·운영 관점
이 부록은 앞선 본문에서 다룬 주제(「Java 시작하기 | JDK 설치부터 Hello World까지」)를 구현·런타임·운영 관점에서 다시 압축합니다. 도메인별 세부 구현은 글마다 다르지만, 입력 검증 → 핵심 연산 → 부작용(I/O·네트워크·동시성) → 관측의 흐름으로 장애를 나누면 원인 추적이 빨라집니다.
내부 동작과 핵심 메커니즘
flowchart TD A[입력·요청·이벤트] --> B[파싱·검증·디코딩] B --> C[핵심 연산·상태 전이] C --> D[부작용: I/O·네트워크·동시성] D --> E[결과·관측·저장]
sequenceDiagram participant C as 클라이언트/호출자 participant B as 경계(런타임·게이트웨이·프로세스) participant D as 의존성(API·DB·큐·파일) C->>B: 요청/이벤트 B->>D: 조회·쓰기·RPC D-->>B: 지연·부분 실패·재시도 가능 B-->>C: 응답 또는 오류(코드·상관 ID)
- 불변 조건(Invariant): 버퍼 경계, 프로토콜 상태, 트랜잭션 격리, FD 상한 등 단계별로 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
- 결정성: 순수 층과 시간·네트워크·스케줄에 의존하는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
- 경계 비용: 직렬화, 인코딩, syscall 횟수, 락 경합, 할당·GC, 캐시 미스를 의심 목록에 둡니다.
- 백프레셔: 생산자가 소비자보다 빠를 때 버퍼·큐·스트림에서 속도를 줄이는 신호를 어디에 둘지 정의합니다.
프로덕션 운영 패턴
| 영역 | 운영 관점 질문 |
|---|---|
| 관측성 | 요청 단위 상관 ID, 에러율·지연 p95/p99, 의존성 타임아웃·재시도가 대시보드에 보이는가 |
| 안전성 | 입력 검증·권한·비밀·감사 로그가 코드 경로마다 일관적인가 |
| 신뢰성 | 재시도는 멱등 연산에만 적용되는가, 서킷 브레이커·백오프·DLQ가 있는가 |
| 성능 | 캐시·배치 크기·커넥션 풀·인덱스·백프레셔가 데이터 규모에 맞는가 |
| 배포 | 롤백 룬북, 카나리/블루그린, 마이그레이션·피처 플래그가 문서화되어 있는가 |
| 용량 | 피크 트래픽·디스크·FD·스레드 풀 상한을 주기적으로 검증하는가 |
스테이징은 데이터 양·네트워크 RTT·동시성을 프로덕션에 가깝게 맞출수록 재현율이 올라갑니다.
확장 예시: 엔드투엔드 미니 시나리오
앞선 본문 주제(「Java 시작하기 | JDK 설치부터 Hello World까지」)를 배포·운영 흐름에 맞춰 옮긴 체크리스트입니다. 도메인에 맞게 단계 이름만 바꿔 적용할 수 있습니다.
- 입력 계약 고정: 스키마·버전·최대 페이로드·타임아웃·에러 코드를 경계에 둔다.
- 핵심 경로 계측: 요청 ID, 단계별 지연, 외부 호출 결과 코드를 로그·메트릭·트레이스에서 한 흐름으로 본다.
- 실패 주입: 의존성 타임아웃·5xx·부분 데이터·락 대기를 스테이징에서 재현한다.
- 호환·롤백: 설정/마이그레이션/클라이언트 버전을 되돌릴 수 있는지 확인한다.
- 부하 후 검증: 피크 대비 p95/p99, 에러율, 리소스 상한, 알림 임계값을 점검한다.
handle(request):
ctx = newCorrelationId()
validated = validateSchema(request)
authorize(validated, ctx)
result = domainCore(validated)
persistOrEmit(result, idempotentKey)
recordMetrics(ctx, latency, outcome)
return result
문제 해결(Troubleshooting)
| 증상 | 가능 원인 | 조치 |
|---|---|---|
| 간헐적 실패 | 레이스, 타임아웃, 외부 의존성, DNS | 최소 재현 스크립트, 분산 트레이스·로그 상관관계, 재시도·서킷 설정 점검 |
| 성능 저하 | N+1, 동기 I/O, 락 경합, 과도한 직렬화, 캐시 미스 | 프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거 |
| 메모리 증가 | 캐시 무제한, 구독/리스너 누수, 대용량 버퍼, 커넥션 미반납 | 상한·TTL·힙/FD 스냅샷 비교 |
| 빌드·배포만 실패 | 환경 변수, 권한, 플랫폼 차이, lockfile | CI 로그와 로컬 diff, 런타임·이미지 버전 핀 |
| 설정 불일치 | 프로필·시크릿·기본값, 리전 | 스키마 검증된 설정 단일 소스와 배포 매트릭스 표준화 |
| 데이터 불일치 | 비멱등 재시도, 부분 쓰기, 캐시 무효화 누락 | 멱등 키·아웃박스·트랜잭션 경계 재검토 |
권장 순서: (1) 최소 재현 (2) 최근 변경 범위 축소 (3) 환경·의존성 차이 (4) 관측으로 가설 검증 (5) 수정 후 회귀·부하 테스트.
배포 전에는 git add → git commit → git push 후 npm run deploy 순서를 권장합니다.
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. Java 시작하기: JDK 설치부터 Hello World까지. JDK 설치·Hello World로 흐름을 잡고 원리·코드·실무 적용을 한글로 정리합니다. Java·자바·JDK 중심으로 설명합니다. Start now. 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. Java 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- Kotlin Spring Boot 입문 | 30분 만에 REST API 만들기 [초보자용]
- JavaScript 클래스 | ES6 Class 문법 완벽 정리
- C++ Chrono Literals | ‘시간 리터럴’ 가이드
이 글에서 다루는 키워드 (관련 검색어)
Java, 자바, JDK, 입문 등으로 검색하시면 이 글이 도움이 됩니다.