Android에서의 소켓 통신 기술 적용 가이드

소켓 통신의 기본 개념과 구현 원리

Android 애플리케이션 개발에서 네트워크 통신은 핵심 요소로, 데이터 전송 및 수신을 담당하는 소켓 기술은 다양한 서비스에 필수적입니다. 이 문서에서는 소켓 통신의 기본 원리부터 실용적인 코드 예제까지 단계별로 설명하며, 안정적인 연결 구조를 설계하는 데 필요한 핵심 지식을 제공합니다.

1. TCP와 UDP 기반 통신의 선택 기준

Android 환경에서 소켓 프로그래밍은 주로 java.net.Socket과 java.net.ServerSocket 클래스를 활용하여 수행됩니다. 이 두 클래스는 모두 전송 계층에서 작동하며, 각각 클라이언트와 서버 역할을 수행합니다.

  • TCP 기반 통신: 데이터 손실 없이 정확하게 전달되며, 연결 지향형으로 세션 관리가 가능합니다. 즉시 메시지 전달이 요구되는 채팅 앱, 파일 전송 등에 적합합니다.
  • UDP 기반 통신: 속도 우선이며, 패킷 손실을 허용합니다. 실시간 영상 스트리밍, 게임 내 위치 동기화 등에서 효과적입니다.

2. 서버-클라이언트 아키텍처의 구현 예제

다음은 간단한 텍스트 기반 대화 시스템을 구현하기 위한 서버 및 클라이언트 코드 예시입니다.

서버 측 구현 (Java)

public class EchoServer {
    private static final int PORT = 8080;
    private ServerSocket serverSocket;

    public void start() {
        try {
            serverSocket = new ServerSocket(PORT);
            System.out.println("서버 시작: 포트 " + PORT + " 대기 중...");

            while (true) {
                Socket client = serverSocket.accept();
                new ClientHandler(client).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class ClientHandler extends Thread {
        private final Socket clientSocket;

        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }

        @Override
        public void run() {
            try (
                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)
            ) {
                String message;
                while ((message = in.readLine()) != null) {
                    System.out.println("수신: " + message);
                    out.println("Echo: " + message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

클라이언트 측 구현 (Android Activity 기반)

public class SocketClientActivity extends AppCompatActivity {
    private EditText inputText;
    private TextView outputText;
    private Button sendButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        inputText = findViewById(R.id.input_text);
        outputText = findViewById(R.id.output_text);
        sendButton = findViewById(R.id.send_button);

        sendButton.setOnClickListener(v -> {
            new Thread(() -> {
                try (Socket socket = new Socket("192.168.1.100", 8080);
                     PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                     BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {

                    out.println(inputText.getText().toString());

                    String response = in.readLine();
                    runOnUiThread(() -> outputText.setText(response));

                } catch (IOException e) {
                    runOnUiThread(() -> outputText.setText("연결 실패: " + e.getMessage()));
                }
            }).start();
        });
    }
}

3. Android 권한 및 보안 설정

네트워크 통신을 위해 반드시 AndroidManifest.xml에 다음 권한을 추가해야 합니다:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

또한, API 23 이상에서는 실행 시 동적으로 권한 요청이 필요하므로, ActivityCompat.requestPermissions()를 사용해 처리해야 합니다.

4. 성능 최적화 및 오류 대응 전략

  • 스레드 풀 사용: 동시에 많은 클라이언트 연결을 처리할 경우, Executors.newFixedThreadPool(5) 등을 통해 스레드 리소스를 효율적으로 관리하세요.
  • 자동 재연결 로직: 네트워크 불안정 시 자동 재접속을 위한 백오프 전략(예: 1초 후 재시도, 최대 3회)을 구현하세요.
  • 자원 해제 보장: try-with-resources 문법을 사용해 InputStream, OutputStream, Socket 등의 자원을 자동으로 닫으세요.

5. 디버깅 및 테스트 방법

실제 장치 또는 에뮬레이터에서 테스트할 때는 다음과 같은 접근이 유용합니다:

  • Wireshark나 Charles Proxy를 이용해 실제 네트워크 패킷을 분석합니다.
  • Logcat을 통해 Log.d("Socket", "메시지 전송 완료")와 같은 디버그 메시지를 출력합니다.
  • 테스트용 서버로는 로컬 머신에서 실행하는 nc -l 8080 명령어도 활용 가능합니다.

태그: Android socket tcp UDP Network

10월 7일 12:57에 게시됨