2026년 02월 10일

🌐 OSI 7계층 모델 완벽 가이드

Java Spring Boot
Cover Image

🌐 OSI 7계층 모델 완벽 가이드

Backend 개발자가 알아야 할 네트워크 계층 구조

💡 왜 계층 모델이 필요한가?

문제: 네트워크는 복잡하다!

해결: 계층으로 나누어 관리!

복잡한 시스템 → 7개 계층으로 분할 → 각 계층은 독립적 기능

📊 OSI 7계층 개요

계층 구조

┌─────────────────────────────────────┐
│  7. 응용 계층 (Application)          │ ← 사용자 인터페이스
├─────────────────────────────────────┤
│  6. 표현 계층 (Presentation)         │ ← 데이터 형식 변환
├─────────────────────────────────────┤
│  5. 세션 계층 (Session)              │ ← 연결 관리
├─────────────────────────────────────┤
│  4. 전송 계층 (Transport)            │ ← 신뢰성 있는 전송 (TCP/UDP)
├─────────────────────────────────────┤
│  3. 네트워크 계층 (Network)           │ ← 경로 선택 (IP)
├─────────────────────────────────────┤
│  2. 데이터 링크 계층 (Data Link)      │ ← 물리적 주소 지정 (MAC)
├─────────────────────────────────────┤
│  1. 물리 계층 (Physical)             │ ← 전기 신호
└─────────────────────────────────────┘

기억법

Application    - All
Presentation   - People
Session        - Seem
Transport      - To
Network        - Need
Data Link      - Data
Physical       - Processing

🔍 각 계층 상세 설명

1️⃣ 물리 계층 (Physical Layer)

역할: 비트를 전기 신호로 변환하여 전송

주요 장비:

Backend 개발자 관점:

거의 신경 쓸 일 없음
하드웨어 엔지니어 영역

실무 예시:


역할: 물리적 주소(MAC)를 이용한 노드 간 전송

주요 프로토콜:

주요 장비:

Backend 개발자 관점:

// MAC 주소 확인
InetAddress localhost = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(localhost);
byte[] mac = network.getHardwareAddress();

StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
    sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
System.out.println("MAC Address: " + sb.toString());
// 출력: MAC Address: 00-1A-2B-3C-4D-5E

실무 예시:


3️⃣ 네트워크 계층 (Network Layer)

역할: IP 주소를 이용한 경로 선택 (라우팅)

주요 프로토콜:

주요 장비:

Backend 개발자 관점:

// IP 주소 얻기
InetAddress localhost = InetAddress.getLocalHost();
System.out.println("IP: " + localhost.getHostAddress());
// 출력: IP: 192.168.0.10

// 특정 호스트의 IP 조회
InetAddress google = InetAddress.getByName("google.com");
System.out.println("Google IP: " + google.getHostAddress());
// 출력: Google IP: 142.250.196.46

// 연결 가능 여부 확인 (ICMP)
boolean reachable = google.isReachable(5000);
System.out.println("Reachable: " + reachable);

실무 예시:

# IP 확인
ifconfig  # Mac/Linux
ipconfig  # Windows

# 라우팅 경로 확인
traceroute google.com  # Mac/Linux
tracert google.com     # Windows

# Ping 테스트
ping 8.8.8.8

4️⃣ 전송 계층 (Transport Layer) ⭐⭐⭐

역할: 프로세스 간 신뢰성 있는 데이터 전송

주요 프로토콜:

TCP vs UDP 비교

특성TCPUDP
연결 방식연결 지향 (Connection-oriented)비연결 (Connectionless)
신뢰성✅ 보장 (재전송, 순서 보장)❌ 미보장
속도느림빠름
용도HTTP, HTTPS, FTP, SMTPDNS, 스트리밍, 게임
헤더 크기20 bytes8 bytes
흐름 제어✅ 있음❌ 없음
혼잡 제어✅ 있음❌ 없음

TCP 3-Way Handshake

클라이언트                서버
    │                      │
    │─────── SYN ─────────>│  1. 연결 요청
    │                      │
    │<────── SYN+ACK ──────│  2. 요청 수락
    │                      │
    │─────── ACK ─────────>│  3. 연결 확립
    │                      │
    │   데이터 전송 시작    │

Backend 개발자 관점

// TCP 소켓 (연결 지향)
@Service
public class TcpClientService {

    public String sendTcpRequest(String host, int port, String message)
            throws IOException {

        // 1. 소켓 생성 및 연결 (3-Way Handshake)
        try (Socket socket = new Socket(host, port);
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(
                 new InputStreamReader(socket.getInputStream()))) {

            // 2. 데이터 전송
            out.println(message);

            // 3. 응답 수신
            return in.readLine();
        }
    }
}

// UDP 소켓 (비연결)
@Service
public class UdpClientService {

    public void sendUdpRequest(String host, int port, String message)
            throws IOException {

        try (DatagramSocket socket = new DatagramSocket()) {
            InetAddress address = InetAddress.getByName(host);
            byte[] buffer = message.getBytes();

            // 데이터그램 생성 및 전송 (연결 없이 바로 전송)
            DatagramPacket packet = new DatagramPacket(
                buffer, buffer.length, address, port
            );
            socket.send(packet);
        }
    }
}

Spring Boot에서의 TCP

@RestController
@RequestMapping("/api")
public class ApiController {

    // HTTP는 TCP 위에서 동작
    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody UserRequest request) {
        // 클라이언트 ↔ 서버: TCP 연결
        // HTTP 요청/응답: TCP를 통해 전송
        User user = userService.create(request);
        return ResponseEntity.ok(user);
    }
}

5️⃣ 세션 계층 (Session Layer)

역할: 통신 세션 관리

Backend 개발자 관점:

@Controller
public class LoginController {

    @PostMapping("/login")
    public String login(@RequestParam String username,
                       @RequestParam String password,
                       HttpSession session) {  // 세션 계층

        if (authService.authenticate(username, password)) {
            // 세션 생성 및 유지
            session.setAttribute("user", username);
            session.setMaxInactiveInterval(1800);  // 30분
            return "redirect:/dashboard";
        }
        return "login";
    }

    @GetMapping("/dashboard")
    public String dashboard(HttpSession session) {
        // 세션 확인
        String user = (String) session.getAttribute("user");
        if (user == null) {
            return "redirect:/login";
        }
        return "dashboard";
    }

    @PostMapping("/logout")
    public String logout(HttpSession session) {
        // 세션 종료
        session.invalidate();
        return "redirect:/login";
    }
}

실무 예시:


6️⃣ 표현 계층 (Presentation Layer)

역할: 데이터 형식 변환, 암호화, 압축

Backend 개발자 관점:

// 1. 데이터 직렬화/역직렬화
@RestController
public class UserController {

    @PostMapping("/users")
    public ResponseEntity<User> createUser(
        @RequestBody User user  // JSON → Java Object (역직렬화)
    ) {
        User created = userService.create(user);
        return ResponseEntity.ok(created);  // Java Object → JSON (직렬화)
    }
}

// 2. 암호화
@Service
public class EncryptionService {

    private static final String ALGORITHM = "AES";

    public String encrypt(String data, SecretKey key) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encrypted = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encrypted);
    }

    public String decrypt(String encryptedData, SecretKey key) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decoded = Base64.getDecoder().decode(encryptedData);
        byte[] decrypted = cipher.doFinal(decoded);
        return new String(decrypted);
    }
}

// 3. 압축
@Service
public class CompressionService {

    public byte[] compress(String data) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (GZIPOutputStream gzipOS = new GZIPOutputStream(baos)) {
            gzipOS.write(data.getBytes(StandardCharsets.UTF_8));
        }
        return baos.toByteArray();
    }

    public String decompress(byte[] compressed) throws IOException {
        ByteArrayInputStream bais = new ByteArrayInputStream(compressed);
        try (GZIPInputStream gzipIS = new GZIPInputStream(bais);
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = gzipIS.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            return baos.toString(StandardCharsets.UTF_8);
        }
    }
}

7️⃣ 응용 계층 (Application Layer) ⭐⭐⭐

역할: 사용자 애플리케이션에 네트워크 서비스 제공

주요 프로토콜:

HTTP 프로토콜

@RestController
@RequestMapping("/api/products")
public class ProductController {

    private final ProductService productService;

    // GET 요청 (조회)
    @GetMapping("/{id}")
    public ResponseEntity<Product> getProduct(@PathVariable Long id) {
        Product product = productService.findById(id);
        return ResponseEntity.ok(product);
    }

    // POST 요청 (생성)
    @PostMapping
    public ResponseEntity<Product> createProduct(
        @RequestBody ProductRequest request
    ) {
        Product product = productService.create(request);
        return ResponseEntity
            .status(HttpStatus.CREATED)
            .body(product);
    }

    // PUT 요청 (수정)
    @PutMapping("/{id}")
    public ResponseEntity<Product> updateProduct(
        @PathVariable Long id,
        @RequestBody ProductRequest request
    ) {
        Product product = productService.update(id, request);
        return ResponseEntity.ok(product);
    }

    // DELETE 요청 (삭제)
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
        productService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

DNS 조회

@Service
public class DnsService {

    public String resolveHostname(String hostname) {
        try {
            InetAddress address = InetAddress.getByName(hostname);
            return address.getHostAddress();
        } catch (UnknownHostException e) {
            throw new RuntimeException("Cannot resolve: " + hostname, e);
        }
    }

    public List<String> getAllIpAddresses(String hostname) {
        try {
            InetAddress[] addresses = InetAddress.getAllByName(hostname);
            return Arrays.stream(addresses)
                .map(InetAddress::getHostAddress)
                .collect(Collectors.toList());
        } catch (UnknownHostException e) {
            throw new RuntimeException("Cannot resolve: " + hostname, e);
        }
    }
}

🌐 TCP/IP 프로토콜 스택 (인터넷 모델)

OSI 7계층 vs TCP/IP 4계층

OSI 7계층                TCP/IP 4계층
┌─────────────────┐
│  7. 응용 계층    │
├─────────────────┤      ┌─────────────────┐
│  6. 표현 계층    │      │  4. 응용 계층    │
├─────────────────┤  →   │  (Application)  │
│  5. 세션 계층    │      └─────────────────┘
├─────────────────┤      ┌─────────────────┐
│  4. 전송 계층    │  →   │  3. 전송 계층    │
├─────────────────┤      │  (Transport)    │
│  3. 네트워크 계층 │  →   └─────────────────┘
├─────────────────┤      ┌─────────────────┐
│  2. 데이터 링크  │  →   │  2. 인터넷 계층   │
├─────────────────┤      │  (Internet)     │
│  1. 물리 계층    │      └─────────────────┘
└─────────────────┘      ┌─────────────────┐
                         │  1. 네트워크     │
                         │    접근 계층      │
                         │  (Network Access)│
                         └─────────────────┘

실무에서 사용하는 모델

TCP/IP 4계층이 실무 표준!

응용 계층: HTTP, FTP, SMTP, DNS
전송 계층: TCP, UDP
인터넷 계층: IP, ICMP, ARP
네트워크 접근: Ethernet, Wi-Fi

🔧 데이터 전송 과정

캡슐화 (Encapsulation)

송신 측 (데이터 생성)
┌─────────────────────────────────────────┐
│ 7. 응용: Data                            │
├─────────────────────────────────────────┤
│ 4. 전송: TCP Header + Data               │ ← Segment
├─────────────────────────────────────────┤
│ 3. 네트워크: IP Header + Segment          │ ← Packet
├─────────────────────────────────────────┤
│ 2. 데이터 링크: Frame Header + Packet + CRC│ ← Frame
└─────────────────────────────────────────┘
          ↓
    전송 매체 (케이블, 무선)

역캡슐화 (Decapsulation)

수신 측 (데이터 수신)
┌─────────────────────────────────────────┐
│ 2. 데이터 링크: Frame 검증 및 헤더 제거   │
├─────────────────────────────────────────┤
│ 3. 네트워크: IP Header 확인 및 제거       │
├─────────────────────────────────────────┤
│ 4. 전송: TCP Header 확인 및 제거          │
├─────────────────────────────────────────┤
│ 7. 응용: Data 전달                       │
└─────────────────────────────────────────┘

실제 HTTP 요청 예시

7. 응용 계층
┌───────────────────────────────────┐
│ GET /api/users/1 HTTP/1.1         │
│ Host: example.com                 │
│ Accept: application/json          │
└───────────────────────────────────┘
          ↓
4. 전송 계층 (TCP)
┌───────────────────────────────────┐
│ TCP Header (Port: 80)             │
│ + HTTP Request                    │
└───────────────────────────────────┘
          ↓
3. 네트워크 계층 (IP)
┌───────────────────────────────────┐
│ IP Header (Dest: 93.184.216.34)  │
│ + TCP Segment                     │
└───────────────────────────────────┘
          ↓
2. 데이터 링크 계층 (Ethernet)
┌───────────────────────────────────┐
│ Ethernet Header (MAC Address)    │
│ + IP Packet                       │
│ + CRC                             │
└───────────────────────────────────┘

🛠️ 실무 디버깅 & 트러블슈팅

계층별 문제 진단

계층문제 증상확인 방법해결 방법
7. 응용404, 500 에러로그 확인, Postman코드 수정
4. 전송타임아웃netstat, ss방화벽, 포트 확인
3. 네트워크연결 안 됨ping, traceroute라우팅 확인
2. 데이터 링크네트워크 느림arp -a스위치, 케이블 점검
1. 물리연결 끊김케이블 확인케이블 교체

유용한 명령어

# 1. 네트워크 연결 확인 (계층 3)
ping google.com

# 2. 라우팅 경로 확인 (계층 3)
traceroute google.com

# 3. 포트 열림 확인 (계층 4)
telnet example.com 80
nc -zv example.com 80

# 4. 연결된 소켓 확인 (계층 4)
netstat -an | grep ESTABLISHED
ss -tuln

# 5. DNS 조회 (계층 7)
nslookup google.com
dig google.com

# 6. HTTP 요청 테스트 (계층 7)
curl -v https://api.example.com/users

Spring Boot 로깅

# application.yml
logging:
  level:
    org.springframework.web: DEBUG
    org.apache.http: DEBUG
    org.apache.http.wire: DEBUG
@Slf4j
@RestController
public class ApiController {

    @GetMapping("/test")
    public String test(HttpServletRequest request) {
        // 요청 정보 로깅 (계층 7)
        log.info("Method: {}", request.getMethod());
        log.info("URI: {}", request.getRequestURI());
        log.info("Remote IP: {}", request.getRemoteAddr());
        log.info("Remote Port: {}", request.getRemotePort());

        return "OK";
    }
}

🎯 실무 시나리오

시나리오 1: HTTP 요청 전체 과정

사용자: https://api.example.com/users/1 접속

1. DNS 조회 (계층 7)
   - api.example.com → 93.184.216.34

2. TCP 연결 (계층 4)
   - 3-Way Handshake
   - 클라이언트 포트: 54321
   - 서버 포트: 443 (HTTPS)

3. TLS 핸드셰이크 (계층 6)
   - 인증서 검증
   - 암호화 키 교환

4. HTTP 요청 전송 (계층 7)
   GET /users/1 HTTP/1.1
   Host: api.example.com

5. 라우팅 (계층 3)
   - 클라이언트 → 라우터 → 인터넷 → 서버

6. 서버 처리
   - Controller → Service → Repository → DB
   - 응답 생성

7. HTTP 응답 수신 (계층 7)
   HTTP/1.1 200 OK
   Content-Type: application/json
   {"id": 1, "name": "홍길동"}

8. TCP 연결 종료 (계층 4)
   - 4-Way Handshake

시나리오 2: 타임아웃 문제 해결

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        // 계층 4: TCP 타임아웃 설정
        HttpComponentsClientHttpRequestFactory factory =
            new HttpComponentsClientHttpRequestFactory();

        factory.setConnectTimeout(5000);     // 연결 타임아웃: 5초
        factory.setReadTimeout(10000);       // 읽기 타임아웃: 10초

        return new RestTemplate(factory);
    }
}

@Service
@Slf4j
public class ExternalApiService {

    private final RestTemplate restTemplate;

    public UserResponse getUser(Long id) {
        String url = "https://api.example.com/users/" + id;

        try {
            // 계층 7: HTTP 요청
            return restTemplate.getForObject(url, UserResponse.class);

        } catch (ResourceAccessException e) {
            // 계층 4: 타임아웃 또는 연결 실패
            log.error("Connection timeout or refused: {}", url, e);
            throw new ExternalApiException("External API unavailable", e);

        } catch (HttpClientErrorException e) {
            // 계층 7: HTTP 4xx 에러
            log.error("Client error: {} - {}", e.getStatusCode(), url, e);
            throw new ExternalApiException("Invalid request", e);

        } catch (HttpServerErrorException e) {
            // 계층 7: HTTP 5xx 에러
            log.error("Server error: {} - {}", e.getStatusCode(), url, e);
            throw new ExternalApiException("Server error", e);
        }
    }
}

📚 핵심 요약

Backend 개발자가 중점적으로 알아야 할 계층

계층중요도이유
7. 응용⭐⭐⭐HTTP, REST API 설계
4. 전송⭐⭐⭐TCP/UDP, 소켓 프로그래밍
3. 네트워크⭐⭐IP 주소, 라우팅 이해
6, 5, 2, 1기본 개념만 이해

프로토콜 선택 가이드

신뢰성 필요 + 순서 보장 → TCP
  - HTTP, HTTPS, FTP, SMTP, SSH

속도 중요 + 손실 허용 → UDP
  - DNS, 스트리밍, 게임, VoIP

데이터 단위

7. 응용: Data (데이터)
4. 전송: Segment (세그먼트)
3. 네트워크: Packet (패킷)
2. 데이터 링크: Frame (프레임)
1. 물리: Bit (비트)

💡 실무 Best Practices

1️⃣ 타임아웃 설정

// ✅ 항상 타임아웃 설정
@Bean
public RestTemplate restTemplate() {
    SimpleClientHttpRequestFactory factory =
        new SimpleClientHttpRequestFactory();
    factory.setConnectTimeout(5000);
    factory.setReadTimeout(10000);
    return new RestTemplate(factory);
}

// ❌ 타임아웃 미설정 (무한 대기 가능)
@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

2️⃣ 재시도 로직

@Service
public class ResilientApiService {

    private final RestTemplate restTemplate;

    @Retryable(
        value = {ResourceAccessException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000)
    )
    public UserResponse getUser(Long id) {
        return restTemplate.getForObject(
            "https://api.example.com/users/" + id,
            UserResponse.class
        );
    }
}

3️⃣ 연결 풀 관리

@Configuration
public class HttpClientConfig {

    @Bean
    public HttpClient httpClient() {
        PoolingHttpClientConnectionManager connectionManager =
            new PoolingHttpClientConnectionManager();

        connectionManager.setMaxTotal(100);        // 최대 연결 수
        connectionManager.setDefaultMaxPerRoute(20);  // 호스트당 최대 연결

        return HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();
    }
}

🚀 마무리

"OSI 7계층 모델은 네트워크의 언어입니다. 각 계층을 이해하면 문제 해결이 쉬워집니다."

Backend 개발자라면:

계층 모델을 이해하면 네트워크 문제를 체계적으로 접근할 수 있습니다! 💪

← 목록으로 돌아가기