| 아파치(apache)란?

세계에서 가장 많이 쓰는 웹 서버중 하나이며, 아파치 소프트웨어 재단에서 관리하는 HTTP 웹 서버이다.

Apache는 Apache재단에서 만든 HTTP서버로 워낙 다양한 추가기능에, 구축이 쉽다는 이유 때문에 많이 쓰고 있다. 대부분의 중소기업들은 무료이기 때문에 많이 쓰인다.

 

톰캣이란(Tomcat)?

톰캣은 아파치 소프트웨어 재단의 웹 어플리케이션 서버(와스)로서, 

자바 서블릿을 실행키고 JSP코드가 포함되어 있는 웹 페이지를 만들어준다. 

 

자바 서블랫과 JSP 규격의 '참조용 구현'으로 평가되고 있는 톰캣은, 개발자들의 개방적 협력 작업의 산물로 바이너리 버전과 소스코드 버전 둘 모두를 아파치 웹 사이트에서 얻을 수 있다. 

즉, 톰캣은 웹 서버에서 넘어온 동적인 페이지를 읽어들여 프로그램을 실행하고 그 결과를 다시 html로 재구성하여 아파치에게 되돌려 준다. 

톰캣은 자체적으로 보유하고 있는 내부 웹 서버와 함께 독립적으로 사용될 수도 있지만 아파치나 넷스케이프 엔터프라이즈 서버, IIS등 다른 웹서버와 함께 사용될 수도 있다. 톰캣을 실행시키기 위해서는 JRE 1.1이상에 부합되는 자바 런타임 환경이 필요하다.

 

| 아파치(웹서버)와 톰캣(와스)의 차이점. 

What is the deference between Aphache and Tomcat ?? (aka. 아파치 != 톰캣)  

  

그동안 아파치 톰캣이 곧 아파치인줄 알았는데(ㄷㄷ) 이 둘은 엄연히 다른것이라는 사실을 깨닫고 충격(...)을 받아서 명확히 정리하기 위한 글. 

 

Apache 아파치 =  Web Server 웹서버 

먼저 아파치는 SW단체 이름이고 우리가 흔히 알고있는 아파치 서버라는 것은 이곳에서 후원 지원하는 http Web Server를 지칭하는 말이다.

즉 아파치는 Web Server 중 하나인 것!! 하도 유명해서 아파치=웹서버 처럼 익히 알고있는 것일뿐 .. (ex. DB=oracle, mysql.. 처럼.)

 

*Web server: http 요청을 처리하는 웹서버.

 

Tomcat 톰캣 = WAS 와스 

톰캣은 흔히 와스 WAS(Web application Server) 라고 한다. 와스는 웹 서버와 서블릿 컨테이너의 결합으로 다양한 역할 수행하는 서버다. 같은 아파치(sw단체)에서 만든놈이기 때문에 아파치 톰캣이다.  요 이름때매 겁나헷갈리는것... ㅜㅜ 

클라이언트 요청을 받아 요청을 처리하고 다시 클라이언트에게 응답해주는 역할하는것이 서블릿 컨테이너이다. 

아파치와 웹 서버와의 차이의 핵심은 이 컨테이너 기능(웹서버 + 서블릿 )이 가능한가 / 불가능한가이다. 

 

 

 

 

 

정리.

| 웹서버 Web Server 

 

정적인 데이터 처리하는 서버.

단순 이미지나 html파일과 같은 리소스만을 제공하는 서버는 웹서버만 사용하여 빠르고 안정적이게 활용.

 

| 와스 WAS 

: 동적인 데이터 처리하는 서버.

 

DB로 연결되어 데이터를 주고받거나 자바등을 통해 데이터 조작이 필요한 경우에는 WAS를 활용.

 

server start 시 가장 먼저 읽어들이는 내용: Web.xml 

web.xml을 기반으로 서버가 돌아가기 위해 필요한 내용 읽어들인다.

https://gmlwjd9405.github.io/2018/10/27/webserver-vs-was.html

https://school.programmers.co.kr/learn/courses/30/lessons/49189#

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드 설명

정점, 간선이 주어진 입력 배열에서 인접리스트를 만들어서
BFS 로 가장 먼 거리를 구했다.
DFS와 BFS는 많이 풀면 풀수록 다양한 개념들이 많이 나온다.
다 이해했다고 생각하지말고 계속 여러번 반복해서 풀어봐야겠다.

import java.util.*;

class Solution {
    
    static int[] visited;
    static ArrayList<ArrayList<Integer>> al;
    
    public int solution(int n, int[][] edge) {
        int answer = 0;
        
        al = new ArrayList<>();
        visited = new int[n + 1];
        
        // 정점이 6개까지 있으므로 0~6으로 선언해야되는거 주의
        for(int i = 0; i <= n; i++)
            al.add(new ArrayList<Integer>());
        
        for(int i = 0; i < edge.length; i++){
            al.get(edge[i][0]).add(edge[i][1]);
            al.get(edge[i][1]).add(edge[i][0]);
        }
        
        BFS(1);
        
        Arrays.sort(visited);
        
        int max = visited[n];
        
        for(int i = 0; i <= n; i++){
            if(max == visited[i])
                answer++;
        }
        
        return answer;
    }
    
    public static void BFS(int V){
        Queue<Integer> qu = new LinkedList<>();
        
        qu.add(1);
        visited[1] = 1;
        
        while(!qu.isEmpty()){
            int cur = qu.poll();
            
            for(int next : al.get(cur)) {
                
                if(visited[next] == 0){
                    visited[next] = visited[cur] + 1;
                    qu.add(next);
                }
            }
        }
    }
}

https://school.programmers.co.kr/learn/courses/30/lessons/12941

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드 설명

최솟값을 만들기 위해서는 가장 큰수와 작은수를 곱해주어야 하기 때문에
문자열 A와 문자열 B를 오름차순, 내림차순으로 각각 정렬해서
같은 인덱스끼리 곱해주려고 했으나,,
Arrays.sort 함수의 내림차순 정렬이 기억이 나지않아서
편법으로 저렇게 처리했다.

자바 Int 내림차순 정렬은 이렇게 활용하면 된다. 기억하자.. ★

Integer[] arr3 = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Arrays.sort(arr3, Collections.reverseOrder());
import java.util.*;

class Solution {
    public int solution(int[] A, int[] B) {
        int answer = 0;

        Arrays.sort(A);
        Arrays.sort(B);

        for (int i = 0; i < A.length; i++) {
            answer += A[i] * B[B.length - i - 1];
        }

        return answer;
    }
}

https://school.programmers.co.kr/learn/courses/30/lessons/12939

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드 설명

1. 문자열을 split 함수로 분리
2. String 배열을 Integer 형 배열로 바꿔서 ArrayList에 추가
3. Collections.sort 함수를 활용해서 오름차순으로 정렬
4. ArrayList에서 첫번째 인덱스(최소값) , 마지막 인덱스(최대값)을 꺼내 StringBuilder에 append

import java.util.*;

class Solution {
    public String solution(String s) {
        ArrayList<Integer> al = new ArrayList<>();
        StringBuilder sb = new StringBuilder();
        
        String arr[] = s.split(" ");
        
        for(int i = 0; i < arr.length; i++){
            al.add(Integer.parseInt(arr[i]));
        }
        
        Collections.sort(al);
        
        sb = sb.append(al.get(0) + " ");
        sb = sb.append(al.get(al.size()-1));
        
        return sb.toString();
    }
}

https://school.programmers.co.kr/learn/courses/30/lessons/12981

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드 설명

끝말잇기 규칙을 체크해야 되는 로직을 구현해야한다.
1. 마지막 사람이 말한 단어에서 마지막 문자와 현재 사람이 말한 단어의 첫번째 문자가 일치하는지 (startsWith 함수,
마지막 단어를 순서대로 꺼내기 위해서 Stack을 활용)

2. 현재 말한 사람의 단어가 이전에 중복된 적이 있는지 (HashMap)
각각의 조건을 체크해 준 후 이상이 없으면 stack과 map에 각각 push, put 해주었고,
조건이 거짓 판별이 나면 몇번 째 사람인지와 몇바퀴 돌았는지 체크해서 각각 answer 배열에 넣어주었다.

import java.util.*;
class Solution {
    public int[] solution(int n, String[] words) {
        int[] answer = new int[2];

        HashMap<String, Integer> map = new HashMap<>();
        Stack<String> stack = new Stack<>();

        for (int i = 0; i < words.length; i++) {

            if (!stack.isEmpty()) {
                String last_word = stack.peek();
                if (words[i].startsWith(last_word.substring(last_word.length() - 1, last_word.length())) 
                        && !map.containsKey(words[i])) {
                    stack.push(words[i]);
                    map.put(words[i], i % n);
                } else {
                    answer[0] = i % n + 1;
                    answer[1] = i / n + 1;
                    break;
                }
            } else {
                stack.push(words[i]);
                map.put(words[i], i % n);
            }
        }
        
        return answer;
    }
}

https://school.programmers.co.kr/learn/courses/30/lessons/12909

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드 설명

Stack 을 활용할 수 있는 문제였다.
stack이 비어있는 것을 체크하고
')' 가 들어올때 '(' 가 없으면 break를 걸어
false 를 return 했다.

import java.util.*;

class Solution {
    boolean solution(String s) {
        boolean answer = true;

        Stack<Character> stack = new Stack<>();
        
        for(int i = 0; i < s.length(); i++){
            char ch = s.charAt(i);
            
            if(ch == '(') {
                stack.push('(');
            }
            else if(ch == ')'){
                if(!stack.isEmpty()){
                    if(stack.peek() == '('){
                        stack.pop();
                    }
                }
                else {
                    answer = false;
                    break;
                }                
            }
        }
        
        if(!stack.isEmpty())
            answer = false;
        
        return answer;
    }
}

https://school.programmers.co.kr/learn/courses/30/lessons/12951

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드 설명

문자열에서 첫번째 문자는 항상 대문자
두번째 문자는 항상 소문자
마지막은 공백 추가
이 로직 대로 StringBuilder 에 append 해주었고,

시간을 생각보다 소비했던건 테스트케이스 8번에서 "3people unFollowed me " 이런식으로
입력값 s 문자열에도 마지막 공백이 추가되어서 이런 경우를 따로 if문 처리해서 따로 sb.append(" ")
처리를 해주어야 했다.

class Solution {
    public String solution(String s) {
        String[] arr = s.split(" ");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            if (arr[i].length() == 0) {
                sb.append(" ");
            } else {
                sb = sb.append(arr[i].substring(0, 1).toUpperCase());
                sb = sb.append(arr[i].substring(1, arr[i].length()).toLowerCase());
                sb = sb.append(" ");
            }
        }

        sb.delete(sb.length() - 1, sb.length());

        if (s.substring(s.length() - 1, s.length()).equals(" ")) {
            sb.append(" ");
        }
        
        return sb.toString();
    }
}

코드 설명

문제 포인트는
1. 3개의 벽을 세울 수 있는 모든 경우의 수를 구해서 새롭게 복사한 COPY_MAP을 각각 만드는 것
여기서 세울 수 있는 경우의 수가 엄청 많은데 이를 하나하나 다 BFS를 돌려봐야 한다.
2. 1번에서 새운 MAP 에서 BFS 돌려서 안전거리의 영역을 카운트해서 그 안전거리의 최대값을 출력

DFS와 BFS 를 동시에 연습할수 있는 아주 좋은 문제였다.
 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {

    static int N, M;
    static int[][] map;
    static int[] dy = {1, 0, -1, 0};
    static int[] dx = {0, 1, 0, -1};
    static int ans = Integer.MIN_VALUE;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        map = new int[N][M];

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        DFS(0);

        System.out.println(ans);
    }

    public static void DFS(int cnt) {
        if (cnt == 3) {
            BFS();
            return;
        }

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] == 0) {
                    map[i][j] = 1;
                    DFS(cnt + 1);
                    map[i][j] = 0;
                }
            }
        }
    }

    public static void BFS() {
        // 벽을 새로 새울떄마다 배열 초기화
        int[][] copy_map = new int[N][M];

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                copy_map[i][j] = map[i][j];
            }
        }
        Queue<Node> qu = new LinkedList<>();

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (copy_map[i][j] == 2) {
                    qu.add(new Node(i, j));
                }
            }
        }

        while (!qu.isEmpty()) {
            Node curNode = qu.poll();

            for (int i = 0; i < 4; i++) {
                int ny = curNode.y + dy[i];
                int nx = curNode.x + dx[i];

                if (ny < 0 || nx < 0 || N <= ny || M <= nx) continue;

                if (copy_map[ny][nx] == 0) {
                    copy_map[ny][nx] = 2;
                    qu.add(new Node(ny, nx));
                }


            }

        }
        int cnt = 0;

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (copy_map[i][j] == 0) {
                    cnt++;
                }
            }
        }
        ans = Math.max(cnt, ans);
    }


    public static class Node {
        int y;
        int x;

        public Node(int y, int x) {
            this.y = y;
            this.x = x;
        }
    }

}

https://www.acmicpc.net/problem/14500

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

 

코드 설명

테트리스의 모양처럼 생긴 블록들이 알고보면 DFS의 방향대로 탐색할때의 모양이라는 것을 알아낼 수 있었다.
DFS를 visited배열을 true 해주면서 depth가 4일때까지 돌리고 빠져나오면서 visited 배열을 false 해주는 백트래킹 방식으로 구현하였다.

여기서 핵심인 부분은 'ㅏ,ㅗ,ㅜ,ㅓ' 에 대한 블록을 어떻게 처리해줄까였는데
나는 cnt == 2 일때 arr[ny][nx] 의 값을 더해준 뒤 다른 ny,nx가 아닌 다른 방향으로 DFS를 한번 더 돌려서
sum 값을 계산하였다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    static int N, M;
    static int[][] arr;
    static boolean[][] visited;
    static int[] dy = {1, -1, 0, 0};
    static int[] dx = {0, 0, 1, -1};
    static int ans = Integer.MIN_VALUE;

    public static void main(String[] agrs) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        arr = new int[N][M];
        visited = new boolean[N][M];

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                visited[i][j] = true;
                DFS(i, j, 0, 0);
                visited[i][j] = false;
            }
        }
        System.out.println(ans);
    }

    public static void DFS(int y, int x, int sum, int cnt) {
        if (cnt == 4) {
            ans = Math.max(sum, ans);
            return;
        }

        for (int i = 0; i < 4; i++) {
            int ny = y + dy[i];
            int nx = x + dx[i];

            if (ny < 0 || nx < 0 || N <= ny || M <= nx)
                continue;

            if (visited[ny][nx])
                continue;

            if (cnt == 2) {
                visited[ny][nx] = true;
                DFS(y, x, sum + arr[ny][nx], cnt + 1);
                visited[ny][nx] = false;
            }

            visited[ny][nx] = true;
            DFS(ny, nx, sum + arr[ny][nx], cnt + 1);
            visited[ny][nx] = false;
        }

    }
}

https://www.acmicpc.net/problem/15686

 

15686번: 치킨 배달

크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸

www.acmicpc.net

코드 설명

BFS로 모든 경로를 다 찾으려고 하면 당연히 시간초과가 나버린다.
집에서 치킨집의 조합의 경우의 수 만큼 거리를 백트래킹으로 구하여 그것의 최소값을 구하면 된다.
(이 아이디어를 생각해내는데 꽤 오래걸렸다..)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {
    static int N, M;
    static int[][] arr;
    static boolean[] visited;
    static ArrayList<Node> chickenList = new ArrayList<>();
    static ArrayList<Node> houseList = new ArrayList<>();
    static int answer = Integer.MAX_VALUE;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        arr = new int[N + 1][N + 1];


        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());

            for (int j = 0; j < N; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());

                if (arr[i][j] == 1)
                    houseList.add(new Node(i, j));

                if (arr[i][j] == 2)
                    chickenList.add(new Node(i, j));
            }
        }

        visited = new boolean[chickenList.size()];

        DFS(0, 0);
        System.out.println(answer);
    }

    public static void DFS(int idx, int cnt) {
        if (cnt == M) {

            int res = 0;

            for (int i = 0; i < houseList.size(); i++) {
                int sum = Integer.MAX_VALUE;
                for (int j = 0; j < chickenList.size(); j++) {
                    if (visited[j]) {
                        // 각 치킨집에서 집까지의 거리의 최소값
                        int distance = Math.abs(chickenList.get(j).y - houseList.get(i).y) + Math.abs(chickenList.get(j).x - houseList.get(i).x);
                        sum = Math.min(sum, distance);
                    }
                }
                res += sum;
            }
            answer = Math.min(answer, res);
            return;
        }

        for (int i = idx; i < chickenList.size(); i++) {
            visited[i] = true;
            DFS(i + 1, cnt + 1);
            visited[i] = false;
        }
    }

    public static class Node {
        int x;
        int y;

        public Node(int y, int x) {
            this.x = x;
            this.y = y;

        }
    }
}

+ Recent posts