TIL - day 61

정상화·2023년 5월 17일
0

TIL

목록 보기
41/46

알고리즘

양과 늑대

기존의 양과 늑대코드를 조금 리팩토링하였다.

import java.util.*;

class Solution {
    private static final int SHEEP = 0;

    public int solution(int[] info, int[][] edges) {
        Map<Integer, Node> nodes = getNodes(info);
        weave(edges, nodes);

        Node root = nodes.get(0);
        LinkedHashSet<Node> nexts = getNextVisitableNodesFrom(root, new LinkedHashSet<>());

        return getMaxSheepCount(root, nexts, 0, 0);
    }

    private Map<Integer, Node> getNodes(int[] info) {
        Map<Integer, Node> nodes = new HashMap<>();

        for (int i = 0; i < info.length; i++) {
            nodes.put(i, new Node(i, info[i]));
        }

        return nodes;
    }

    private void weave(int[][] edges, Map<Integer, Node> nodes) {
        for (int[] edge : edges) {
            Node parent = nodes.get(edge[0]);
            Node child = nodes.get(edge[1]);

            parent.setChild(child);
        }
    }

    private int getMaxSheepCount(Node node, LinkedHashSet<Node> visitableNodes, int sheepCnt, int wolfCnt) {
        if (node.TYPE == SHEEP) {
            sheepCnt++;
        } else {
            wolfCnt++;
        }
        if (sheepCnt == wolfCnt) {
            return 0;
        }

        int maxSheepCount = sheepCnt;
        for (Node nextNode : visitableNodes) {
            LinkedHashSet<Node> visitableNodesAfterVisitNextNode = getNextVisitableNodesFrom(nextNode, visitableNodes);
            maxSheepCount = Math.max(maxSheepCount, getMaxSheepCount(nextNode, visitableNodesAfterVisitNextNode, sheepCnt, wolfCnt));
        }
        return maxSheepCount;
    }

    private LinkedHashSet<Node> getNextVisitableNodesFrom(Node from, LinkedHashSet<Node> oldVisitableNodes) {
        LinkedHashSet<Node> nextVisitableNodes = new LinkedHashSet<>(oldVisitableNodes);
        if (from.isNotRoot()) {
            nextVisitableNodes.remove(from);
        }
        if (from.left != null) {
            nextVisitableNodes.add(from.left);
        }
        if (from.right != null) {
            nextVisitableNodes.add(from.right);
        }
        return nextVisitableNodes;
    }

    class Node {
        final int NUMBER;
        final int TYPE;

        Node left;
        Node right;

        public Node(int NUMBER, int TYPE) {
            this.NUMBER = NUMBER;
            this.TYPE = TYPE;
        }

        public boolean isRoot() {
            return NUMBER == 0;
        }

        public boolean isNotRoot() {
            return !isRoot();
        }

        public void setChild(Node child){
            if (this.left == null) {
                this.left = child;
            } else {
                this.right = child;
            }
        }
    }
}

유사MVC

1. smart tomcat 플러그인 설치

2. 실행 구성 편집

3. 서블릿&JSP에 필요한 의존성

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'

    // https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api
    compileOnly group: 'jakarta.servlet', name: 'jakarta.servlet-api', version: '6.0.0'

    // https://mvnrepository.com/artifact/org.projectlombok/lombok
    compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.26'
    annotationProcessor 'org.projectlombok:lombok:1.18.26'
}

+) JSTL

  • jstl을 사용하려면 jstl 구현체와 api를 톰캣설치 파일에 넣어줘야한다.
  • 톰캣설치파일/libs
  • 프로젝트 의존성에 추가하는 것이 아님에 주의

RestAPI

로그인

rest api에선 세션을 갖지 않는다. 앞으로 인증은 클라이언트에게 JWT를 제공하는 방식으로 구현된다.

표현

rest api는 http 메서드와 url의 조합으로 요청의 행위를 표현하는 것이 권장된다.

예시

  • 게시글 목록: GET 도메인/articles
  • 게시글 수정: PATCH 도메인/article/1
  • 게시글 등록: POST 도메인/article
  • 게시글 삭제: DELETE 도메인/article/1

PATCH는 전체 데이터 수정, PUT은 데이터의 일부를 수정하는데에 주로 쓰인다.

rest api로 로그인

과정

  1. 사용자는 Post로그인 요청을 한다. 이 때 로그인 정보는 폼데이터가 아닌 요청바디에 정해진 형식으로 보내진다.

  2. 서버는 db에서 사용자를 검색하고 사용자 정보를 담은 jwt를 응답에 담아서 보낸다.

코드

컨트롤러

    @PostMapping("/login")
    public RsData<LoginResponse> login(@Valid @RequestBody LoginRequest loginRequest, HttpServletResponse resp) {
        String accessToken = memberService.getAccessToken(loginRequest.getUsername(),loginRequest.getPassword());

        resp.addHeader("Authentication", accessToken);
        return RsData.of(
                "S-1",
                "액세스 토큰이 생성되었습니다.",
                new LoginResponse(accessToken)
        );
    }

서비스

    public String getAccessToken(String username, String password) {
        Member member = findByUsername(username).orElse(null);

        if (member==null) {
            return null;
        }

        if (!passwordEncoder.matches(password, member.getPassword())) {
            return null;
        }

        return jwtProvider.genToken(member.toClaims(), 60 * 60 * 24 * 365);
    }
profile
백엔드 희망

0개의 댓글