๐Ÿ–ฅ๏ธ Server Code (1) - Controller

์ดํ˜„์šฐยท2023๋…„ 12์›” 10์ผ

๋ชฉ์ 

  • ๊ฐ์ฒด์ง€ํ–ฅ์  ์„ค๊ณ„๋ฅผ ์ง€ํ–ฅํ•œ๋‹ค.
  • SpringBoot ๋ฅผ ๋ชจ๋ฐฉํ•˜์—ฌ, ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•œ๋‹ค.
  • ์†Œ์ผ“์„ ํ™œ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•œ๋‹ค.

Package ๊ตฌ์„ฑ


src ํŒจํ‚ค์ง€

์„œ๋ฒ„์˜ ๋ฉ”์ธ ํŒจํ‚ค์ง€

1. Main ํด๋ž˜์Šค

  • MainServer๋ฅผ ์ž‘๋™์‹œํ‚จ๋‹ค.

2. MainServer ํด๋ž˜์Šค

  • ์†Œ์ผ“ ์—ฐ๊ฒฐ ์š”์ฒญ์„ ๋Œ€๊ธฐํ•œ๋‹ค.
  • ์—ฐ๊ฒฐ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ServerThread ๋ฅผ Daemon Thread๋กœ ํ˜ธ์ถœํ•˜์—ฌ ๊ฐ ์†Œ์ผ“์„ ๊ด€๋ฆฌํ•˜๋ฉฐ,
    ๋‹ค์‹œ ์†Œ์ผ“ ์—ฐ๊ฒฐ ์š”์ฒญ ๋Œ€๊ธฐ ๋ชจ๋“œ๊ฐ€ ๋œ๋‹ค.
  • HashMap<Long, PrintWriter> ์ธ์Šคํ„ด์Šค๋ฅผ public static ํ•˜๊ฒŒ ์„ ์–ธํ•˜์—ฌ
    userId: Long, ์—ฐ๊ฒฐ๋œ ์†Œ์ผ“์˜ out: PrintWriter๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.
HashMap<Long, PrintWriter> onlineUser; // userId: Key, out: Value ๋กœ ๊ด€๋ฆฌ

Socket client = new ServerSocket(8000).accept(); // ์†Œ์ผ“ ์—ฐ๊ฒฐ ํ–ˆ์„ ๋•Œ (ํด๋ผ์ด์–ธํŠธ ์ ‘์†)
out = new PrintWriter(client.getOutputStream(), true, StandardCharsets.UTF_8);

userId = login(User body).getUserId(); // DB์—์„œ ์œ ์ €์ •๋ณด ๊ฐ€์ ธ์˜ฌ ๋•Œ (๋กœ๊ทธ์ธ)

onlineUser.put(userId, out);

3. ServerThread ํด๋ž˜์Šค

  • ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์‹œ, ์†Œ์ผ“์„ ํ• ๋‹น ๋ฐ›๊ณ  ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ์„ ๋Š์„ ๋•Œ๊นŒ์ง€ ํ†ต์‹ ์„ ๊ด€์žฅํ•œ๋‹ค.
  • ์—ฐ๊ฒฐ๋œ ์†Œ์ผ“์˜ ip / BufferedReader / PrintWriter ๋ฅผ ๊ด€๋ฆฌํ•˜์—ฌ ํ†ต์‹ ํ•œ๋‹ค.
  • Request / Response ๋ฌธ์ž์—ด์„ ๋„˜๊ธฐ๊ธฐ๋งŒ ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
    • ํ†ต์‹ ์— ๋Œ€ํ•œ ๋‹จ์ผ ์ฑ…์ž„๋งŒ์„ ๊ฐ–๋Š”๋‹ค.
  • Request๋Š” ProxyController / Response๋Š” CustomResponse ๋กœ ๋ณด๋‚ธ๋‹ค.

Controller ํŒจํ‚ค์ง€

  • ํ”„๋กœํ† ์ฝœ Header String์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • Singleton Pattern / DI ๋ฅผ ์ ์šฉํ•˜์˜€๋‹ค.

1. DefalutController ์ธํ„ฐํŽ˜์ด์Šค

  • ๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ์˜ ์ตœ์ƒ์œ„ ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.
  • void callService ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•ด, ๊ตฌํ˜„์„ ๊ฐ•์ œํ•œ๋‹ค.
package main.src.Controller;
    
public interface DefaultController {
    void callService(String header, String body, PrintWriter out);
}

2. ProxyController ํด๋ž˜์Šค (์ค‘์š”)

  • ProxyPattern์„ ์ ์šฉํ•˜์—ฌ path ๋ณ„๋กœ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ์ด๋‹ค.

    • Request ๋ฌธ์ž์—ด์„ ํ•ด์„ํ•˜์—ฌ ๋Ÿฐํƒ€์ž„ ์‹œ, Header ์˜ path๊ฐ€ Controller ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.
  • ์˜ˆ์‹œ

  • ์ ์šฉ
  • ProxyController์—์„œ ๋ชจ๋“  Controller ์ธ์Šคํ„ด์Šค๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.
  • Controller ์ธ์Šคํ„ด์Šค๋ฅผ ์ง€์ •ํ•œ ํ›„, ๊ฐ Controller ์˜ callService ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
package main.src.Controller;

public class ProxyController implements DefaultController {
    DefaultController controller;
    /**
     * request[0] (header) == "POST /user"
     * request[1] (body) == "username:username1,password:password1,nickname:nickname1"
     */

    @Override
    public void callService(String header, String body) {
        switch (header.split(" ")[1]) { // path
            case "/user":
                controller = UserController.getInstance();
                break;
            case "/room":
                controller = RoomController.getInstance();
                break;
            case "/chat":
                controller = ChatController.getInstance();
                break;
            default: ; // ์ž˜๋ชป๋œ ์š”์ฒญ
        }
        controller.callService(header.split(" ")[0], body);
    }
}

3. UserController ํด๋ž˜์Šค

  • ํšŒ์›๊ด€๋ฆฌ ๊ธฐ๋Šฅ ์š”์ฒญ๋งŒ ์ฒ˜๋ฆฌํ•œ๋‹ค. path == โ€œ/userโ€
  • Header ์˜ ์š”์ฒญ ๋ฉ”์„œ๋“œ๋กœ ๊ธฐ๋Šฅ์„ ๊ตฌ๋ถ„ํ•œ๋‹ค.
    • ํšŒ์›๊ฐ€์ž…(POST) / ๋กœ๊ทธ์ธ(GET) / ๋กœ๊ทธ์•„์›ƒ(PATCH)
  • Singleton pattern ์œผ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค.
package main.src.Controller;

import main.src.Service.UserService;

public class UserController implements DefaultController {
    private static UserController instance = new UserController();

    private UserController() {}

    public static UserController getInstance() {
        return instance;
    }
    UserService userService = UserService.getInstance();

    @Override
    public void callService(String header, String body) {
        switch (header) {
            case "GET": userService.login(body); break;
            case "POST": userService.signUp(body); break;
            case "PATCH": userService.logout(body); break;
            default: userService.methodError();
        }
    }
}

4. RoomController ํด๋ž˜์Šค

  • ์ฑ„ํŒ…๋ฐฉ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ ์š”์ฒญ๋งŒ ์ฒ˜๋ฆฌํ•œ๋‹ค. path == โ€œ/roomโ€
  • Header ์˜ ์š”์ฒญ ๋ฉ”์„œ๋“œ๋กœ ๊ธฐ๋Šฅ์„ ๊ตฌ๋ถ„ํ•œ๋‹ค.
    • ์ฑ„ํŒ…๋ฐฉ ๋ชฉ๋ก ์กฐํšŒ(GET) / ์ฑ„ํŒ…๋ฐฉ ์ƒ์„ฑ(POST) / ์ฑ„ํŒ…๋ฐฉ ์ดˆ๋Œ€(PATCH) / ์ฑ„ํŒ…๋ฐฉ ๋‚˜๊ฐ€๊ธฐ(DELETE)
  • UserController ์™€ ๊ตฌ์„ฑ์ด ๋™์ผํ•˜๋‹ค.

5. ChatController ํด๋ž˜์Šค

  • ์ฑ„ํŒ… ๊ด€๋ฆฌ ๊ธฐ๋Šฅ ์š”์ฒญ๋งŒ ์ฒ˜๋ฆฌํ•œ๋‹ค. path == โ€œ/chatโ€
  • Header ์˜ ์š”์ฒญ ๋ฉ”์„œ๋“œ๋กœ ๊ธฐ๋Šฅ์„ ๊ตฌ๋ถ„ํ•œ๋‹ค.
    • ์ฑ„ํŒ… ๋ชฉ๋ก ์กฐํšŒ(์ฑ„ํŒ…๋ฐฉ ํ•˜๋‚˜๋ฅผ ์„ ํƒ)(GET) / ์ฑ„ํŒ… ์ „์†ก(POST)
  • UserController ์™€ ๊ตฌ์„ฑ์ด ๋™์ผํ•˜๋‹ค.

ChatProgram

profile
Back-End ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€